Skip to content
This repository was archived by the owner on May 9, 2019. It is now read-only.

Commit a5a8b5a

Browse files
lakhinaTim Moore
authored and
Tim Moore
committed
Add a user read-side processor (#131)
1 parent ef0b3d5 commit a5a8b5a

File tree

18 files changed

+412
-108
lines changed

18 files changed

+412
-108
lines changed

build.sbt

+13-10
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,14 @@ lazy val transactionImpl = (project in file("transaction-impl"))
156156
tools,
157157
testkit % "test"
158158
).settings(
159-
version := "1.0-SNAPSHOT",
160-
libraryDependencies ++= Seq(
161-
lagomJavadslPersistenceCassandra,
162-
lagomJavadslTestKit,
163-
lagomJavadslKafkaBroker,
164-
cassandraExtras
165-
)
159+
version := "1.0-SNAPSHOT",
160+
libraryDependencies ++= Seq(
161+
lagomJavadslPersistenceCassandra,
162+
lagomJavadslTestKit,
163+
lagomJavadslKafkaBroker,
164+
cassandraExtras
166165
)
166+
)
167167

168168
lazy val userApi = (project in file("user-api"))
169169
.settings(commonSettings: _*)
@@ -174,18 +174,21 @@ lazy val userApi = (project in file("user-api"))
174174
lombok
175175
)
176176
)
177-
.dependsOn(security)
177+
.dependsOn(security, tools)
178178

179179
lazy val userImpl = (project in file("user-impl"))
180180
.settings(commonSettings: _*)
181181
.enablePlugins(LagomJava)
182-
.dependsOn(userApi)
182+
.dependsOn(userApi, tools,
183+
testkit % "test"
184+
)
183185
.settings(
184186
version := "1.0-SNAPSHOT",
185187
libraryDependencies ++= Seq(
186188
lagomJavadslPersistenceCassandra,
187189
lagomJavadslTestKit,
188-
"de.svenkubiak" % "jBCrypt" % "0.4"
190+
"de.svenkubiak" % "jBCrypt" % "0.4",
191+
cassandraExtras
189192
)
190193
)
191194

Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
package com.example.auction.user.api;
22

3-
import com.fasterxml.jackson.annotation.JsonCreator;
4-
import com.fasterxml.jackson.annotation.JsonProperty;
53
import lombok.Value;
64

7-
import java.util.Optional;
5+
import java.time.Instant;
86
import java.util.UUID;
97

