merge
This commit is contained in:
commit
4321be4c58
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<project
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>akka-http</artifactId>
|
||||||
|
<name>akka-http</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<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>2.5.11</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>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<akka.http.version>10.0.11</akka.http.version>
|
||||||
|
<akka.stream.version>2.5.11</akka.stream.version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.akkahttp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User Entity
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String address;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
this.name = "";
|
||||||
|
this.address = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String name, String address) {
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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,72 @@
|
||||||
|
package com.baeldung.akkahttp;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines all messages related to User Actor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface UserRegistryMessages {
|
||||||
|
|
||||||
|
class GetUsers implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 CreateUser implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final User user;
|
||||||
|
|
||||||
|
public CreateUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetUser implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public GetUser(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteUser implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public DeleteUser(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.baeldung.akkahttp;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletionStage;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import akka.actor.ActorRef;
|
||||||
|
import akka.http.javadsl.marshallers.jackson.Jackson;
|
||||||
|
import akka.http.javadsl.model.StatusCodes;
|
||||||
|
import akka.http.javadsl.server.AllDirectives;
|
||||||
|
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.CreateUser;
|
||||||
|
import scala.concurrent.duration.Duration;
|
||||||
|
import static akka.http.javadsl.server.PathMatchers.*;
|
||||||
|
|
||||||
|
class UserRoutes extends AllDirectives {
|
||||||
|
|
||||||
|
private final ActorRef userActor;
|
||||||
|
|
||||||
|
Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS));
|
||||||
|
|
||||||
|
UserRoutes(ActorRef userActor) {
|
||||||
|
this.userActor = userActor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Route routes() {
|
||||||
|
return path("users", this::postUser)
|
||||||
|
.orElse(path(segment("users").slash(longSegment()), id ->
|
||||||
|
route(getUser(id),
|
||||||
|
deleteUser(id))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Route getUser(Long id) {
|
||||||
|
return get(() -> {
|
||||||
|
CompletionStage<Optional<User>> user = PatternsCS.ask(userActor, new UserMessages.GetUser(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 deleteUser(Long id) {
|
||||||
|
return delete(() -> {
|
||||||
|
CompletionStage<ActionPerformed> userDeleted = PatternsCS.ask(userActor, new UserMessages.DeleteUser(id), timeout)
|
||||||
|
.thenApply(obj -> (ActionPerformed) obj);
|
||||||
|
|
||||||
|
return onSuccess(() -> userDeleted, performed -> {
|
||||||
|
return complete(StatusCodes.OK, performed, Jackson.marshaller());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Route postUser() {
|
||||||
|
return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> {
|
||||||
|
CompletionStage<ActionPerformed> userCreated = PatternsCS.ask(userActor, new CreateUser(user), timeout)
|
||||||
|
.thenApply(obj -> (ActionPerformed) obj);
|
||||||
|
|
||||||
|
return onSuccess(() -> userCreated, performed -> {
|
||||||
|
return complete(StatusCodes.CREATED, performed, Jackson.marshaller());
|
||||||
|
});
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package com.baeldung.akkahttp;
|
||||||
|
|
||||||
|
public class UserService {
|
||||||
|
}
|
|
@ -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 UserRoutesUnitTest extends JUnitRouteTest {
|
||||||
|
|
||||||
|
ActorSystem system = ActorSystem.create("helloAkkaHttpServer");
|
||||||
|
|
||||||
|
ActorRef userActorRef = system.actorOf(UserActor.props(), "userActor");
|
||||||
|
|
||||||
|
TestRoute appRoute = testRoute(new UserRoutes(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\"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue