Akka with Spring
- Actor를 만들때 필요한 의존성을 대표적인 Dependency Injection 프레임워크인 Spring를 이용하여 사용하는 방법에 대해 알아보자
- Spring Bean Cycle과 다르게 Akka Actor의 Life Cycle을 가지고 있는다.
Gradle
compile "org.springframework:spring-context:${spring.version}"
compile "com.typesafe.akka:akka-actor_2.11:${akka.version}"
Define Actor
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends UntypedActor {
@Autowired
private GreetingService greetingService;
@Override
public void onReceive(Object message) throws Throwable {
if (message instanceof Greet) {
String name = ((Greet) message).getName();
getSender().tell(greetingService.greet(name), getSelf());
} else {
unhandled(message);
}
}
public static class Greet {
private String name;
// standard constructors/getters
}
}
- Actor의 Life Cycle와 맞추기 위해 Bean의 SCOPE을 PROTOTYPE으로 설정을 한다.
- 다른 Scope으로 활용하는 경우에는 제대로 작동이 되지 않을수가 있다.
Actor Extension
public class SpringExtension
extends AbstractExtensionId<SpringExtension.SpringExt> {
public static final SpringExtension SPRING_EXTENSION_PROVIDER
= new SpringExtension();
@Override
public SpringExt createExtension(ExtendedActorSystem system) {
return new SpringExt();
}
public static class SpringExt implements Extension {
private volatile ApplicationContext applicationContext;
public void initialize(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public Props props(String actorBeanName) {
return Props.create(
SpringActorProducer.class, applicationContext, actorBeanName);
}
}
}
- extension을 반드시 Singleton을 구현이 되어야 한다.
- ActorSystem 하나당 ActorExtension이 하나가 나와야 된다.
SpringActorProducer
public class SpringActorProducer implements IndirectActorProducer {
private ApplicationContext applicationContext;
private String beanActorName;
public SpringActorProducer(ApplicationContext applicationContext,
String beanActorName) {
this.applicationContext = applicationContext;
this.beanActorName = beanActorName;
}
@Override
public Actor produce() {
return (Actor) applicationContext.getBean(beanActorName);
}
@Override
public Class<? extends Actor> actorClass() {
return (Class<? extends Actor>) applicationContext
.getType(beanActorName);
}
}
- DI를 위한 actor Producer를 정의를 한다.
- 직접 Actor를 생성하는 것이 간적접(indirect)를 생성을 란다. Actor 객체를 applicationContext를 통해 가지고 온다.
Confiugration
@Configuration
@ComponentScan
public class AppConfiguration {
@Autowired
private ApplicationContext applicationContext;
@Bean
public ActorSystem actorSystem() {
ActorSystem system = ActorSystem.create("akka-spring-demo");
SPRING_EXTENSION_PROVIDER.get(system)
.initialize(applicationContext);
return system;
}
}
Use
ActorRef greeter = system.actorOf(SPRING_EXTENSION_PROVIDER.get(system)
.props("greetingActor"), "greeter");
FiniteDuration duration = FiniteDuration.create(1, TimeUnit.SECONDS);
Timeout timeout = Timeout.durationToTimeout(duration);
Future<Object> result = ask(greeter, new Greet("John"), timeout);
Assert.assertEquals("Hello, John", Await.result(result, duration));
Reference
'Programing > Akka' 카테고리의 다른 글
Akka Actor Life Cycle (0) | 2018.10.21 |
---|---|
Akka Pulling Pattern (0) | 2018.10.13 |
Akka Actor 개발팁 (0) | 2018.09.18 |
Akka Distributed Publish Subscribe in Cluster #3. Configuration (0) | 2018.09.11 |
Akka Distributed Publish Subscribe in Cluster #2.Send (0) | 2018.09.11 |