Getting started¶
1. Add the dependency¶
For a Spring MVC application that exposes use cases over HTTP:
If you only need injectable use cases (no HTTP endpoints), use io.github.enact-framework:enact-starter instead.
Snapshots
Every change merged to main is published as a snapshot (for example 0.0.2-SNAPSHOT).
To try unreleased changes, add the snapshot repository:
2. Write steps¶
A step is a method annotated with @Step. Its parameters are the inputs the use case will bind:
@StepDefinition
class OrderValidationService {
@Step
fun validateOrderCreation(request: OrderRequest): OrderRequest {
require(request.amount > 0) { "Amount should be greater than zero." }
return request
}
}
@StepDefinition
class OrderPersistingService {
@Step
fun saveOrder(request: OrderRequest): OrderEntity = TODO("persist")
}
@StepDefinition
class OrderResponseMapperService {
@Step
fun mapOrderResponse(order: OrderEntity): OrderResponse = OrderResponse(order.id)
}
@StepDefinition
public class OrderValidationService {
@Step
public OrderRequest validateOrderCreation(OrderRequest request) {
if (request.amount() <= 0) {
throw new IllegalArgumentException("Amount should be greater than zero.");
}
return request;
}
}
@StepDefinition
public class OrderPersistingService {
@Step
public OrderEntity saveOrder(OrderRequest request) {
throw new UnsupportedOperationException("TODO: persist");
}
}
@StepDefinition
public class OrderResponseMapperService {
@Step
public OrderResponse mapOrderResponse(OrderEntity order) {
return new OrderResponse(order.id());
}
}
3. Define the use case¶
Use cases are written in YAML files under src/main/resources/enact/, one file per domain:
src/main/resources/enact/orders.yaml
use-cases:
createOrder:
description: Validates and stores a new order
trigger:
rest: # (1)!
method: POST
path: /api/v1/orders
status: 201
steps:
- step: validateOrderCreation # (2)!
- step: saveOrder
- step: mapOrderResponse
- Exposes the use case as
POST /api/v1/orders. Leavetriggerout to use it only through injection. - Steps are referenced by name, and a step that binds nothing reads the one declared before it.
OrderRequest → OrderRequest → OrderEntity → OrderResponseis checked at startup.
Enact reads every file of that folder. See Definition files to keep them elsewhere, and Use cases to branch, join, skip or run steps at once instead of passing one value along.
4. Run it¶
curl -X POST localhost:8080/api/v1/orders \
-H 'Content-Type: application/json' \
-d '{"amount": 1.23, "productCount": 2}'
The enact-demo module is a complete, runnable example.