2013-07-12 12 views
6

Otrzymuję wyjątek wskaźnik null na wtrysku pola serwera, który jest uruchamiany jako aktor akka.za pomocą wtrysku guice z aktorem rzuca zerowy wskaźnik

cedularne część:

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()); 

} 

Retreiver klasa część:

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()) { 
    .... 
    .... 
    .... 
    } 

}

Dostaję null dla dataService. Proszę, powiedz mi o tym.

Dzięki.

+0

Zauważ, że nie mam żadnych wiąże do tego. Oczekuję, że GUice wstrzyknie usługę danych, gdy klasa Retreiver zostanie utworzona jako aktor. – popcoder

Odpowiedz

7

Dostajesz NullPointerException, ponieważ Akka tworzy swojego aktora, a nie Guice. Musisz dostać Guice do skonstruowania instancji, a następnie przekazać, że do Akka, IndirectActorProducer może pomóc osiągnąć ten cel, na przykład:

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); 
    } 
} 

Zauważ, że produce()musi utworzyć nowy Actor instancji przy każdym wywołaniu, nie może zwrócić tej samej instancji.

Następnie można dostać Akka odzyskać swoją aktora przez RetrieverDependencyInjector, np:

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

UPDATE

myślałem o tobie dalszych komentarzy, możesz być w stanie włączyć RetrieverDependencyInjector do GenericDependencyInjector dostarczając klasę Actor, którą chcesz jako parametr konstruktora, który prawdopodobnie pozwoli ci zrobić coś takiego:

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

Nie próbowałem tego, ale może to dać punkt wyjścia.

+0

Jonathan, dzięki za odpowiedź. Mam wielu nieopisanych aktorów. Potrzebuję więc generycznego iniektora zaleŜności, aby móc odzyskać aktorów. Jak mogę to zrobić? – popcoder

+1

@popprem Pomyślałem, zobacz moją zaktualizowaną odpowiedź. – Jonathan

+0

Dzięki Jonathan, to jest pomocne. – popcoder

8

Dla każdego, kto tego potrzebuje:

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); 
} 

}

I

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

to wszystko ... !!!

+0

Jak można tego użyć wraz z wtryskiem dostawcy? Normalnie w moim GuiceModule Mam funkcję tak: '@Provides @Named ("somename") ActorRef getSomeActor() {return Akka.System () ... }' Problemem jest to, że nie mam dostęp do wtryskiwacza z wnętrza GuiceModule. –

+0

@Chanan 'wtryskiwacza może być także wstrzykiwane do modułu, jak to: @Provides @Singleton @Named ("jcrActor") ActorSelection jcrActor (system końcowy ActorSystem, końcowe wtryskiwacz wtryskiwacz) throws Exception {systemu . actorOf (nowy RoundRobinPool (3) .props (Props.create (GuiceInjectedActor.class, injector, JcrActor.class)), "jcrActorRouter"); return system.actorSelection (ActorConstants.PATH_JCR_ACTOR_ROUTER); } ' – rwijngaa

2

Nie może być inne sposoby, na przykład, można umieścić statyczny uchwyt wtryskiwacza w Boot lub niektórych-Injector posiadacz klasy i wstrzyknąć podczas tworzenia aktora przez wywołanie odziedziczoną metodę: 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()) { 
     .... 
     .... 
     .... 
     } 
    } 

a także można również wstrzykiwać wtryskiwacz w celu zainicjowania dostawcy aktor aktor przez wtryskiwacz w zakresie 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; 
    } 
} 
+0

Jak wstrzyknąć wtryskiwacz? – mor

+0

Wtryskiwacz jest dostarczany przez Guice, nie trzeba go wstrzykiwać. –

Powiązane problemy