Merge pull request #26289 from akka/wip-javadsl-blog-sample-patriknw

Cleanup javadsl Blog Post sample in Persistence Typed
This commit is contained in:
Patrik Nordwall 2019-01-31 16:28:34 +01:00 committed by GitHub
commit 9d6aa8ae94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 137 deletions

View file

@ -197,36 +197,17 @@ Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #commands }
@java[The commandler handler to process each command is decided by the state class (or state predicate) that is
given to the `commandHandlerBuilder` and the match cases in the builders. Several builders can be composed with `orElse`:]
given to the `forStateType` of the `CommandHandlerBuilder` and the match cases in the builders.]
@scala[The command handler to process each command is decided by first looking at the state and then the command.
It typically becomes two levels of pattern matching, first on the state and then on the command. Delegating to methods
is a good practise because the one-line cases give a nice overview of the message dispatch.]
@@@ div { .group-scala }
It typically becomes two levels of pattern matching, first on the state and then on the command.]
Delegating to methods is a good practise because the one-line cases give a nice overview of the message dispatch.
Scala
: @@snip [BlogPostExample.scala](/akka-persistence-typed/src/test/scala/docs/akka/persistence/typed/BlogPostExample.scala) { #command-handler }
@@@
@@@ div { .group-java }
TODO rewrite this example to be more like the Scala example
Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #command-handler }
The `CommandHandlerBuilder` for a post that hasn't been initialized with content:
Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #initial-command-handler }
And a different `CommandHandlerBuilder` for after the post content has been added:
Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #post-added-command-handler }
@@@
The event handler:

View file

@ -12,12 +12,12 @@ import akka.actor.typed.javadsl.Behaviors;
import akka.persistence.typed.PersistenceId;
import akka.persistence.typed.javadsl.*;
public class BlogPostExample {
public interface BlogPostExample {
// #event
interface BlogEvent {}
public static class PostAdded implements BlogEvent {
public class PostAdded implements BlogEvent {
private final String postId;
private final PostContent content;
@ -27,7 +27,7 @@ public class BlogPostExample {
}
}
public static class BodyChanged implements BlogEvent {
public class BodyChanged implements BlogEvent {
private final String postId;
private final String newBody;
@ -37,7 +37,7 @@ public class BlogPostExample {
}
}
public static class Published implements BlogEvent {
public class Published implements BlogEvent {
private final String postId;
public Published(String postId) {
@ -53,35 +53,43 @@ public class BlogPostExample {
INSTANCE
}
public static class DraftState implements BlogState {
final PostContent postContent;
public class DraftState implements BlogState {
final PostContent content;
DraftState(PostContent postContent) {
this.postContent = postContent;
DraftState(PostContent content) {
this.content = content;
}
public DraftState withContent(PostContent newContent) {
return new DraftState(newContent);
}
public DraftState withBody(String newBody) {
return withContent(new PostContent(postId(), content.title, newBody));
}
public String postId() {
return postContent.postId;
return content.postId;
}
}
public static class PublishedState implements BlogState {
final PostContent postContent;
public class PublishedState implements BlogState {
final PostContent content;
PublishedState(PostContent postContent) {
this.postContent = postContent;
PublishedState(PostContent content) {
this.content = content;
}
public PublishedState withContent(PostContent newContent) {
return new PublishedState(newContent);
}
public PublishedState withBody(String newBody) {
return withContent(new PostContent(postId(), content.title, newBody));
}
public String postId() {
return postContent.postId;
return content.postId;
}
}
// #state
@ -89,7 +97,7 @@ public class BlogPostExample {
// #commands
public interface BlogCommand {}
// #reply-command
public static class AddPost implements BlogCommand {
public class AddPost implements BlogCommand {
final PostContent content;
final ActorRef<AddPostDone> replyTo;
@ -99,7 +107,7 @@ public class BlogPostExample {
}
}
public static class AddPostDone implements BlogCommand {
public class AddPostDone implements BlogCommand {
final String postId;
public AddPostDone(String postId) {
@ -107,7 +115,7 @@ public class BlogPostExample {
}
}
// #reply-command
public static class GetPost implements BlogCommand {
public class GetPost implements BlogCommand {
final ActorRef<PostContent> replyTo;
public GetPost(ActorRef<PostContent> replyTo) {
@ -115,7 +123,7 @@ public class BlogPostExample {
}
}
public static class ChangeBody implements BlogCommand {
public class ChangeBody implements BlogCommand {
final String newBody;
final ActorRef<Done> replyTo;
@ -125,7 +133,7 @@ public class BlogPostExample {
}
}
public static class Publish implements BlogCommand {
public class Publish implements BlogCommand {
final ActorRef<Done> replyTo;
public Publish(ActorRef<Done> replyTo) {
@ -133,7 +141,7 @@ public class BlogPostExample {
}
}
public static class PostContent implements BlogCommand {
public class PostContent implements BlogCommand {
final String postId;
final String title;
final String body;
@ -147,97 +155,74 @@ public class BlogPostExample {
// #commands
// #behavior
public static class BlogBehavior extends EventSourcedBehavior<BlogCommand, BlogEvent, BlogState> {
// #behavior
public class BlogBehavior extends EventSourcedBehavior<BlogCommand, BlogEvent, BlogState> {
private final ActorContext<BlogCommand> ctx;
public BlogBehavior(PersistenceId persistenceId, ActorContext<BlogCommand> ctx) {
public BlogBehavior(PersistenceId persistenceId) {
super(persistenceId);
this.ctx = ctx;
}
// #initial-command-handler
private CommandHandlerBuilderByState<BlogCommand, BlogEvent, BlankState, BlogState>
initialCommandHandler() {
return newCommandHandlerBuilder()
.forStateType(BlankState.class)
.matchCommand(
AddPost.class,
(state, cmd) -> {
// #reply
PostAdded event = new PostAdded(cmd.content.postId, cmd.content);
return Effect()
.persist(event)
.thenRun(() -> cmd.replyTo.tell(new AddPostDone(cmd.content.postId)));
// #reply
});
}
// #initial-command-handler
// #post-added-command-handler
private CommandHandlerBuilderByState<BlogCommand, BlogEvent, DraftState, BlogState>
draftCommandHandler() {
return newCommandHandlerBuilder()
.forStateType(DraftState.class)
.matchCommand(
ChangeBody.class,
(state, cmd) -> {
BodyChanged event = new BodyChanged(state.postId(), cmd.newBody);
return Effect().persist(event).thenRun(() -> cmd.replyTo.tell(Done.getInstance()));
})
.matchCommand(
Publish.class,
(state, cmd) ->
Effect()
.persist(new Published(state.postId()))
.thenRun(
() -> {
System.out.println("Blog post published: " + state.postId());
cmd.replyTo.tell(Done.getInstance());
}))
.matchCommand(
GetPost.class,
(state, cmd) -> {
cmd.replyTo.tell(state.postContent);
return Effect().none();
});
}
private CommandHandlerBuilderByState<BlogCommand, BlogEvent, PublishedState, BlogState>
publishedCommandHandler() {
return newCommandHandlerBuilder()
.forStateType(PublishedState.class)
.matchCommand(
ChangeBody.class,
(state, cmd) -> {
BodyChanged event = new BodyChanged(state.postId(), cmd.newBody);
return Effect().persist(event).thenRun(() -> cmd.replyTo.tell(Done.getInstance()));
})
.matchCommand(
GetPost.class,
(state, cmd) -> {
cmd.replyTo.tell(state.postContent);
return Effect().none();
});
}
private CommandHandlerBuilderByState<BlogCommand, BlogEvent, BlogState, BlogState>
commonCommandHandler() {
return newCommandHandlerBuilder()
.forStateType(BlogState.class)
.matchCommand(AddPost.class, (state, cmd) -> Effect().unhandled());
}
// #post-added-command-handler
// #behavior
// #command-handler
@Override
public CommandHandler<BlogCommand, BlogEvent, BlogState> commandHandler() {
return initialCommandHandler()
.orElse(draftCommandHandler())
.orElse(publishedCommandHandler())
.orElse(commonCommandHandler())
.build();
CommandHandlerBuilder<BlogCommand, BlogEvent, BlogState> builder = newCommandHandlerBuilder();
builder.forStateType(BlankState.class).matchCommand(AddPost.class, this::addPost);
builder
.forStateType(DraftState.class)
.matchCommand(ChangeBody.class, this::changeBody)
.matchCommand(Publish.class, this::publish)
.matchCommand(GetPost.class, this::getPost);
builder
.forStateType(PublishedState.class)
.matchCommand(ChangeBody.class, this::changeBody)
.matchCommand(GetPost.class, this::getPost);
builder.forAnyState().matchCommand(AddPost.class, (state, cmd) -> Effect().unhandled());
return builder.build();
}
private Effect<BlogEvent, BlogState> addPost(AddPost cmd) {
// #reply
PostAdded event = new PostAdded(cmd.content.postId, cmd.content);
return Effect()
.persist(event)
.thenRun(() -> cmd.replyTo.tell(new AddPostDone(cmd.content.postId)));
// #reply
}
private Effect<BlogEvent, BlogState> changeBody(DraftState state, ChangeBody cmd) {
BodyChanged event = new BodyChanged(state.postId(), cmd.newBody);
return Effect().persist(event).thenRun(() -> cmd.replyTo.tell(Done.getInstance()));
}
private Effect<BlogEvent, BlogState> changeBody(PublishedState state, ChangeBody cmd) {
BodyChanged event = new BodyChanged(state.postId(), cmd.newBody);
return Effect().persist(event).thenRun(() -> cmd.replyTo.tell(Done.getInstance()));
}
private Effect<BlogEvent, BlogState> publish(DraftState state, Publish cmd) {
return Effect()
.persist(new Published(state.postId()))
.thenRun(
() -> {
System.out.println("Blog post published: " + state.postId());
cmd.replyTo.tell(Done.getInstance());
});
}
private Effect<BlogEvent, BlogState> getPost(DraftState state, GetPost cmd) {
cmd.replyTo.tell(state.content);
return Effect().none();
}
private Effect<BlogEvent, BlogState> getPost(PublishedState state, GetPost cmd) {
cmd.replyTo.tell(state.content);
return Effect().none();
}
// #command-handler
@ -253,20 +238,12 @@ public class BlogPostExample {
builder
.forStateType(DraftState.class)
.matchEvent(
BodyChanged.class,
(state, chg) ->
state.withContent(
new PostContent(state.postId(), state.postContent.title, chg.newBody)))
.matchEvent(Published.class, (state, event) -> new PublishedState(state.postContent));
.matchEvent(BodyChanged.class, (state, chg) -> state.withBody(chg.newBody))
.matchEvent(Published.class, (state, event) -> new PublishedState(state.content));
builder
.forStateType(PublishedState.class)
.matchEvent(
BodyChanged.class,
(state, chg) ->
state.withContent(
new PostContent(state.postId(), state.postContent.title, chg.newBody)));
.matchEvent(BodyChanged.class, (state, chg) -> state.withBody(chg.newBody));
return builder.build();
}
@ -274,7 +251,7 @@ public class BlogPostExample {
// #behavior
public static Behavior<BlogCommand> behavior(String entityId) {
return Behaviors.setup(ctx -> new BlogBehavior(new PersistenceId("Blog-" + entityId), ctx));
return Behaviors.setup(ctx -> new BlogBehavior(new PersistenceId("Blog-" + entityId)));
}
@Override