diff --git a/akka-http/pom.xml b/akka-http/pom.xml
new file mode 100644
index 0000000000..51e70fb583
--- /dev/null
+++ b/akka-http/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+ 4.0.0
+ akka-http
+ akka-http
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+
+
+ com.typesafe.akka
+ akka-http_2.12
+ ${akka.http.version}
+
+
+ com.typesafe.akka
+ akka-stream_2.12
+ 2.5.11
+
+
+ com.typesafe.akka
+ akka-http-jackson_2.12
+ ${akka.http.version}
+
+
+ com.typesafe.akka
+ akka-http-testkit_2.12
+ ${akka.http.version}
+ test
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 10.0.11
+ 2.5.11
+
+
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/User.java b/akka-http/src/main/java/com/baeldung/akkahttp/User.java
new file mode 100644
index 0000000000..43c21eca62
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/User.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java
new file mode 100644
index 0000000000..431014a88b
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java
@@ -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 handleCreateUser() {
+ return createUserMessageMessage -> {
+ userService.createUser(createUserMessageMessage.getUser());
+ sender().tell(new ActionPerformed(String.format("User %s created.", createUserMessageMessage.getUser()
+ .getName())), getSelf());
+ };
+ }
+
+ private FI.UnitApply handleGetUser() {
+ return getUserMessageMessage -> {
+ sender().tell(userService.getUser(getUserMessageMessage.getUserId()), getSelf());
+ };
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java
new file mode 100644
index 0000000000..995b92bcb0
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java
@@ -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;
+ }
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java
new file mode 100644
index 0000000000..0c1dbd1f60
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java
@@ -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> user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout)
+ .thenApply(obj -> (Optional) 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 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);
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java
new file mode 100644
index 0000000000..50dc1e1b28
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java
@@ -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 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 getUser(Long id) {
+ return users.stream()
+ .filter(user -> user.getId()
+ .equals(id))
+ .findFirst();
+ }
+
+ public void createUser(User user) {
+ users.add(user);
+ }
+
+ public List getUsers(){
+ return users;
+ }
+
+}
diff --git a/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java
new file mode 100644
index 0000000000..1170a2d761
--- /dev/null
+++ b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java
@@ -0,0 +1,50 @@
+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.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());
+
+ @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(200);
+
+ appRoute.run(HttpRequest.DELETE("/users/42"))
+ .assertStatusCode(200);
+
+ 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\"}";
+ }
+
+}