5

I'm using Akka Persistence with Cluster Sharding. What is the proper way to provide dependencies into such PersistentActor-s?

As far as I understand, passing them as constructor arguments is not possible, as Cluster Sharding is creating these actors.

Using Spring/Guice/etc. is not idiomatic Scala (and possibly has other issues (?)).

Using an object to implement a singleton makes for cumbersome testing and seems bad style.

What is the proper way?

P.S. If you plan to suggest the Cake pattern, please provide sample code in this specific Akka Persistence Cluster Sharding context.

John M
  • 1,469
  • 17
  • 41
  • As I wrote - "Cluster Sharding is creating these actors" – John M Jan 29 '15 at 09:59
  • EDIT: http://stackoverflow.com/questions/26475491/akka-cluster-sharding-can-entry-actors-have-dynamic-props sorry, my thinking is fundamentally wrong here. – goral Jan 29 '15 at 10:04
  • Thanks for linking to this question, @goral, it is somewhat relevant (although doesn't seem to provide a solution). – John M Jan 29 '15 at 10:13
  • 1
    How about sending an init message containing the dependencies? It could also be sent by the actor to himself in the prestart. – Diego Martinoia Jan 29 '15 at 12:48
  • That's an interesting idea, but it seems quite cumbersome and would require the dependencies to be serializable. Also, the actor himself doesn't know his dependencies. He could send a "give me dependencies" message to an actor on some well-known address, which would return the dependencies. But then we might as well wrap all the dependencies as actors in the first place. – John M Jan 29 '15 at 13:38
  • Wait, if the actor does not know the dependencies, how can he use them? Also, using Guice for that requires some hacking (we did it) and it works, but you are going to have troubles if you want to use advanced features such as value classes (requires some reflection magic) – Diego Martinoia Jan 29 '15 at 17:12
  • He gets the dependencies injected or otherwise provided. But he doesn't know the specifics, only interfaces. – John M Jan 29 '15 at 19:34

1 Answers1

0

UPDATED VERSION: the solution I offered earlier did not allow to mock services of the actor under test in unit test cases.

I am using instead one solution offered on that article http://letitcrash.com/post/55958814293/akka-dependency-injection that is called "aspect weaving" and that consists of injecting the dependencies in the actor using aspect oriented programming. This solution can be used to inject Spring dependencies on any bean not controlled by Spring container (potentially useful for legacy code).

A full example is provided by the above article: https://github.com/huntc/akka-spring/blob/f137c98b621517301f636e6ea03519388fcd5fff/src/main/scala/org/typesafe/Akkaspring.scala

And to enable aspect weaving in a spring based application you should check the documentation on Spring doc In my case, on a jetty application server, it consists of using the spring agent and setting it in the jvm arguments.

As far as tests are concerned, I :

  • created setters for the injected services
  • created basic configuration for my actors with null beans referenced for my dependencies
  • instantiated the actor in my test case
  • replace the actor's services with mocks
  • run the actor's inner methods and check the results, actor's state or calls to dependencies

ORIGINAL:

I am using Akka in a Spring Application to enable clustering. At first it raises the following issue: you cannot inject spring managed dependencies in the actor constructor, as you said. (it tries to serialize the application context and fails)

So I created a class that holds the application context and provides a static method to retrieve beans I need. I retrieve the bean only if I need it, this way:

public void onReceive{
  if (message instanceof HandledMessage) {
    (MyService) SpringApplicationContext.getBean("myService");
    ...
  }
}

It's not conventional but it does the job, what do you think? Hope otherwise it might help another one.

Jeremie
  • 1,267
  • 12
  • 33
  • How do you approach testing? – John M Mar 10 '15 at 04:35
  • 1
    I thank you for your question, I shamefully had not approached isolation for testing yet. I came up with a new solution that allows me to inject a mock service in unit test cases. I found an advice on that page http://letitcrash.com/post/55958814293/akka-dependency-injection , and it consists of using aspect weaving for dependency injection. I am going to update my answer with my new solution. – Jeremie Mar 16 '15 at 12:09