Cleanup javadsl Blog Post sample in Persistence Typed

This commit is contained in:
Patrik Nordwall 2019-01-25 20:48:37 +01:00
parent a920349090
commit 491d7efc60
2 changed files with 95 additions and 137 deletions

View file

@ -194,36 +194,17 @@ Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #commands } : @@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 @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. @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 It typically becomes two levels of pattern matching, first on the state and then on the command.]
is a good practise because the one-line cases give a nice overview of the message dispatch.] Delegating to methods is a good practise because the one-line cases give a nice overview of the message dispatch.
@@@ div { .group-scala }
Scala Scala
: @@snip [BlogPostExample.scala](/akka-persistence-typed/src/test/scala/docs/akka/persistence/typed/BlogPostExample.scala) { #command-handler } : @@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 Java
: @@snip [BlogPostExample.java](/akka-persistence-typed/src/test/java/jdocs/akka/persistence/typed/BlogPostExample.java) { #command-handler } : @@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: The event handler:

View file

@ -12,12 +12,12 @@ import akka.actor.typed.javadsl.Behaviors;
import akka.persistence.typed.PersistenceId; import akka.persistence.typed.PersistenceId;
import akka.persistence.typed.javadsl.*; import akka.persistence.typed.javadsl.*;
public class BlogPostExample { public interface BlogPostExample {
// #event // #event
interface BlogEvent {} interface BlogEvent {}
public static class PostAdded implements BlogEvent { public class PostAdded implements BlogEvent {
private final String postId; private final String postId;
private final PostContent content; 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 postId;
private final String newBody; 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; private final String postId;
public Published(String postId) { public Published(String postId) {
@ -53,35 +53,43 @@ public class BlogPostExample {
INSTANCE INSTANCE
} }
public static class DraftState implements BlogState { public class DraftState implements BlogState {
final PostContent postContent; final PostContent content;
DraftState(PostContent postContent) { DraftState(PostContent content) {
this.postContent = postContent; this.content = content;
} }
public DraftState withContent(PostContent newContent) { public DraftState withContent(PostContent newContent) {
return new DraftState(newContent); return new DraftState(newContent);
} }
public DraftState withBody(String newBody) {
return withContent(new PostContent(postId(), content.title, newBody));
}
public String postId() { public String postId() {
return postContent.postId; return content.postId;
} }
} }
public static class PublishedState implements BlogState { public class PublishedState implements BlogState {
final PostContent postContent; final PostContent content;
PublishedState(PostContent postContent) { PublishedState(PostContent content) {
this.postContent = postContent; this.content = content;
} }
public PublishedState withContent(PostContent newContent) { public PublishedState withContent(PostContent newContent) {
return new PublishedState(newContent); return new PublishedState(newContent);
} }
public PublishedState withBody(String newBody) {
return withContent(new PostContent(postId(), content.title, newBody));
}
public String postId() { public String postId() {
return postContent.postId; return content.postId;
} }
} }
// #state // #state
@ -89,7 +97,7 @@ public class BlogPostExample {
// #commands // #commands
public interface BlogCommand {} public interface BlogCommand {}
// #reply-command // #reply-command
public static class AddPost implements BlogCommand { public class AddPost implements BlogCommand {
final PostContent content; final PostContent content;
final ActorRef<AddPostDone> replyTo; 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; final String postId;
public AddPostDone(String postId) { public AddPostDone(String postId) {
@ -107,7 +115,7 @@ public class BlogPostExample {
} }
} }
// #reply-command // #reply-command
public static class GetPost implements BlogCommand { public class GetPost implements BlogCommand {
final ActorRef<PostContent> replyTo; final ActorRef<PostContent> replyTo;
public GetPost(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 String newBody;
final ActorRef<Done> replyTo; 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; final ActorRef<Done> replyTo;
public Publish(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 postId;
final String title; final String title;
final String body; final String body;
@ -147,97 +155,74 @@ public class BlogPostExample {
// #commands // #commands
// #behavior // #behavior
public static class BlogBehavior extends EventSourcedBehavior<BlogCommand, BlogEvent, BlogState> { public class BlogBehavior extends EventSourcedBehavior<BlogCommand, BlogEvent, BlogState> {
// #behavior
private final ActorContext<BlogCommand> ctx; public BlogBehavior(PersistenceId persistenceId) {
public BlogBehavior(PersistenceId persistenceId, ActorContext<BlogCommand> ctx) {
super(persistenceId); super(persistenceId);
this.ctx = ctx;
} }
// #initial-command-handler // #behavior
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
// #command-handler // #command-handler
@Override @Override
public CommandHandler<BlogCommand, BlogEvent, BlogState> commandHandler() { public CommandHandler<BlogCommand, BlogEvent, BlogState> commandHandler() {
return initialCommandHandler() CommandHandlerBuilder<BlogCommand, BlogEvent, BlogState> builder = newCommandHandlerBuilder();
.orElse(draftCommandHandler())
.orElse(publishedCommandHandler()) builder.forStateType(BlankState.class).matchCommand(AddPost.class, this::addPost);
.orElse(commonCommandHandler())
.build(); 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 // #command-handler
@ -253,20 +238,12 @@ public class BlogPostExample {
builder builder
.forStateType(DraftState.class) .forStateType(DraftState.class)
.matchEvent( .matchEvent(BodyChanged.class, (state, chg) -> state.withBody(chg.newBody))
BodyChanged.class, .matchEvent(Published.class, (state, event) -> new PublishedState(state.content));
(state, chg) ->
state.withContent(
new PostContent(state.postId(), state.postContent.title, chg.newBody)))
.matchEvent(Published.class, (state, event) -> new PublishedState(state.postContent));
builder builder
.forStateType(PublishedState.class) .forStateType(PublishedState.class)
.matchEvent( .matchEvent(BodyChanged.class, (state, chg) -> state.withBody(chg.newBody));
BodyChanged.class,
(state, chg) ->
state.withContent(
new PostContent(state.postId(), state.postContent.title, chg.newBody)));
return builder.build(); return builder.build();
} }
@ -274,7 +251,7 @@ public class BlogPostExample {
// #behavior // #behavior
public static Behavior<BlogCommand> behavior(String entityId) { 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 @Override