Table of Contents |
---|
...
Reference_description_with_linked_URLs____________________ | Notes____________________________________________________________ |
---|---|
m REST API design and tools | api and openapi design details |
https://microservices.io/ | Microservices |
Comparing_Java_REST_API_Frameworks_-_jconf.dev_2020.pdf https://drive.google.com/file/d/1vr5_jae2KghjIOyB6cpix47KB7fwUv5d/ https://developer.okta.com/blog/2021/06/18/native-java-framework-comparison Build Native Java Apps with Micronaut, Quarkus, and Spring Boot pdf rest-compare-Build Native Java Apps with Micronaut Quarkus and Spring Boot.pdf | Raible - compare Java REST Micronaut, Quarkus, Spring Boot work w Grails, JHipster front ends |
REST tutorials | |
https://dzone.com/articles/rest-api-your-guide-to-getting-started-quickly | REST tutorial with Swagger and Docker - Dzone |
models | |
https://microservices.io/patterns/data/event-sourcing.html | event sourcing vs current state for entities |
https://microservices.io/ | Microservices patterns |
...
https://microservices.io/patterns/data/event-sourcing.html
problem
How to reliably/atomically update the database and publish messages/events?
forces
2PC - 2 phase commit not an option
solution
A good solution to this problem is to use event sourcing. Event sourcing persists the state of a business entity such an Order or a Customer as a sequence of state-changing events. Whenever the state of a business entity changes, a new event is appended to the list of events. Since saving an event is a single operation, it is inherently atomic. The application reconstructs an entity’s current state by replaying the events.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
public class Order extends ReflectiveMutableCommandProcessingAggregate<Order, OrderCommand> { private OrderState state; private String customerId; public OrderState getState() { return state; } public List<Event> process(CreateOrderCommand cmd) { return EventUtil.events(new OrderCreatedEvent(cmd.getCustomerId(), cmd.getOrderTotal())); } public List<Event> process(ApproveOrderCommand cmd) { return EventUtil.events(new OrderApprovedEvent(customerId)); } public List<Event> process(RejectOrderCommand cmd) { return EventUtil.events(new OrderRejectedEvent(customerId)); } public void apply(OrderCreatedEvent event) { this.state = OrderState.CREATED; this.customerId = event.getCustomerId(); } public void apply(OrderApprovedEvent event) { this.state = OrderState.APPROVED; } public void apply(OrderRejectedEvent event) { this.state = OrderState.REJECTED; } |
Here is an example of an event handler in the CustomerService
that subscribes to Order
events:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@EventSubscriber(id = "customerWorkflow") public class CustomerWorkflow { @EventHandlerMethod public CompletableFuture<EntityWithIdAndVersion<Customer>> reserveCredit( EventHandlerContext<OrderCreatedEvent> ctx) { OrderCreatedEvent event = ctx.getEvent(); Money orderTotal = event.getOrderTotal(); String customerId = event.getCustomerId(); String orderId = ctx.getEntityId(); return ctx.update(Customer.class, customerId, new ReserveCreditCommand(orderTotal, orderId)); } } |
...
- Highly maintainable and testable
- Loosely coupled
- Independently deployable
- Organized around business capabilities
- Owned by a small team
The microservice architecture enables the rapid, frequent and reliable delivery of large, complex applications. It also enables an organization to evolve its technology stack.
Potential Value Opportunities
...