Skip to content

Instantly share code, notes, and snippets.

@javajack
Created November 27, 2013 06:26
Show Gist options
  • Save javajack/7671468 to your computer and use it in GitHub Desktop.
Save javajack/7671468 to your computer and use it in GitHub Desktop.
http://blog.nemccarthy.me/?p=272 With Akka 2.2-RC1 coming out last night I decided to upgrade. There are a few changes that make DI with Akka in Java much easier. Previously (Akka 2.1) I was using the UntypedActorFactory approach, however in 2.2 this seems that these methods have been deprecated in favor of the Creator approach. Trying to dig ar…
@Component
@org.springframework.context.annotation.Scope("prototype")
public class EmailServiceActor extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
//Do actor stuff...
}
}
import akka.actor.Actor;
import akka.actor.IndirectActorProducer;
import email.ApplicationContextProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A class to create a new Actor Instance from a Spring Bean with PROTOTYPE scope
* Usage :
* akka.actorOf(Props.create(SpringConfiguredActor.class, EmailServiceActor.class, "myActor").withRouter(new SmallestMailboxRouter(3)), "myActorService");
* User: Nathan
*/
// Trick 1 – Getting a Bean from Spring App Context:
public class SpringConfiguredActor implements IndirectActorProducer {
private static final Logger LOG = LoggerFactory.getLogger(SpringDIActor.class);
private String beanId;
private Class<? extends Actor> type;
/**
* Get an Actor bean instance of bean #type with ID=#beanName
* @param type
* @param beanName
*/
public SpringConfiguredActor(Class<? extends Actor> type, String beanName) {
this.beanId = beanName;
this.type = type;
}
/**
* Get an instance bean of #type from the App Context - By Type wiring
* @param type
*/
public SpringConfiguredActor(Class<? extends Actor> type) {
this.type = type;
}
/**
* This factory method must produce a fresh actor instance upon each
* invocation. <b>It is not permitted to return the same instance more than
* once.</b>
*/
@Override
public Actor produce() {
if (beanId != null) {
//By Name wiring;
return (Actor) ApplicationContextProvider.getApplicationContext().getBean(beanId);
}
//By Type wiring;
return (Actor) ApplicationContextProvider.getApplicationContext().getBean(type);
}
/**
* This method is used by [[Props]] to determine the type of actor which will
* be created. This means that an instance of this `IndirectActorProducer`
* will be created in order to call this method during any call to
* [[Props#actorClass]]; it should be noted that such calls may
* performed during actor set-up before the actual actor’s instantiation, and
* that the instance created for calling `actorClass` is not necessarily reused
* later to produce the actor.
*/
@Override
public Class<? extends Actor> actorClass() {
return type;
}
}
import akka.actor.Actor;
import akka.actor.IndirectActorProducer;
import email.ApplicationContextProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Create a new instance of the Actor and then autowire its fields by passing it to the Spring App Context
* //Expanded this to take an instance and just autowire it.
Usage:
akka.actorOf(Props.create(SpringDIActor.class, MyActor.class)
.withRouter(new SmallestMailboxRouter(3)), "myActorService");
You can create a Spring wired actor from within another actor (in fact you should to take advantage of akka’s actor hierarchies). To do this from within an actor its the same call;
e.g. in MyActor class you could have;
private ActorRef mySubWorker = getContext().actorOf(Props.create(SpringConfiguredActor.class, MyActor.class, "myNestedActor")
.withRouter(new SmallestMailboxRouter(3)), "myNestedActorService");
* User: Nathan
*/
// Trick 2 – Manually create the instance and autowire it by passing it to the Spring Application Context
public class SpringDIActor implements IndirectActorProducer {
private static final Logger LOG = LoggerFactory.getLogger(SpringDIActor.class);
private Class<? extends Actor> type;
private Actor actorInstance = null;
public SpringDIActor(Class<? extends Actor> type) {
this.type = type;
}
public SpringDIActor(Actor actorInstance) {
this.actorInstance = actorInstance;
}
/**
* This factory method must produce a fresh actor instance upon each
* invocation. <b>It is not permitted to return the same instance more than
* once.</b>
*/
@Override
public Actor produce() {
Actor newActor = actorInstance;
actorInstance = null;
if (newActor == null) {
try {
newActor = type.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
LOG.error("Unable to create actor of type:{}", type, e);
}
}
ApplicationContextProvider.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(newActor);
return newActor;
}
/**
* This method is used by [[Props]] to determine the type of actor which will
* be created. This means that an instance of this `IndirectActorProducer`
* will be created in order to call this method during any call to
* [[Props#actorClass]]; it should be noted that such calls may
* performed during actor set-up before the actual actor’s instantiation, and
* that the instance created for calling `actorClass` is not necessarily reused
* later to produce the actor.
*/
@Override
public Class<? extends Actor> actorClass() {
return type;
// ParameterizedType parameterizedType = (ParameterizedType)getClass().getGenericSuperclass();
// return (Class) parameterizedType.getActualTypeArguments()[0];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment