+act #3873 Adding Props.create method with manifested type
The generated classes for Java 8 lambdas doesn't carry the type information that we need, so we need to pass in the return type of the Creator.
This commit is contained in:
parent
f1edf78979
commit
c432b3e2f0
3 changed files with 59 additions and 9 deletions
|
|
@ -54,19 +54,38 @@ public class ActorCreationTest {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class G implements Creator {
|
||||||
|
public Object create() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testErasedCreator() {
|
||||||
|
try {
|
||||||
|
Props.create(new G());
|
||||||
|
assert false;
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
assertEquals("erased Creator types are unsupported, use Props.create(actorClass, creator) instead", e.getMessage());
|
||||||
|
}
|
||||||
|
Props.create(UntypedActor.class, new G());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRightCreator() {
|
public void testRightCreator() {
|
||||||
final Props p = Props.create(new C());
|
final Props p = Props.create(new C());
|
||||||
assertEquals(UntypedActor.class, p.actorClass());
|
assertEquals(UntypedActor.class, p.actorClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTopLevelNonStaticCreator() {
|
public void testTopLevelNonStaticCreator() {
|
||||||
final Props p = Props.create(new NonStaticCreator());
|
final Props p = Props.create(new NonStaticCreator());
|
||||||
assertEquals(UntypedActor.class, p.actorClass());
|
assertEquals(UntypedActor.class, p.actorClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParametricCreator() {
|
public void testParametricCreator() {
|
||||||
final Props p = Props.create(new D<UntypedActor>());
|
final Props p = Props.create(new D<UntypedActor>());
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,27 @@ public class JavaAPI {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Props mkErasedProps() {
|
||||||
|
return Props.create(JavaAPITestActor.class, new Creator() {
|
||||||
|
public Object create() {
|
||||||
|
return new JavaAPITestActor();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mustBeAbleToCreateActorRefFromFactory() {
|
public void mustBeAbleToCreateActorRefFromFactory() {
|
||||||
ActorRef ref = system.actorOf(mkProps());
|
ActorRef ref = system.actorOf(mkProps());
|
||||||
assertNotNull(ref);
|
assertNotNull(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mustBeAbleToCreateActorRefFromErasedFactory() {
|
||||||
|
ActorRef ref = system.actorOf(mkErasedProps());
|
||||||
|
assertNotNull(ref);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mustBeAbleToCreateActorWIthConstructorParams() {
|
public void mustBeAbleToCreateActorWIthConstructorParams() {
|
||||||
ActorRef ref = system.actorOf(Props.create(ActorWithConstructorParams.class, "a", "b", new Integer(17), 18));
|
ActorRef ref = system.actorOf(Props.create(ActorWithConstructorParams.class, "a", "b", new Integer(17), 18));
|
||||||
|
|
|
||||||
|
|
@ -100,12 +100,19 @@ object Props {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new Props from the given [[akka.japi.Creator]].
|
* Create new Props from the given [[akka.japi.Creator]].
|
||||||
|
*
|
||||||
|
* You can not use a Java 8 lambda with this method since the generated classes
|
||||||
|
* don't carry enough type information.
|
||||||
|
*
|
||||||
|
* Use the Props.create(actorClass, creator) instead.
|
||||||
*/
|
*/
|
||||||
def create[T <: Actor](creator: Creator[T]): Props = {
|
def create[T <: Actor](creator: Creator[T]): Props = {
|
||||||
if ((creator.getClass.getEnclosingClass ne null) && (creator.getClass.getModifiers & Modifier.STATIC) == 0)
|
val cc = creator.getClass
|
||||||
|
if ((cc.getEnclosingClass ne null) && (cc.getModifiers & Modifier.STATIC) == 0)
|
||||||
throw new IllegalArgumentException("cannot use non-static local Creator to create actors; make it static (e.g. local to a static method) or top-level")
|
throw new IllegalArgumentException("cannot use non-static local Creator to create actors; make it static (e.g. local to a static method) or top-level")
|
||||||
val ac = classOf[Actor]
|
val ac = classOf[Actor]
|
||||||
val actorClass = Reflect.findMarker(creator.getClass, classOf[Creator[_]]) match {
|
val coc = classOf[Creator[_]]
|
||||||
|
val actorClass = Reflect.findMarker(cc, coc) match {
|
||||||
case t: ParameterizedType ⇒
|
case t: ParameterizedType ⇒
|
||||||
t.getActualTypeArguments.head match {
|
t.getActualTypeArguments.head match {
|
||||||
case c: Class[_] ⇒ c // since T <: Actor
|
case c: Class[_] ⇒ c // since T <: Actor
|
||||||
|
|
@ -113,9 +120,18 @@ object Props {
|
||||||
v.getBounds collectFirst { case c: Class[_] if ac.isAssignableFrom(c) && c != ac ⇒ c } getOrElse ac
|
v.getBounds collectFirst { case c: Class[_] if ac.isAssignableFrom(c) && c != ac ⇒ c } getOrElse ac
|
||||||
case x ⇒ throw new IllegalArgumentException(s"unsupported type found in Creator argument [$x]")
|
case x ⇒ throw new IllegalArgumentException(s"unsupported type found in Creator argument [$x]")
|
||||||
}
|
}
|
||||||
|
case c: Class[_] if (c == coc) ⇒
|
||||||
|
throw new IllegalArgumentException(s"erased Creator types are unsupported, use Props.create(actorClass, creator) instead")
|
||||||
}
|
}
|
||||||
apply(defaultDeploy, classOf[CreatorConsumer], actorClass :: creator :: Nil)
|
apply(defaultDeploy, classOf[CreatorConsumer], actorClass :: creator :: Nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new Props from the given [[akka.japi.Creator]] with the type set to the given actorClass.
|
||||||
|
*/
|
||||||
|
def create[T <: Actor](actorClass: Class[T], creator: Creator[T]): Props = {
|
||||||
|
apply(defaultDeploy, classOf[CreatorConsumer], actorClass :: creator :: Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue