Java 11501 (#12405)
* added parent module (akka-modules) * moved akka-http(submodule) to akka-modules(parent) * moved akka-streams(submodule) to akka-modules(parent) * moved spring-akka(submodule) to akka-modules(parent) * deleted submodules that we moved to akka-modules Co-authored-by: panagiotiskakos <panagiotis.kakos@libra-is.com>
This commit is contained in:
3
akka-modules/README.md
Normal file
3
akka-modules/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Akka
|
||||
|
||||
This module contains modules about Akka.
|
||||
7
akka-modules/akka-http/README.md
Normal file
7
akka-modules/akka-http/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Akka HTTP
|
||||
|
||||
This module contains articles about Akka HTTP.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http)
|
||||
44
akka-modules/akka-http/pom.xml
Normal file
44
akka-modules/akka-http/pom.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>akka-http</artifactId>
|
||||
<name>akka-http</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>akka-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-stream_2.12</artifactId>
|
||||
<version>${akka.stream.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http-jackson_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http-testkit_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<akka.http.version>10.0.11</akka.http.version>
|
||||
<akka.stream.version>2.5.11</akka.stream.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
public class User {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String name;
|
||||
|
||||
public User() {
|
||||
this.name = "";
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
public User(Long id, String name) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.actor.Props;
|
||||
import akka.japi.pf.FI;
|
||||
import com.baeldung.akkahttp.UserMessages.ActionPerformed;
|
||||
import com.baeldung.akkahttp.UserMessages.CreateUserMessage;
|
||||
import com.baeldung.akkahttp.UserMessages.GetUserMessage;
|
||||
|
||||
|
||||
class UserActor extends AbstractActor {
|
||||
|
||||
private UserService userService = new UserService();
|
||||
|
||||
static Props props() {
|
||||
return Props.create(UserActor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(CreateUserMessage.class, handleCreateUser())
|
||||
.match(GetUserMessage.class, handleGetUser())
|
||||
.build();
|
||||
}
|
||||
|
||||
private FI.UnitApply<CreateUserMessage> handleCreateUser() {
|
||||
return createUserMessageMessage -> {
|
||||
userService.createUser(createUserMessageMessage.getUser());
|
||||
sender().tell(new ActionPerformed(String.format("User %s created.", createUserMessageMessage.getUser()
|
||||
.getName())), getSelf());
|
||||
};
|
||||
}
|
||||
|
||||
private FI.UnitApply<GetUserMessage> handleGetUser() {
|
||||
return getUserMessageMessage -> {
|
||||
sender().tell(userService.getUser(getUserMessageMessage.getUserId()), getSelf());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface UserMessages {
|
||||
|
||||
class ActionPerformed implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String description;
|
||||
|
||||
public ActionPerformed(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
class CreateUserMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final User user;
|
||||
|
||||
public CreateUserMessage(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
class GetUserMessage implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Long userId;
|
||||
|
||||
public GetUserMessage(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.http.javadsl.marshallers.jackson.Jackson;
|
||||
import akka.http.javadsl.model.StatusCodes;
|
||||
import akka.http.javadsl.server.HttpApp;
|
||||
import akka.http.javadsl.server.Route;
|
||||
import akka.pattern.PatternsCS;
|
||||
import akka.util.Timeout;
|
||||
import com.baeldung.akkahttp.UserMessages.ActionPerformed;
|
||||
import com.baeldung.akkahttp.UserMessages.CreateUserMessage;
|
||||
import com.baeldung.akkahttp.UserMessages.GetUserMessage;
|
||||
import scala.concurrent.duration.Duration;
|
||||
import static akka.http.javadsl.server.PathMatchers.*;
|
||||
|
||||
class UserServer extends HttpApp {
|
||||
|
||||
private final ActorRef userActor;
|
||||
|
||||
Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS));
|
||||
|
||||
UserServer(ActorRef userActor) {
|
||||
this.userActor = userActor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Route routes() {
|
||||
return path("users", this::postUser)
|
||||
.orElse(path(segment("users").slash(longSegment()), id ->
|
||||
route(getUser(id))));
|
||||
}
|
||||
|
||||
private Route getUser(Long id) {
|
||||
return get(() -> {
|
||||
CompletionStage<Optional<User>> user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout)
|
||||
.thenApply(obj -> (Optional<User>) obj);
|
||||
|
||||
return onSuccess(() -> user, performed -> {
|
||||
if (performed.isPresent())
|
||||
return complete(StatusCodes.OK, performed.get(), Jackson.marshaller());
|
||||
else
|
||||
return complete(StatusCodes.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private Route postUser() {
|
||||
return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> {
|
||||
CompletionStage<ActionPerformed> userCreated = PatternsCS.ask(userActor, new CreateUserMessage(user), timeout)
|
||||
.thenApply(obj -> (ActionPerformed) obj);
|
||||
|
||||
return onSuccess(() -> userCreated, performed -> {
|
||||
return complete(StatusCodes.CREATED, performed, Jackson.marshaller());
|
||||
});
|
||||
})));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ActorSystem system = ActorSystem.create("userServer");
|
||||
ActorRef userActor = system.actorOf(UserActor.props(), "userActor");
|
||||
UserServer server = new UserServer(userActor);
|
||||
server.startServer("localhost", 8080, system);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class UserService {
|
||||
|
||||
private final static List<User> users = new ArrayList<>();
|
||||
|
||||
static {
|
||||
users.add(new User(1l, "Alice"));
|
||||
users.add(new User(2l, "Bob"));
|
||||
users.add(new User(3l, "Chris"));
|
||||
users.add(new User(4l, "Dick"));
|
||||
users.add(new User(5l, "Eve"));
|
||||
users.add(new User(6l, "Finn"));
|
||||
}
|
||||
|
||||
public Optional<User> getUser(Long id) {
|
||||
return users.stream()
|
||||
.filter(user -> user.getId()
|
||||
.equals(id))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public void createUser(User user) {
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
public List<User> getUsers(){
|
||||
return users;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.akkahttp;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.http.javadsl.model.ContentTypes;
|
||||
import akka.http.javadsl.model.HttpEntities;
|
||||
import akka.http.javadsl.model.HttpRequest;
|
||||
import akka.http.javadsl.testkit.JUnitRouteTest;
|
||||
import akka.http.javadsl.testkit.TestRoute;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UserServerUnitTest extends JUnitRouteTest {
|
||||
|
||||
ActorSystem system = ActorSystem.create("helloAkkaHttpServer");
|
||||
|
||||
ActorRef userActorRef = system.actorOf(UserActor.props(), "userActor");
|
||||
|
||||
TestRoute appRoute = testRoute(new UserServer(userActorRef).routes());
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void whenRequest_thenActorResponds() {
|
||||
|
||||
appRoute.run(HttpRequest.GET("/users/1"))
|
||||
.assertEntity(alice())
|
||||
.assertStatusCode(200);
|
||||
|
||||
appRoute.run(HttpRequest.GET("/users/42"))
|
||||
.assertStatusCode(404);
|
||||
|
||||
appRoute.run(HttpRequest.DELETE("/users/1"))
|
||||
.assertStatusCode(405);
|
||||
|
||||
appRoute.run(HttpRequest.DELETE("/users/42"))
|
||||
.assertStatusCode(405);
|
||||
|
||||
appRoute.run(HttpRequest.POST("/users")
|
||||
.withEntity(HttpEntities.create(ContentTypes.APPLICATION_JSON, zaphod())))
|
||||
.assertStatusCode(201);
|
||||
|
||||
}
|
||||
|
||||
private String alice() {
|
||||
return "{\"id\":1,\"name\":\"Alice\"}";
|
||||
}
|
||||
|
||||
private String zaphod() {
|
||||
return "{\"id\":42,\"name\":\"Zaphod\"}";
|
||||
}
|
||||
|
||||
}
|
||||
7
akka-modules/akka-streams/README.md
Normal file
7
akka-modules/akka-streams/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Akka Streams
|
||||
|
||||
This module contains articles about Akka Streams.
|
||||
|
||||
### Relevant articles
|
||||
|
||||
- [Guide to Akka Streams](https://www.baeldung.com/akka-streams)
|
||||
33
akka-modules/akka-streams/pom.xml
Normal file
33
akka-modules/akka-streams/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>akka-streams</artifactId>
|
||||
<name>akka-streams</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>akka-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-stream_${scala.version}</artifactId>
|
||||
<version>${akkastreams.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-stream-testkit_${scala.version}</artifactId>
|
||||
<version>${akkastreams.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<akkastreams.version>2.5.2</akkastreams.version>
|
||||
<scala.version>2.11</scala.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.akkastreams;
|
||||
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
public class AverageRepository {
|
||||
CompletionStage<Double> save(Double average) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
System.out.println("saving average: " + average);
|
||||
return average;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.baeldung.akkastreams;
|
||||
|
||||
|
||||
import akka.Done;
|
||||
import akka.NotUsed;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.stream.ActorMaterializer;
|
||||
import akka.stream.javadsl.Flow;
|
||||
import akka.stream.javadsl.Keep;
|
||||
import akka.stream.javadsl.Sink;
|
||||
import akka.stream.javadsl.Source;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DataImporter {
|
||||
private final ActorSystem actorSystem;
|
||||
private final AverageRepository averageRepository = new AverageRepository();
|
||||
|
||||
public DataImporter(ActorSystem actorSystem) {
|
||||
this.actorSystem = actorSystem;
|
||||
|
||||
}
|
||||
|
||||
private List<Integer> parseLine(String line) {
|
||||
String[] fields = line.split(";");
|
||||
return Arrays.stream(fields)
|
||||
.map(Integer::parseInt)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Flow<String, Integer, NotUsed> parseContent() {
|
||||
return Flow.of(String.class).mapConcat(this::parseLine);
|
||||
}
|
||||
|
||||
private Flow<Integer, Double, NotUsed> computeAverage() {
|
||||
return Flow.of(Integer.class).grouped(2).mapAsyncUnordered(8, integers ->
|
||||
CompletableFuture.supplyAsync(() -> integers
|
||||
.stream()
|
||||
.mapToDouble(v -> v)
|
||||
.average()
|
||||
.orElse(-1.0)));
|
||||
}
|
||||
|
||||
Flow<String, Double, NotUsed> calculateAverage() {
|
||||
return Flow.of(String.class)
|
||||
.via(parseContent())
|
||||
.via(computeAverage());
|
||||
}
|
||||
|
||||
private Sink<Double, CompletionStage<Done>> storeAverages() {
|
||||
return Flow.of(Double.class)
|
||||
.mapAsyncUnordered(4, averageRepository::save)
|
||||
.toMat(Sink.ignore(), Keep.right());
|
||||
}
|
||||
|
||||
|
||||
CompletionStage<Done> calculateAverageForContent(String content) {
|
||||
return Source.single(content)
|
||||
.via(calculateAverage())
|
||||
.runWith(storeAverages(), ActorMaterializer.create(actorSystem))
|
||||
.whenComplete((d, e) -> {
|
||||
if (d != null) {
|
||||
System.out.println("Import finished ");
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
13
akka-modules/akka-streams/src/main/resources/logback.xml
Normal file
13
akka-modules/akka-streams/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.akkastreams;
|
||||
|
||||
import akka.NotUsed;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.stream.ActorMaterializer;
|
||||
import akka.stream.javadsl.Flow;
|
||||
import akka.stream.javadsl.Source;
|
||||
import akka.stream.testkit.javadsl.TestSink;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class DataImporterUnitTest {
|
||||
private final ActorSystem actorSystem = ActorSystem.create();
|
||||
|
||||
@Test
|
||||
public void givenStreamOfIntegers_whenCalculateAverageOfPairs_thenShouldReturnProperResults() {
|
||||
//given
|
||||
Flow<String, Double, NotUsed> tested = new DataImporter(actorSystem).calculateAverage();
|
||||
String input = "1;9;11;0";
|
||||
|
||||
//when
|
||||
Source<Double, NotUsed> flow = Source.single(input).via(tested);
|
||||
|
||||
//then
|
||||
flow
|
||||
.runWith(TestSink.probe(actorSystem), ActorMaterializer.create(actorSystem))
|
||||
.request(4)
|
||||
.expectNextUnordered(5d, 5.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStreamOfIntegers_whenCalculateAverageAndSaveToSink_thenShouldFinishSuccessfully() {
|
||||
//given
|
||||
DataImporter dataImporter = new DataImporter(actorSystem);
|
||||
String input = "10;90;110;10";
|
||||
|
||||
//when
|
||||
dataImporter.calculateAverageForContent(input)
|
||||
.thenAccept(d -> actorSystem.terminate());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
34
akka-modules/pom.xml
Normal file
34
akka-modules/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>akka-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>akka-modules</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>akka-http</module>
|
||||
<module>akka-streams</module>
|
||||
<module>spring-akka</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
6
akka-modules/spring-akka/README.md
Normal file
6
akka-modules/spring-akka/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## Spring Akka
|
||||
|
||||
This module contains articles about Spring with Akka
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Spring with Akka](https://www.baeldung.com/akka-with-spring)
|
||||
51
akka-modules/spring-akka/pom.xml
Normal file
51
akka-modules/spring-akka/pom.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-akka</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>spring-akka</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>akka-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-actor_${scala.version}</artifactId>
|
||||
<version>${akka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<properties>
|
||||
<spring.version>4.3.4.RELEASE</spring.version>
|
||||
<akka.version>2.4.14</akka.version>
|
||||
<scala.version>2.11</scala.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.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;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
public class AppConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Bean
|
||||
public ActorSystem actorSystem() {
|
||||
ActorSystem system = ActorSystem.create("akka-spring-demo");
|
||||
SpringExtension.SPRING_EXTENSION_PROVIDER.get(system).initialize(applicationContext);
|
||||
return system;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.akka;
|
||||
|
||||
import akka.actor.UntypedActor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Scope(ConfigurableBeanFactory.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.akka;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class GreetingService {
|
||||
|
||||
public String greet(String name) {
|
||||
return "Hello, " + name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.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<? extends Actor> actorClass() {
|
||||
return (Class<? extends Actor>) applicationContext.getType(beanActorName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.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<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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
13
akka-modules/spring-akka/src/main/resources/logback.xml
Normal file
13
akka-modules/spring-akka/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.akka;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.util.Timeout;
|
||||
import com.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 com.baeldung.akka.SpringExtension.SPRING_EXTENSION_PROVIDER;
|
||||
|
||||
@ContextConfiguration(classes = AppConfiguration.class)
|
||||
public class SpringAkkaIntegrationTest 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<Object> result = ask(greeter, new Greet("John"), timeout);
|
||||
|
||||
Assert.assertEquals("Hello, John", Await.result(result, duration));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
system.shutdown();
|
||||
system.awaitTermination();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user