Programing/Akka

Akka with Spring

BUST 2018. 9. 29. 13:04

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