From 7d6178a25b3f0bc1ff179315391aa3449afb2536 Mon Sep 17 00:00:00 2001 From: Andrzej Ludwikowski Date: Fri, 27 Dec 2024 11:37:02 +0100 Subject: [PATCH] chore: aligning view store sample --- .../java/pages/key-value-entities.adoc | 20 ------ docs/src/modules/java/pages/views.adoc | 23 ------- samples/view-store/README.md | 33 ++++------ .../store/customer/api/CustomerEndpoint.java | 40 +++++++++++ .../{api => application}/CustomerEntity.java | 18 ++--- .../java/store/order/api/OrderEndpoint.java | 66 +++++++++++++++++++ .../{api => application}/CreateOrder.java | 2 +- .../{api => application}/OrderEntity.java | 9 ++- .../view/joined/CustomerOrder.java | 2 +- .../view/joined/JoinedCustomerOrdersView.java | 12 ++-- .../{ => order}/view/model/Customer.java | 2 +- .../store/{ => order}/view/model/Product.java | 2 +- .../view/nested/CustomerOrder.java | 2 +- .../view/nested/CustomerOrders.java | 2 +- .../view/nested/NestedCustomerOrdersView.java | 12 ++-- .../view/structured/CustomerOrders.java | 2 +- .../view/structured/CustomerShipping.java | 2 +- .../view/structured/ProductOrder.java | 2 +- .../view/structured/ProductValue.java | 2 +- .../StructuredCustomerOrdersView.java | 12 ++-- .../store/product/api/ProductEndpoint.java | 39 +++++++++++ .../{api => application}/ProductEntity.java | 16 +++-- .../customer/api/CustomerEntityTest.java | 1 + .../store/product/api/ProductEntityTest.java | 1 + .../store/view/StoreViewIntegrationTest.java | 8 +-- ...inedCustomerOrdersViewIntegrationTest.java | 2 + ...stedCustomerOrdersViewIntegrationTest.java | 3 + ...uredCustomerOrdersViewIntegrationTest.java | 3 + 28 files changed, 223 insertions(+), 115 deletions(-) create mode 100644 samples/view-store/src/main/java/store/customer/api/CustomerEndpoint.java rename samples/view-store/src/main/java/store/customer/{api => application}/CustomerEntity.java (79%) create mode 100644 samples/view-store/src/main/java/store/order/api/OrderEndpoint.java rename samples/view-store/src/main/java/store/order/{api => application}/CreateOrder.java (71%) rename samples/view-store/src/main/java/store/order/{api => application}/OrderEntity.java (73%) rename samples/view-store/src/main/java/store/{ => order}/view/joined/CustomerOrder.java (90%) rename samples/view-store/src/main/java/store/{ => order}/view/joined/JoinedCustomerOrdersView.java (91%) rename samples/view-store/src/main/java/store/{ => order}/view/model/Customer.java (91%) rename samples/view-store/src/main/java/store/{ => order}/view/model/Product.java (91%) rename samples/view-store/src/main/java/store/{ => order}/view/nested/CustomerOrder.java (87%) rename samples/view-store/src/main/java/store/{ => order}/view/nested/CustomerOrders.java (87%) rename samples/view-store/src/main/java/store/{ => order}/view/nested/NestedCustomerOrdersView.java (91%) rename samples/view-store/src/main/java/store/{ => order}/view/structured/CustomerOrders.java (82%) rename samples/view-store/src/main/java/store/{ => order}/view/structured/CustomerShipping.java (80%) rename samples/view-store/src/main/java/store/{ => order}/view/structured/ProductOrder.java (83%) rename samples/view-store/src/main/java/store/{ => order}/view/structured/ProductValue.java (75%) rename samples/view-store/src/main/java/store/{ => order}/view/structured/StructuredCustomerOrdersView.java (91%) create mode 100644 samples/view-store/src/main/java/store/product/api/ProductEndpoint.java rename samples/view-store/src/main/java/store/product/{api => application}/ProductEntity.java (78%) diff --git a/docs/src/modules/java/pages/key-value-entities.adoc b/docs/src/modules/java/pages/key-value-entities.adoc index 7991e1e01..3d943e6c9 100644 --- a/docs/src/modules/java/pages/key-value-entities.adoc +++ b/docs/src/modules/java/pages/key-value-entities.adoc @@ -161,23 +161,3 @@ include::example$key-value-counter/src/test/java/com/example/CounterIntegrationT <5> Explicitly request current value of `bar`. It should be `1`. NOTE: The integration tests in samples can be run using `mvn integration-test`. - -== Exposing entities directly - -include::partial$component-endpoint.adoc[] - -=== API - -The entity is exposed at a fixed path: - -[source] ----- -/akka/v1.0/entity/// ----- - -In our counter example that is: - -[source,shell] ----- -curl localhost:9000/akka/v1.0/entity/counter/foo/get ----- diff --git a/docs/src/modules/java/pages/views.adoc b/docs/src/modules/java/pages/views.adoc index f158fa648..93f392717 100644 --- a/docs/src/modules/java/pages/views.adoc +++ b/docs/src/modules/java/pages/views.adoc @@ -318,26 +318,3 @@ include::example$key-value-customer-registry/src/test/java/customer/application/ Views are not replicated directly in the same way as for example xref:event-sourced-entities.adoc#_replication[Event Sourced Entity replication]. A View is built from entities in the same service, or another service, in the same region. The entities will replicate all events across regions and identical Views are built in each region. A View can also be built from a message broker topic, and that could be regional or global depending on how the message broker is configured. - -== Exposing views directly - -include::partial$component-endpoint.adoc[] - -=== API - -The view is exposed at a fixed path: - -[source] ----- -/akka/v1.0/view// ----- - -Taking the sample from the <> as an example, that would be: - -[source,shell] ----- -curl localhost:9000/akka/v1.0/view/view_customers_by_email/getCustomer \ - --header "Content-Type: application/json" \ - -XPOST \ - --data '{"email":"test2@example.com"}' ----- diff --git a/samples/view-store/README.md b/samples/view-store/README.md index e7adac46d..40c9a988a 100644 --- a/samples/view-store/README.md +++ b/samples/view-store/README.md @@ -21,7 +21,7 @@ With your Akka service running, once you have defined endpoints they should be a Create some products: ```shell -curl localhost:9000/akka/v1.0/entity/product/P123/create \ +curl -i localhost:9000/products/P123 \ -XPOST \ --header "Content-Type: application/json" \ --data '{ @@ -31,7 +31,7 @@ curl localhost:9000/akka/v1.0/entity/product/P123/create \ ``` ```shell -curl localhost:9000/akka/v1.0/entity/product/P987/create \ +curl -i localhost:9000/products/P987 \ -XPOST \ --header "Content-Type: application/json" \ --data '{ @@ -43,13 +43,13 @@ curl localhost:9000/akka/v1.0/entity/product/P987/create \ Retrieve a product by id: ```shell -curl localhost:9000/akka/v1.0/entity/product/P123/get +curl localhost:9000/products/P123 ``` Create a customer: ```shell -curl localhost:9000/akka/v1.0/entity/customer/C001/create \ +curl -i localhost:9000/customers/C001 \ -XPOST \ --header "Content-Type: application/json" \ --data '{ @@ -62,13 +62,13 @@ curl localhost:9000/akka/v1.0/entity/customer/C001/create \ Retrieve a customer by id: ```shell -curl localhost:9000/akka/v1.0/entity/customer/C001/get +curl localhost:9000/customers/C001 ``` Create customer orders for the products: ```shell -curl localhost:9000/akka/v1.0/entity/order/O1234/create \ +curl -i localhost:9000/orders/O1234 \ -XPOST \ --header "Content-Type: application/json" \ --data '{ @@ -79,7 +79,7 @@ curl localhost:9000/akka/v1.0/entity/order/O1234/create \ ``` ```shell -curl localhost:9000/akka/v1.0/entity/order/O5678/create \ +curl -i localhost:9000/orders/O5678 \ -XPOST \ --header "Content-Type: application/json" \ --data '{ @@ -92,38 +92,29 @@ curl localhost:9000/akka/v1.0/entity/order/O5678/create \ Retrieve orders by id: ```shell -curl localhost:9000/akka/v1.0/entity/order/O1234/get +curl localhost:9000/orders/O1234 ``` ```shell -curl localhost:9000/akka/v1.0/entity/order/O5678/get +curl localhost:9000/orders/O5678 ``` Retrieve all product orders for a customer id using a view (with joins): ```shell -curl localhost:9000/akka/v1.0/view/joined-customer-orders/get \ - --header "Content-Type: application/json" \ - -XPOST \ - --data '{ "customerId": "C001" }' +curl localhost:9000/orders/joined-by-customer/C001 ``` Retrieve all product orders for a customer id using a view (with joins and nested projection): ```shell -curl localhost:9000/akka/v1.0/view/nested-customer-orders/get \ - --header "Content-Type: application/json" \ - -XPOST \ - --data '{ "customerId": "C001" }' +curl localhost:9000/orders/nested-by-customer/C001 ``` Retrieve all product orders for a customer id using a view (with joins and structured projection): ```shell -curl localhost:9000/akka/v1.0/view/structured-customer-orders/get \ - --header "Content-Type: application/json" \ - -XPOST \ - --data '{ "customerId": "C001" }' +curl localhost:9000/orders/structured-by-customer/C001 ``` ## Deploying diff --git a/samples/view-store/src/main/java/store/customer/api/CustomerEndpoint.java b/samples/view-store/src/main/java/store/customer/api/CustomerEndpoint.java new file mode 100644 index 000000000..d049dab86 --- /dev/null +++ b/samples/view-store/src/main/java/store/customer/api/CustomerEndpoint.java @@ -0,0 +1,40 @@ +package store.customer.api; + +import akka.http.javadsl.model.HttpResponse; +import akka.javasdk.annotations.Acl; +import akka.javasdk.annotations.http.Get; +import akka.javasdk.annotations.http.HttpEndpoint; +import akka.javasdk.annotations.http.Post; +import akka.javasdk.client.ComponentClient; +import store.customer.application.CustomerEntity; +import store.customer.domain.Customer; + +import java.util.concurrent.CompletionStage; + +import static akka.javasdk.http.HttpResponses.created; + +@HttpEndpoint("/customers") +@Acl(allow = @Acl.Matcher(principal = Acl.Principal.INTERNET)) +public class CustomerEndpoint { + + private final ComponentClient componentClient; + + public CustomerEndpoint(ComponentClient componentClient) { + this.componentClient = componentClient; + } + + @Post("/{customerId}") + public CompletionStage create(String customerId, Customer customer) { + return componentClient.forEventSourcedEntity(customerId) + .method(CustomerEntity::create) + .invokeAsync(customer) + .thenApply(__ -> created()); + } + + @Get("/{customerId}") + public CompletionStage get(String customerId) { + return componentClient.forEventSourcedEntity(customerId) + .method(CustomerEntity::get) + .invokeAsync(); + } +} diff --git a/samples/view-store/src/main/java/store/customer/api/CustomerEntity.java b/samples/view-store/src/main/java/store/customer/application/CustomerEntity.java similarity index 79% rename from samples/view-store/src/main/java/store/customer/api/CustomerEntity.java rename to samples/view-store/src/main/java/store/customer/application/CustomerEntity.java index fe7a9baa1..becd1991b 100644 --- a/samples/view-store/src/main/java/store/customer/api/CustomerEntity.java +++ b/samples/view-store/src/main/java/store/customer/application/CustomerEntity.java @@ -1,11 +1,13 @@ -package store.customer.api; +package store.customer.application; +import akka.Done; import akka.javasdk.annotations.ComponentId; import akka.javasdk.eventsourcedentity.EventSourcedEntity; import store.customer.domain.Address; import store.customer.domain.Customer; import store.customer.domain.CustomerEvent; +import static akka.Done.done; import static store.customer.domain.CustomerEvent.CustomerAddressChanged; import static store.customer.domain.CustomerEvent.CustomerCreated; import static store.customer.domain.CustomerEvent.CustomerNameChanged; @@ -17,22 +19,20 @@ public ReadOnlyEffect get() { return effects().reply(currentState()); } - public Effect create(Customer customer) { + public Effect create(Customer customer) { return effects() .persist(new CustomerCreated(customer.email(), customer.name(), customer.address())) - .thenReply(__ -> "OK"); + .thenReply(__ -> done()); } - public Effect changeName(String newName) { - return effects().persist(new CustomerNameChanged(newName)).thenReply(__ -> "OK"); + public Effect changeName(String newName) { + return effects().persist(new CustomerNameChanged(newName)).thenReply(__ -> done()); } - - public Effect changeAddress(Address newAddress) { - return effects().persist(new CustomerAddressChanged(newAddress)).thenReply(__ -> "OK"); + public Effect changeAddress(Address newAddress) { + return effects().persist(new CustomerAddressChanged(newAddress)).thenReply(__ -> done()); } - @Override public Customer applyEvent(CustomerEvent event) { return switch (event) { diff --git a/samples/view-store/src/main/java/store/order/api/OrderEndpoint.java b/samples/view-store/src/main/java/store/order/api/OrderEndpoint.java new file mode 100644 index 000000000..81988286d --- /dev/null +++ b/samples/view-store/src/main/java/store/order/api/OrderEndpoint.java @@ -0,0 +1,66 @@ +package store.order.api; + +import akka.http.javadsl.model.HttpResponse; +import akka.javasdk.annotations.Acl; +import akka.javasdk.annotations.http.Get; +import akka.javasdk.annotations.http.HttpEndpoint; +import akka.javasdk.annotations.http.Post; +import akka.javasdk.client.ComponentClient; +import store.order.application.CreateOrder; +import store.order.application.OrderEntity; +import store.order.domain.Order; +import store.order.view.joined.JoinedCustomerOrdersView; +import store.order.view.nested.CustomerOrders; +import store.order.view.nested.NestedCustomerOrdersView; +import store.order.view.structured.StructuredCustomerOrdersView; + +import java.util.concurrent.CompletionStage; + +import static akka.javasdk.http.HttpResponses.created; + +@HttpEndpoint("/orders") +@Acl(allow = @Acl.Matcher(principal = Acl.Principal.INTERNET)) +public class OrderEndpoint { + + private final ComponentClient componentClient; + + public OrderEndpoint(ComponentClient componentClient) { + this.componentClient = componentClient; + } + + @Post("/{orderId}") + public CompletionStage create(String orderId, CreateOrder createOrder) { + return componentClient.forKeyValueEntity(orderId) + .method(OrderEntity::create) + .invokeAsync(createOrder) + .thenApply(__ -> created()); + } + + @Get("/{orderId}") + public CompletionStage get(String orderId) { + return componentClient.forKeyValueEntity(orderId) + .method(OrderEntity::get) + .invokeAsync(); + } + + @Get("/joined-by-customer/{customerId}") + public CompletionStage joinedByCustomer(String customerId) { + return componentClient.forView() + .method(JoinedCustomerOrdersView::get) + .invokeAsync(customerId); + } + + @Get("/nested-by-customer/{customerId}") + public CompletionStage nestedByCustomer(String customerId) { + return componentClient.forView() + .method(NestedCustomerOrdersView::get) + .invokeAsync(customerId); + } + + @Get("/structured-by-customer/{customerId}") + public CompletionStage structuredByCustomer(String customerId) { + return componentClient.forView() + .method(StructuredCustomerOrdersView::get) + .invokeAsync(customerId); + } +} diff --git a/samples/view-store/src/main/java/store/order/api/CreateOrder.java b/samples/view-store/src/main/java/store/order/application/CreateOrder.java similarity index 71% rename from samples/view-store/src/main/java/store/order/api/CreateOrder.java rename to samples/view-store/src/main/java/store/order/application/CreateOrder.java index 06946c468..9056c0be4 100644 --- a/samples/view-store/src/main/java/store/order/api/CreateOrder.java +++ b/samples/view-store/src/main/java/store/order/application/CreateOrder.java @@ -1,4 +1,4 @@ -package store.order.api; +package store.order.application; public record CreateOrder(String productId, String customerId, int quantity) { } diff --git a/samples/view-store/src/main/java/store/order/api/OrderEntity.java b/samples/view-store/src/main/java/store/order/application/OrderEntity.java similarity index 73% rename from samples/view-store/src/main/java/store/order/api/OrderEntity.java rename to samples/view-store/src/main/java/store/order/application/OrderEntity.java index f56ec11cd..7c1a24c9f 100644 --- a/samples/view-store/src/main/java/store/order/api/OrderEntity.java +++ b/samples/view-store/src/main/java/store/order/application/OrderEntity.java @@ -1,11 +1,14 @@ -package store.order.api; +package store.order.application; +import akka.Done; import akka.javasdk.annotations.ComponentId; import akka.javasdk.keyvalueentity.KeyValueEntity; import store.order.domain.Order; import java.time.Instant; +import static akka.Done.done; + @ComponentId("order") public class OrderEntity extends KeyValueEntity { @@ -13,7 +16,7 @@ public Effect get() { return effects().reply(currentState()); } - public Effect create(CreateOrder createOrder) { + public Effect create(CreateOrder createOrder) { Order order = new Order( commandContext().entityId(), @@ -21,6 +24,6 @@ public Effect create(CreateOrder createOrder) { createOrder.customerId(), createOrder.quantity(), Instant.now().toEpochMilli()); - return effects().updateState(order).thenReply("OK"); + return effects().updateState(order).thenReply(done()); } } diff --git a/samples/view-store/src/main/java/store/view/joined/CustomerOrder.java b/samples/view-store/src/main/java/store/order/view/joined/CustomerOrder.java similarity index 90% rename from samples/view-store/src/main/java/store/view/joined/CustomerOrder.java rename to samples/view-store/src/main/java/store/order/view/joined/CustomerOrder.java index 391df1266..0670e45d4 100644 --- a/samples/view-store/src/main/java/store/view/joined/CustomerOrder.java +++ b/samples/view-store/src/main/java/store/order/view/joined/CustomerOrder.java @@ -1,4 +1,4 @@ -package store.view.joined; +package store.order.view.joined; import store.customer.domain.Address; import store.product.domain.Money; diff --git a/samples/view-store/src/main/java/store/view/joined/JoinedCustomerOrdersView.java b/samples/view-store/src/main/java/store/order/view/joined/JoinedCustomerOrdersView.java similarity index 91% rename from samples/view-store/src/main/java/store/view/joined/JoinedCustomerOrdersView.java rename to samples/view-store/src/main/java/store/order/view/joined/JoinedCustomerOrdersView.java index efb71c1d2..70d294e78 100644 --- a/samples/view-store/src/main/java/store/view/joined/JoinedCustomerOrdersView.java +++ b/samples/view-store/src/main/java/store/order/view/joined/JoinedCustomerOrdersView.java @@ -1,4 +1,4 @@ -package store.view.joined; +package store.order.view.joined; import akka.javasdk.annotations.Query; import akka.javasdk.annotations.Consume; @@ -6,14 +6,14 @@ import akka.javasdk.annotations.ComponentId; import akka.javasdk.view.View; import akka.javasdk.view.TableUpdater; -import store.customer.api.CustomerEntity; +import store.customer.application.CustomerEntity; import store.customer.domain.CustomerEvent; -import store.order.api.OrderEntity; +import store.order.application.OrderEntity; import store.order.domain.Order; -import store.product.api.ProductEntity; +import store.product.application.ProductEntity; import store.product.domain.ProductEvent; -import store.view.model.Customer; -import store.view.model.Product; +import store.order.view.model.Customer; +import store.order.view.model.Product; import java.util.List; diff --git a/samples/view-store/src/main/java/store/view/model/Customer.java b/samples/view-store/src/main/java/store/order/view/model/Customer.java similarity index 91% rename from samples/view-store/src/main/java/store/view/model/Customer.java rename to samples/view-store/src/main/java/store/order/view/model/Customer.java index 2a19d23dd..77467c6b6 100644 --- a/samples/view-store/src/main/java/store/view/model/Customer.java +++ b/samples/view-store/src/main/java/store/order/view/model/Customer.java @@ -1,4 +1,4 @@ -package store.view.model; +package store.order.view.model; import store.customer.domain.Address; diff --git a/samples/view-store/src/main/java/store/view/model/Product.java b/samples/view-store/src/main/java/store/order/view/model/Product.java similarity index 91% rename from samples/view-store/src/main/java/store/view/model/Product.java rename to samples/view-store/src/main/java/store/order/view/model/Product.java index ea1226253..a5d093ae6 100644 --- a/samples/view-store/src/main/java/store/view/model/Product.java +++ b/samples/view-store/src/main/java/store/order/view/model/Product.java @@ -1,4 +1,4 @@ -package store.view.model; +package store.order.view.model; import store.product.domain.Money; diff --git a/samples/view-store/src/main/java/store/view/nested/CustomerOrder.java b/samples/view-store/src/main/java/store/order/view/nested/CustomerOrder.java similarity index 87% rename from samples/view-store/src/main/java/store/view/nested/CustomerOrder.java rename to samples/view-store/src/main/java/store/order/view/nested/CustomerOrder.java index dded33d10..c6d5f91d0 100644 --- a/samples/view-store/src/main/java/store/view/nested/CustomerOrder.java +++ b/samples/view-store/src/main/java/store/order/view/nested/CustomerOrder.java @@ -1,4 +1,4 @@ -package store.view.nested; +package store.order.view.nested; import store.product.domain.Money; diff --git a/samples/view-store/src/main/java/store/view/nested/CustomerOrders.java b/samples/view-store/src/main/java/store/order/view/nested/CustomerOrders.java similarity index 87% rename from samples/view-store/src/main/java/store/view/nested/CustomerOrders.java rename to samples/view-store/src/main/java/store/order/view/nested/CustomerOrders.java index aa01e0d13..b287d858c 100644 --- a/samples/view-store/src/main/java/store/view/nested/CustomerOrders.java +++ b/samples/view-store/src/main/java/store/order/view/nested/CustomerOrders.java @@ -1,4 +1,4 @@ -package store.view.nested; +package store.order.view.nested; import store.customer.domain.Address; diff --git a/samples/view-store/src/main/java/store/view/nested/NestedCustomerOrdersView.java b/samples/view-store/src/main/java/store/order/view/nested/NestedCustomerOrdersView.java similarity index 91% rename from samples/view-store/src/main/java/store/view/nested/NestedCustomerOrdersView.java rename to samples/view-store/src/main/java/store/order/view/nested/NestedCustomerOrdersView.java index 6ba765184..361f349c3 100644 --- a/samples/view-store/src/main/java/store/view/nested/NestedCustomerOrdersView.java +++ b/samples/view-store/src/main/java/store/order/view/nested/NestedCustomerOrdersView.java @@ -1,4 +1,4 @@ -package store.view.nested; +package store.order.view.nested; import akka.javasdk.annotations.Query; import akka.javasdk.annotations.Consume; @@ -6,14 +6,14 @@ import akka.javasdk.annotations.ComponentId; import akka.javasdk.view.View; import akka.javasdk.view.TableUpdater; -import store.customer.api.CustomerEntity; +import store.customer.application.CustomerEntity; import store.customer.domain.CustomerEvent; -import store.order.api.OrderEntity; +import store.order.application.OrderEntity; import store.order.domain.Order; -import store.product.api.ProductEntity; +import store.product.application.ProductEntity; import store.product.domain.ProductEvent; -import store.view.model.Customer; -import store.view.model.Product; +import store.order.view.model.Customer; +import store.order.view.model.Product; @ComponentId("nested-customer-orders") public class NestedCustomerOrdersView extends View { diff --git a/samples/view-store/src/main/java/store/view/structured/CustomerOrders.java b/samples/view-store/src/main/java/store/order/view/structured/CustomerOrders.java similarity index 82% rename from samples/view-store/src/main/java/store/view/structured/CustomerOrders.java rename to samples/view-store/src/main/java/store/order/view/structured/CustomerOrders.java index f82c1fd5e..93acc9407 100644 --- a/samples/view-store/src/main/java/store/view/structured/CustomerOrders.java +++ b/samples/view-store/src/main/java/store/order/view/structured/CustomerOrders.java @@ -1,4 +1,4 @@ -package store.view.structured; +package store.order.view.structured; import java.util.List; diff --git a/samples/view-store/src/main/java/store/view/structured/CustomerShipping.java b/samples/view-store/src/main/java/store/order/view/structured/CustomerShipping.java similarity index 80% rename from samples/view-store/src/main/java/store/view/structured/CustomerShipping.java rename to samples/view-store/src/main/java/store/order/view/structured/CustomerShipping.java index b1d9a462e..6b6a97a32 100644 --- a/samples/view-store/src/main/java/store/view/structured/CustomerShipping.java +++ b/samples/view-store/src/main/java/store/order/view/structured/CustomerShipping.java @@ -1,4 +1,4 @@ -package store.view.structured; +package store.order.view.structured; // tag::structured[] public record CustomerShipping( diff --git a/samples/view-store/src/main/java/store/view/structured/ProductOrder.java b/samples/view-store/src/main/java/store/order/view/structured/ProductOrder.java similarity index 83% rename from samples/view-store/src/main/java/store/view/structured/ProductOrder.java rename to samples/view-store/src/main/java/store/order/view/structured/ProductOrder.java index 3f04a2731..d6c1de4dd 100644 --- a/samples/view-store/src/main/java/store/view/structured/ProductOrder.java +++ b/samples/view-store/src/main/java/store/order/view/structured/ProductOrder.java @@ -1,4 +1,4 @@ -package store.view.structured; +package store.order.view.structured; // tag::structured[] public record ProductOrder( diff --git a/samples/view-store/src/main/java/store/view/structured/ProductValue.java b/samples/view-store/src/main/java/store/order/view/structured/ProductValue.java similarity index 75% rename from samples/view-store/src/main/java/store/view/structured/ProductValue.java rename to samples/view-store/src/main/java/store/order/view/structured/ProductValue.java index f2bc6d4da..73d4299d5 100644 --- a/samples/view-store/src/main/java/store/view/structured/ProductValue.java +++ b/samples/view-store/src/main/java/store/order/view/structured/ProductValue.java @@ -1,4 +1,4 @@ -package store.view.structured; +package store.order.view.structured; // tag::structured[] public record ProductValue(String currency, long units, int cents) { diff --git a/samples/view-store/src/main/java/store/view/structured/StructuredCustomerOrdersView.java b/samples/view-store/src/main/java/store/order/view/structured/StructuredCustomerOrdersView.java similarity index 91% rename from samples/view-store/src/main/java/store/view/structured/StructuredCustomerOrdersView.java rename to samples/view-store/src/main/java/store/order/view/structured/StructuredCustomerOrdersView.java index 3d748170e..ea6a7ff4b 100644 --- a/samples/view-store/src/main/java/store/view/structured/StructuredCustomerOrdersView.java +++ b/samples/view-store/src/main/java/store/order/view/structured/StructuredCustomerOrdersView.java @@ -1,4 +1,4 @@ -package store.view.structured; +package store.order.view.structured; import akka.javasdk.annotations.Query; import akka.javasdk.annotations.Consume; @@ -6,14 +6,14 @@ import akka.javasdk.annotations.ComponentId; import akka.javasdk.view.View; import akka.javasdk.view.TableUpdater; -import store.customer.api.CustomerEntity; +import store.customer.application.CustomerEntity; import store.customer.domain.CustomerEvent; -import store.order.api.OrderEntity; +import store.order.application.OrderEntity; import store.order.domain.Order; -import store.product.api.ProductEntity; +import store.product.application.ProductEntity; import store.product.domain.ProductEvent; -import store.view.model.Customer; -import store.view.model.Product; +import store.order.view.model.Customer; +import store.order.view.model.Product; @ComponentId("structured-customer-orders") public class StructuredCustomerOrdersView extends View { diff --git a/samples/view-store/src/main/java/store/product/api/ProductEndpoint.java b/samples/view-store/src/main/java/store/product/api/ProductEndpoint.java new file mode 100644 index 000000000..c3b388308 --- /dev/null +++ b/samples/view-store/src/main/java/store/product/api/ProductEndpoint.java @@ -0,0 +1,39 @@ +package store.product.api; + +import akka.http.javadsl.model.HttpResponse; +import akka.javasdk.annotations.Acl; +import akka.javasdk.annotations.http.Get; +import akka.javasdk.annotations.http.HttpEndpoint; +import akka.javasdk.annotations.http.Post; +import akka.javasdk.client.ComponentClient; +import store.product.application.ProductEntity; +import store.product.domain.Product; + +import java.util.concurrent.CompletionStage; + +import static akka.javasdk.http.HttpResponses.created; + +@HttpEndpoint("/products") +@Acl(allow = @Acl.Matcher(principal = Acl.Principal.INTERNET)) +public class ProductEndpoint { + private final ComponentClient componentClient; + + public ProductEndpoint(ComponentClient componentClient) { + this.componentClient = componentClient; + } + + @Post("/{productId}") + public CompletionStage create(String productId, Product product) { + return componentClient.forEventSourcedEntity(productId) + .method(ProductEntity::create) + .invokeAsync(product) + .thenApply(__ -> created()); + } + + @Get("/{productId}") + public CompletionStage get(String productId) { + return componentClient.forEventSourcedEntity(productId) + .method(ProductEntity::get) + .invokeAsync(); + } +} diff --git a/samples/view-store/src/main/java/store/product/api/ProductEntity.java b/samples/view-store/src/main/java/store/product/application/ProductEntity.java similarity index 78% rename from samples/view-store/src/main/java/store/product/api/ProductEntity.java rename to samples/view-store/src/main/java/store/product/application/ProductEntity.java index af28febd8..49da02ac6 100644 --- a/samples/view-store/src/main/java/store/product/api/ProductEntity.java +++ b/samples/view-store/src/main/java/store/product/application/ProductEntity.java @@ -1,11 +1,13 @@ -package store.product.api; +package store.product.application; +import akka.Done; import akka.javasdk.annotations.ComponentId; import akka.javasdk.eventsourcedentity.EventSourcedEntity; import store.product.domain.Money; import store.product.domain.Product; import store.product.domain.ProductEvent; +import static akka.Done.done; import static store.product.domain.ProductEvent.ProductCreated; import static store.product.domain.ProductEvent.ProductNameChanged; import static store.product.domain.ProductEvent.ProductPriceChanged; @@ -18,18 +20,18 @@ public ReadOnlyEffect get() { return effects().reply(currentState()); } - public Effect create(Product product) { + public Effect create(Product product) { return effects() .persist(new ProductCreated(product.name(), product.price())) - .thenReply(__ -> "OK"); + .thenReply(__ -> done()); } - public Effect changeName(String newName) { - return effects().persist(new ProductNameChanged(newName)).thenReply(__ -> "OK"); + public Effect changeName(String newName) { + return effects().persist(new ProductNameChanged(newName)).thenReply(__ -> done()); } - public Effect changePrice(Money newPrice) { - return effects().persist(new ProductPriceChanged(newPrice)).thenReply(__ -> "OK"); + public Effect changePrice(Money newPrice) { + return effects().persist(new ProductPriceChanged(newPrice)).thenReply(__ -> done()); } @Override diff --git a/samples/view-store/src/test/java/store/customer/api/CustomerEntityTest.java b/samples/view-store/src/test/java/store/customer/api/CustomerEntityTest.java index 1ae5b4697..d05c13024 100644 --- a/samples/view-store/src/test/java/store/customer/api/CustomerEntityTest.java +++ b/samples/view-store/src/test/java/store/customer/api/CustomerEntityTest.java @@ -3,6 +3,7 @@ import akka.javasdk.testkit.EventSourcedResult; import akka.javasdk.testkit.EventSourcedTestKit; import org.junit.jupiter.api.Test; +import store.customer.application.CustomerEntity; import store.customer.domain.Address; import store.customer.domain.Customer; import store.customer.domain.CustomerEvent; diff --git a/samples/view-store/src/test/java/store/product/api/ProductEntityTest.java b/samples/view-store/src/test/java/store/product/api/ProductEntityTest.java index 4361f9e94..456e68a21 100644 --- a/samples/view-store/src/test/java/store/product/api/ProductEntityTest.java +++ b/samples/view-store/src/test/java/store/product/api/ProductEntityTest.java @@ -3,6 +3,7 @@ import akka.javasdk.testkit.EventSourcedResult; import akka.javasdk.testkit.EventSourcedTestKit; import org.junit.jupiter.api.Test; +import store.product.application.ProductEntity; import store.product.domain.Money; import store.product.domain.Product; import store.product.domain.ProductEvent; diff --git a/samples/view-store/src/test/java/store/view/StoreViewIntegrationTest.java b/samples/view-store/src/test/java/store/view/StoreViewIntegrationTest.java index 35450e942..db4f00868 100644 --- a/samples/view-store/src/test/java/store/view/StoreViewIntegrationTest.java +++ b/samples/view-store/src/test/java/store/view/StoreViewIntegrationTest.java @@ -1,12 +1,12 @@ package store.view; import akka.javasdk.testkit.TestKitSupport; -import store.customer.api.CustomerEntity; +import store.customer.application.CustomerEntity; import store.customer.domain.Address; import store.customer.domain.Customer; -import store.order.api.CreateOrder; -import store.order.api.OrderEntity; -import store.product.api.ProductEntity; +import store.order.application.CreateOrder; +import store.order.application.OrderEntity; +import store.product.application.ProductEntity; import store.product.domain.Money; import store.product.domain.Product; diff --git a/samples/view-store/src/test/java/store/view/joined/JoinedCustomerOrdersViewIntegrationTest.java b/samples/view-store/src/test/java/store/view/joined/JoinedCustomerOrdersViewIntegrationTest.java index ef90a0b9e..1c8c4efb2 100644 --- a/samples/view-store/src/test/java/store/view/joined/JoinedCustomerOrdersViewIntegrationTest.java +++ b/samples/view-store/src/test/java/store/view/joined/JoinedCustomerOrdersViewIntegrationTest.java @@ -2,6 +2,8 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +import store.order.view.joined.CustomerOrder; +import store.order.view.joined.JoinedCustomerOrdersView; import store.view.StoreViewIntegrationTest; import java.util.List; diff --git a/samples/view-store/src/test/java/store/view/nested/NestedCustomerOrdersViewIntegrationTest.java b/samples/view-store/src/test/java/store/view/nested/NestedCustomerOrdersViewIntegrationTest.java index 1e187871f..5104d9c3f 100644 --- a/samples/view-store/src/test/java/store/view/nested/NestedCustomerOrdersViewIntegrationTest.java +++ b/samples/view-store/src/test/java/store/view/nested/NestedCustomerOrdersViewIntegrationTest.java @@ -2,6 +2,9 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +import store.order.view.nested.CustomerOrder; +import store.order.view.nested.CustomerOrders; +import store.order.view.nested.NestedCustomerOrdersView; import store.view.StoreViewIntegrationTest; import java.util.concurrent.TimeUnit; diff --git a/samples/view-store/src/test/java/store/view/structured/StructuredCustomerOrdersViewIntegrationTest.java b/samples/view-store/src/test/java/store/view/structured/StructuredCustomerOrdersViewIntegrationTest.java index 29002dfbc..32ae08a53 100644 --- a/samples/view-store/src/test/java/store/view/structured/StructuredCustomerOrdersViewIntegrationTest.java +++ b/samples/view-store/src/test/java/store/view/structured/StructuredCustomerOrdersViewIntegrationTest.java @@ -2,6 +2,9 @@ import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; +import store.order.view.structured.CustomerOrders; +import store.order.view.structured.ProductOrder; +import store.order.view.structured.StructuredCustomerOrdersView; import store.view.StoreViewIntegrationTest; import java.util.concurrent.TimeUnit;