108
@Value
119
public final class User {
1210

1311
private final UUID id;
12+
private final Instant createdAt;
1413
private final String name;
1514
private final String email;
1615

17-
@JsonCreator
18-
public User(@JsonProperty("id") UUID id, @JsonProperty("name") String name, @JsonProperty("email") String email) {
19-
this.id = id;
20-
this.name = name;
21-
this.email = email;
22-
}
16+
2317

2418
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.example.auction.user.api;
22

3-
import com.fasterxml.jackson.annotation.JsonCreator;
4-
import com.fasterxml.jackson.annotation.JsonProperty;
53
import lombok.Value;
64

75
@Value
@@ -11,11 +9,6 @@ public final class UserRegistration {
119
private final String email;
1210
private final String password;
1311

14-
@JsonCreator
15-
public UserRegistration( @JsonProperty("name") String name, @JsonProperty("email") String email, @JsonProperty("password") String password) {
16-
this.name = name;
17-
this.email = email;
18-
this.password = password;
19-
}
12+
2013

2114
}
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
package com.example.auction.user.api;
22

33
import akka.NotUsed;
4+
import com.example.auction.pagination.PaginatedSequence;
45
import com.lightbend.lagom.javadsl.api.Descriptor;
56
import com.lightbend.lagom.javadsl.api.Service;
67
import com.lightbend.lagom.javadsl.api.ServiceCall;
78
import com.lightbend.lagom.javadsl.api.deser.PathParamSerializers;
8-
import org.pcollections.PSequence;
99

10+
import java.util.Optional;
1011
import java.util.UUID;
1112

12-
import static com.lightbend.lagom.javadsl.api.Service.*;
13+
import static com.lightbend.lagom.javadsl.api.Service.named;
14+
import static com.lightbend.lagom.javadsl.api.Service.pathCall;
1315

1416
public interface UserService extends Service {
1517

1618
ServiceCall<UserRegistration, User> createUser();
1719

1820
ServiceCall<NotUsed, User> getUser(UUID userId);
1921

20-
// Remove once we have a proper user service
21-
ServiceCall<NotUsed, PSequence<User>> getUsers();
22+
ServiceCall<NotUsed, PaginatedSequence<User>> getUsers(
23+
Optional<Integer> pageNo, Optional<Integer> pageSize);
2224

2325
@Override
2426
default Descriptor descriptor() {
2527
return named("user").withCalls(
2628
pathCall("/api/user", this::createUser),
2729
pathCall("/api/user/:id", this::getUser),
28-
pathCall("/api/user", this::getUsers)
29-
).withPathParamSerializer(UUID.class, PathParamSerializers.required("UUID", UUID::fromString, UUID::toString));
30+
pathCall("/api/user?pageNo&pageSize", this::getUsers)
31+
).withPathParamSerializer(
32+
UUID.class, PathParamSerializers.required("UUID", UUID::fromString, UUID::toString)
33+
);
3034
}
3135
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package com.example.auction.user.impl;
2-
31
import com.example.auction.user.api.UserService;
2+
import com.example.auction.user.impl.UserRepository;
3+
import com.example.auction.user.impl.UserServiceImpl;
44
import com.google.inject.AbstractModule;
55
import com.lightbend.lagom.javadsl.server.ServiceGuiceSupport;
66

7-
public class UserModule extends AbstractModule implements ServiceGuiceSupport {
7+
public class Module extends AbstractModule implements ServiceGuiceSupport {
88
@Override
99
protected void configure() {
1010
bindService(UserService.class, UserServiceImpl.class);
11+
bind(UserRepository.class);
1112
}
1213
}

user-impl/src/main/java/com/example/auction/user/impl/Mappers.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
import com.example.auction.user.api.User;
44

5-
/**
6-
*
7-
*/
5+
import java.util.Optional;
6+
87
public class Mappers {
98

10-
public static User toApi(PUser user) {
9+
public static User toApi(Optional<PUser> user) {
1110
return new User(
12-
user.getId(),
13-
user.getName(),
14-
user.getEmail()
11+
user.get().getId(),
12+
user.get().getCreatedAt(),
13+
user.get().getName(),
14+
user.get().getEmail()
1515
);
1616
}
1717

user-impl/src/main/java/com/example/auction/user/impl/PUser.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
import com.lightbend.lagom.serialization.Jsonable;
44
import lombok.Value;
55

6+
import java.time.Instant;
67
import java.util.UUID;
78

89
@Value
910
public final class PUser implements Jsonable {
1011

1112
private final UUID id;
13+
private final Instant createdAt;
1214
private final String name;
13-
private final String email;
15+
private final String email;
1416
private final String passwordHash;
1517

1618

user-impl/src/main/java/com/example/auction/user/impl/PUserCommand.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.example.auction.user.impl;
22

3-
import com.fasterxml.jackson.annotation.JsonCreator;
43
import com.lightbend.lagom.javadsl.persistence.PersistentEntity;
54
import com.lightbend.lagom.serialization.Jsonable;
65
import lombok.Value;
@@ -10,28 +9,29 @@
109

1110
public interface PUserCommand extends Jsonable {
1211
@Value
13-
final class CreatePUser implements PUserCommand, PersistentEntity.ReplyType<PUser> {
12+
final class CreatePUser implements PUserCommand, PersistentEntity.ReplyType<Optional<PUser>> {
1413
private final String name;
1514
private final String email;
1615
private final String passwordHash;
1716
}
18-
public static String hashPassword(String password_plaintext) {
19-
String salt = BCrypt.gensalt(12);
20-
String hashed_password = BCrypt.hashpw(password_plaintext, salt);
2117

22-
return (hashed_password);
23-
}
18+
public static String hashPassword(String password_plaintext) {
19+
String salt = BCrypt.gensalt(12);
20+
String hashed_password = BCrypt.hashpw(password_plaintext, salt);
2421

25-
public static boolean checkPassword(String password_plaintext, String stored_hash) {
26-
boolean password_verified = false;
22+
return (hashed_password);
23+
}
24+
25+
public static boolean checkPassword(String password_plaintext, String stored_hash) {
26+
boolean password_verified = false;
2727

28-
if (null == stored_hash)
29-
throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
28+
if (null == stored_hash)
29+
throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
3030

31-
password_verified = BCrypt.checkpw(password_plaintext, stored_hash);
31+
password_verified = BCrypt.checkpw(password_plaintext, stored_hash);
3232

33-
return (password_verified);
34-
}
33+
return (password_verified);
34+
}
3535

3636

3737
enum GetPUser implements PUserCommand, PersistentEntity.ReplyType<Optional<PUser>> {

user-impl/src/main/java/com/example/auction/user/impl/PUserEntity.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.example.auction.user.impl;
22

3-
import com.example.auction.user.api.UserRegistration;
3+
import com.example.auction.user.impl.PUserCommand.CreatePUser;
4+
import com.example.auction.user.impl.PUserCommand.GetPUser;
5+
import com.example.auction.user.impl.PUserEvent.PUserCreated;
46
import com.lightbend.lagom.javadsl.persistence.PersistentEntity;
5-
import com.example.auction.user.impl.PUserCommand.*;
6-
import com.example.auction.user.impl.PUserEvent.*;
77

8+
import java.time.Instant;
89
import java.util.Optional;
910
import java.util.UUID;
1011
import java.util.function.Function;
@@ -30,7 +31,7 @@ private Behavior created(PUser user) {
3031
);
3132

3233
b.setReadOnlyCommandHandler(CreatePUser.class, (create, ctx) ->
33-
ctx.invalidCommand("User already exists.")
34+
ctx.invalidCommand("User already exists.")
3435
);
3536

3637
return b.build();
@@ -45,8 +46,8 @@ private Behavior notCreated() {
4546

4647
b.setCommandHandler(CreatePUser.class, (create, ctx) -> {
4748

48-
PUser user = new PUser(UUID.fromString(entityId()), create.getName(), create.getEmail(), create.getPasswordHash());
49-
return ctx.thenPersist(new PUserCreated(user), (e) -> ctx.reply(user));
49+
PUser user = new PUser(UUID.fromString(entityId()), Instant.now(), create.getName(), create.getEmail(), create.getPasswordHash());
50+
return ctx.thenPersist(new PUserCreated(user), (e) -> ctx.reply(Optional.ofNullable(user)));
5051
});
5152

5253
b.setEventHandlerChangingBehavior(PUserCreated.class, user -> created(user.getUser()));
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
package com.example.auction.user.impl;
22

33
import com.lightbend.lagom.javadsl.persistence.AggregateEvent;
4+
import com.lightbend.lagom.javadsl.persistence.AggregateEventShards;
45
import com.lightbend.lagom.javadsl.persistence.AggregateEventTag;
6+
import com.lightbend.lagom.javadsl.persistence.AggregateEventTagger;
57
import com.lightbend.lagom.serialization.Jsonable;
68
import lombok.Value;
79

810
public interface PUserEvent extends Jsonable, AggregateEvent<PUserEvent> {
911

12+
int NUM_SHARDS = 4;
13+
AggregateEventShards<PUserEvent> TAG = AggregateEventTag.sharded(PUserEvent.class, NUM_SHARDS);
14+
1015
@Value
1116
final class PUserCreated implements PUserEvent {
1217
private final PUser user;
1318
}
1419

1520
@Override
16-
default AggregateEventTag<PUserEvent> aggregateTag() {
17-
return AggregateEventTag.of(PUserEvent.class);
21+
default AggregateEventTagger<PUserEvent> aggregateTag() {
22+
return TAG;
1823
}
1924
}

0 commit comments

Comments
 (0)