Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using guice injection with actor throws null pointer

I'm getting null pointer exception on the field injection of a server which is started as an akka actor.

Schedular part:

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 class part:

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

}

I'm getting null for dataService. Please advice me on this.

Thanks.

like image 389
popcoder Avatar asked Jul 12 '13 10:07

popcoder


People also ask

Can Guice inject null?

Guice forbids null by default So if something tries to supply null for an object, Guice will refuse to inject it and throw a NULL_INJECTED_INTO_NON_NULLABLE ProvisionException error instead. If null is permissible by your class, you can annotate the field or parameter with @Nullable .

What is the point of Guice?

The main selling point of Guice (and Dagger) is that we don't have to manually create our dependencies anymore. The tooling will do that for us if we instrument our code with Guice's API. There are a few patterns for how to use Guice: Field Injection, Constructor Injection, and the Provider Pattern.


2 Answers

For anyone who needs this:

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

}

AND

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

Thats it...!!!

like image 115
popcoder Avatar answered Oct 14 '22 07:10

popcoder


You're getting the NullPointerException because Akka is instantiating your Retriever actor and not Guice. You need to get Guice to construct your instance and then pass that to Akka, IndirectActorProducer can help you achieve this, e.g.:

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

Note that produce() must create a new Actor instance each time it is invoked, it cannot return the same instance.

You can then get Akka to retrieve your actor through the RetrieverDependencyInjector, e.g.:

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

UPDATE

I thought about you comment further, you might be able to turn RetrieverDependencyInjector into a GenericDependencyInjector by providing the class of the Actor you want as a constructor parameter, that perhaps will allow you to do something like:

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

I haven't tried this, but it might give you a starting point.

like image 43
Jonathan Avatar answered Oct 14 '22 09:10

Jonathan