java dependency-injection guice akka actor

java - usando la inyección de guice con el actor lanza un puntero nulo



dependency-injection akka (3)

Obtengo una excepción de puntero nulo en la inyección de campo de un servidor que se inició como un actor Akka.

Parte schedular:

private ActorRef myActor = Akka.system().actorOf( new Props(Retreiver.class)); @Override public void onStart(Application app) { log.info("Starting schedular.....!"); Akka.system() .scheduler() .schedule(Duration.create(0, TimeUnit.MILLISECONDS), Duration.create(30, TimeUnit.MINUTES), myActor, "tick", Akka.system().dispatcher()); }

Parte de la clase Retreiver:

public class Retreiver extends UntypedActor { private Logger.ALogger log = Logger.of(Retreiver .class); @Inject private myDataService dataService; @Override public void onReceive(Object arg0) throws Exception { if (0 != dataService.getDataCount()) { .... .... .... }

}

Me estoy poniendo nulo para dataService. Por favor, avísenme sobre esto.

Gracias.


NullPointerException la NullPointerException porque Akka está creando instancias de tu actor Retriever y no de Guice. Es necesario que Guice construya su instancia y luego se la pase a Akka. IndirectActorProducer puede ayudarlo a lograr esto, por ejemplo:

class RetrieverDependencyInjector implements IndirectActorProducer { final Injector injector; public RetrieverDependencyInjector(Injector injector) { this.injector = injector; } @Override public Class<? extends Actor> actorClass() { return Retriever.class; } @Override public Retriever produce() { return injector.getInstance(Retriever.class); } }

Tenga en cuenta que produce() debe crear una nueva instancia Actor cada vez que se invoca, no puede devolver la misma instancia.

A continuación, puede obtener Akka para recuperar su actor a través de RetrieverDependencyInjector , por ejemplo:

ActorRef myActor = Akka.system().actorOf( Props.create(RetrieverDependencyInjector.class, injector) );

ACTUALIZAR

Pensé en ti comentar más, podrías convertir RetrieverDependencyInjector en un GenericDependencyInjector al proporcionar la clase del Actor que deseas como parámetro de constructor, que quizás te permita hacer algo como:

Props.create(GenericDependencyInjector.class, injector, Retriever.class)

No he intentado esto, pero podría darte un punto de partida.


Para cualquiera que necesite esto:

public class GuiceInjectedActor implements IndirectActorProducer { final Injector injector; final Class<? extends Actor> actorClass; public GuiceInjectedActor(Injector injector, Class<? extends Actor> actorClass) { this.injector = injector; this.actorClass = actorClass; } @Override public Class<? extends Actor> actorClass() { return actorClass; } @Override public Actor produce() { return injector.getInstance(actorClass); }

}

Y

Akka.system().actorOf(Props.create(GuiceInjectedActor.class, INJECTOR,Retreiver.class))

Eso es...!!!


Puede haber otras formas, por ejemplo, puede colocar un controlador de inyector estático en Boot o Some-Injector-Holder-class, e inyectar al crear el actor mediante el método heredado: preStart ()

public class Retreiver extends UntypedActor { private Logger.ALogger log = Logger.of(Retreiver .class); @Override public void preStart () { super.preStart (); Boot.injector.injectMembers (this); //Some-Injector-holder.injectMembers (this); } @Inject private myDataService dataService; @Override public void onReceive(Object arg0) throws Exception { if (0 != dataService.getDataCount()) { .... .... .... } }

y también, también puede inyectar el inyector en el proveedor de actor para inicializar al actor por el inyector en un alcance de UntypedActorFactory:

public class InjectingActorProvider implements Provider<ActorRef> { @Inject private Injector injector; @SuppressWarnings("serial") @Override public final ActorRef get() { Props props = new Props(new UntypedActorFactory() { @Override public Actor create() { return injector.getInstance(actorClass); } }); props = props.withRouter(...); props = props.withDispatcher(...); actor = system.actorOf(props, actorName); return actor; } }