简体   繁体   中英

Akka - How can an actor get a reference to a web service

I have the following basic setup:

public static void main(...) {
  final MyWebServiceClient client = new MyWebServiceClient(...,....,....);
  ...
  final ActorRef master = system.actorOf(Props.create(Level1Actor.class), "level1");
  master.tell(new Level1Message()...);
}

Level1Actor.onRecieve() creates several Level2Actors:

...
getContext().actorOf(Props.create(Level2Actor.class)).tell(new Level2Message(), getSelf());
...

and similarly Level2Actor.onReceive creates several Level3Actors

Here's my question: In Level3Actor.onRecieve() I want to use the web service client I created in my main method, something like:

public void onReceive() {
...
EmailSummary summary = client.getEmailSummary(username, password, etc, etc);
//create and send a response to sender based on 'summary'
...
}

How do I achieve this? Ideally I want to configure my web service at startup (urls etc) and then access it several layers of Actor deep?

Is there a way in my main method to register some factory that is called whenever an actor is created? like:

system.register(Level3Actor.class, myFactoryWithReferenceToWebService);

? Or from a Spring point of view my web service would be a bean and just be autowired into the Level3Actor instances?

Thanks.

Use an Extension . They are a nice way to provide "global" stuff to actors:

public class MyWebServiceExtension extends
  AbstractExtensionId<MyWebServiceExtension.MyWebServiceExt> {

  public static MyWebServiceExtension MyWebServiceExtProvider = 
    new MyWebServiceExtension();

  public MyWebServiceExt createExtension(ExtendedActorSystem system) {
    return new MyWebServiceExt();
  }

  public static class MyWebServiceExt implements Extension {
    private final MyWebServiceClient client = new MyWebServiceClient();

    public MyWebServiceClient getClient() { return client; }
  }
}

Then in your actor:

import static com.foo.MyWebServiceExtension.MyWebServiceExtProvider;

public class MyUntypedActor extends UntypedActor {
  final MyWebServiceClient client =
    MyWebServiceExtProvider.get(getContext().system()).getClient();

Or if you are using Spring you can use the IndirectActorProducer and let Spring DI your dependencies into your actors. See this project for an example.

Two possible solutions are:

  1. Define the webservice ref as a property of your message classes ( Level1Message , Level2Message , etc..) and propagate it down the chain via message passing.
  2. Define your actors that need the webservice as having a constructor that accepts the webservice as an arg. Then, when creating those actors, use the Props.create that accepts constructor args like so:

     getContext().actorOf(Props.create(Level2Actor.class, client)) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM