From ffcd83697ab050e7550daf4be35ccf2ba49a6625 Mon Sep 17 00:00:00 2001 From: Sergey Petunin Date: Thu, 28 Jul 2016 21:22:08 +0600 Subject: [PATCH] Source code for the article "An Intro to Spring with Akka" (#541) --- spring-all/pom.xml | 13 +++-- .../org/baeldung/akka/AppConfiguration.java | 26 ++++++++++ .../java/org/baeldung/akka/GreetingActor.java | 43 +++++++++++++++++ .../org/baeldung/akka/GreetingService.java | 12 +++++ .../baeldung/akka/SpringActorProducer.java | 28 +++++++++++ .../org/baeldung/akka/SpringExtension.java | 33 +++++++++++++ .../org/baeldung/akka/SpringAkkaTest.java | 48 +++++++++++++++++++ 7 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 spring-all/src/main/java/org/baeldung/akka/AppConfiguration.java create mode 100644 spring-all/src/main/java/org/baeldung/akka/GreetingActor.java create mode 100644 spring-all/src/main/java/org/baeldung/akka/GreetingService.java create mode 100644 spring-all/src/main/java/org/baeldung/akka/SpringActorProducer.java create mode 100644 spring-all/src/main/java/org/baeldung/akka/SpringExtension.java create mode 100644 spring-all/src/test/java/org/baeldung/akka/SpringAkkaTest.java diff --git a/spring-all/pom.xml b/spring-all/pom.xml index d014b35e95..b7a8fcc79e 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -45,11 +45,6 @@ spring-aspects - - org.springframework - spring-orm - - @@ -92,6 +87,14 @@ runtime + + + + com.typesafe.akka + akka-actor_2.11 + 2.4.8 + + diff --git a/spring-all/src/main/java/org/baeldung/akka/AppConfiguration.java b/spring-all/src/main/java/org/baeldung/akka/AppConfiguration.java new file mode 100644 index 0000000000..9211ae0fdb --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/akka/AppConfiguration.java @@ -0,0 +1,26 @@ +package org.baeldung.akka; + +import akka.actor.ActorSystem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import static org.baeldung.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; + +@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; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/akka/GreetingActor.java b/spring-all/src/main/java/org/baeldung/akka/GreetingActor.java new file mode 100644 index 0000000000..1a9386c769 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/akka/GreetingActor.java @@ -0,0 +1,43 @@ +package org.baeldung.akka; + +import akka.actor.UntypedActor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; + +@Component +@Scope(SCOPE_PROTOTYPE) +public class GreetingActor extends UntypedActor { + + private GreetingService greetingService; + + public GreetingActor(GreetingService greetingService) { + this.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; + + public Greet(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + } + +} diff --git a/spring-all/src/main/java/org/baeldung/akka/GreetingService.java b/spring-all/src/main/java/org/baeldung/akka/GreetingService.java new file mode 100644 index 0000000000..801921887d --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/akka/GreetingService.java @@ -0,0 +1,12 @@ +package org.baeldung.akka; + +import org.springframework.stereotype.Component; + +@Component +public class GreetingService { + + public String greet(String name) { + return "Hello, " + name; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/akka/SpringActorProducer.java b/spring-all/src/main/java/org/baeldung/akka/SpringActorProducer.java new file mode 100644 index 0000000000..20813ab60a --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/akka/SpringActorProducer.java @@ -0,0 +1,28 @@ +package org.baeldung.akka; + +import akka.actor.Actor; +import akka.actor.IndirectActorProducer; +import org.springframework.context.ApplicationContext; + +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 actorClass() { + return (Class) applicationContext.getType(beanActorName); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/akka/SpringExtension.java b/spring-all/src/main/java/org/baeldung/akka/SpringExtension.java new file mode 100644 index 0000000000..624e289812 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/akka/SpringExtension.java @@ -0,0 +1,33 @@ +package org.baeldung.akka; + +import akka.actor.AbstractExtensionId; +import akka.actor.ExtendedActorSystem; +import akka.actor.Extension; +import akka.actor.Props; +import org.springframework.context.ApplicationContext; + +public class SpringExtension extends AbstractExtensionId { + + 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); + } + + } + + +} diff --git a/spring-all/src/test/java/org/baeldung/akka/SpringAkkaTest.java b/spring-all/src/test/java/org/baeldung/akka/SpringAkkaTest.java new file mode 100644 index 0000000000..6162b02307 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/akka/SpringAkkaTest.java @@ -0,0 +1,48 @@ +package org.baeldung.akka; + +import java.util.concurrent.TimeUnit; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.util.Timeout; +import org.baeldung.akka.GreetingActor.Greet; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; + +import static akka.pattern.Patterns.ask; +import static org.baeldung.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; + +@ContextConfiguration(classes = AppConfiguration.class) +public class SpringAkkaTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private ActorSystem system; + + @Test + public void whenCallingGreetingActor_thenActorGreetsTheCaller() throws Exception { + 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 result = ask(greeter, new Greet("John"), timeout); + + Assert.assertEquals("Hello, John", Await.result(result, duration)); + } + + @After + public void tearDown() { + system.shutdown(); + system.awaitTermination(); + } + +}