From 6e296258bbebe73e18a956634ca9c6f0ee4d58f9 Mon Sep 17 00:00:00 2001 From: Jennifer Stamm Date: Fri, 25 Apr 2025 16:57:58 +0200 Subject: [PATCH 1/3] init flows --- java/flows.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 java/flows.md diff --git a/java/flows.md b/java/flows.md new file mode 100644 index 000000000..5081f30f7 --- /dev/null +++ b/java/flows.md @@ -0,0 +1,126 @@ +--- +synopsis: > + Learn about the flow feature in CAP Java. +status: draft +--- + +# Flow: Modeling State Transitions + + +{{ $frontmatter.synopsis }} + +Use the flow feature to define flows in your CDS model. The feature ensures that transitions between states are explicitly modeled, validated, and performed in a controlled manner. + +## Enabling Flows { #enabling-flows } + +To use the flow feature, add a dependency to [cds-feature-flows](TODO) in the `srv/pom.xml` file of your service: + +```xml + + com.sap.cds + cds-feature-flows + runtime + +``` + +## Modeling Flows { #modeling-flows } + +Flows are defined in the CDS model using annotations. Flows consist out of one status element and one or more _flow_ actions. Annotate the status element with `@flow.status`. Define all transitions as bound actions (TODO link /cap/docs/cds/cdl#bound-actions), list the valid entry states using `@flow.from` and the target state using `@flow.to`. + +::: tip Best Practice +We recommend to always use `@flow.status` in combination with `@readonly`. +This gives full control over all transitions to the flow feature. +::: + +### Details +Let's dive into the details of the annotations: + +`@flow.status` +- This annotation is mandatory. +- The annotated element must be either an enum or an association to an enum. +- Only one status element per entity is supported. +- Draft-enabled entities are supported. +- `null` is **not** a valid state. Model your empty state explicitly. + +`@flow.from` +- This annotation is optional. Leave it out and all states are valid entry states. +- This annotation's value type is an array. Each array element's type must match the status element. + +`@flow.to` +- This annotation is optional. Leave it out and the target state is the entry state. +- This annotation's value type must match the status element. + +Please note, while both `@flow.from` and `@flow.to` are optional, one of them is mandatory to mark the action as a flow action. + +## Using and Extending Flows +When using the flow feature, default handlers (todo link /docs/java/cqn-services/application-services#implement-event-handler) are provided for your flow actions. + +The default `Before` handler will validate that your entity instance is in a valid entry state. A validation error will return a 409 Http Status Code. + +The default `On` handler will complete the action for void return types. + +The default `After` handler will process the transition and update the status to the target state. + +### Custom Event Handler { #custom-event-handler} +You can extend the default flow handlers with an event handler to implement custom event logic that should run on a transition. + +TODO: node example: less than 100, more than 100 + +TODO: does readonly mean using the persistence service in custom handlers? + + +## Sample { #sample } + +Let's take a look at the [CAP SFLIGHT App](https://github.com/SAP-samples/cap-sflight) sample and how we can update it using the flow feature. + +The `cds-feature-flow` has been added to the dependenies. + +Following is an extract of the relevant parts of the entity model that has been extended with the `@flow.status` annotation: + +```cds +entity Travel : managed { + key TravelUUID : UUID; + TravelID : Integer default 0 @readonly; + @flow.status + TravelStatus : Association to TravelStatus default 'O' @readonly; +}; + +type TravelStatusCode : String(1) enum { + Open = 'O'; + Accepted = 'A'; + Canceled = 'X'; +}; +``` + +Now, let's have a look at the flow annotations in the service model: + +```cds +service TravelService @(path:'/processor') { + + entity Travel as projection on my.Travel actions { + @(flow: { + from:[ Open ], + to: Canceled + }) + action rejectTravel(); + @(flow: { + from:[ Open ], + to: Accepted + }) + action acceptTravel(); + }; + +} +``` + +We can simply remove the [AcceptRejectHandler](https://github.com/SAP-samples/cap-sflight/blob/main/srv/src/main/java/com/sap/cap/sflight/processor/AcceptRejectHandler.java). All of the logic is taken care of by the flow feature. The flow feature will validate that entry state is `Open`. The flow feature will transit the status to `Accepted` and `Canceled` respectively. + +TODO: validate that draft will work the same as in contracts/tests. It looks different here. + + + + From 04e42ab2e9067e03691a8494bda089d33625ee51 Mon Sep 17 00:00:00 2001 From: Jennifer Stamm Date: Fri, 25 Apr 2025 17:00:35 +0200 Subject: [PATCH 2/3] add todo --- java/flows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/flows.md b/java/flows.md index 5081f30f7..2acdffc2c 100644 --- a/java/flows.md +++ b/java/flows.md @@ -1,7 +1,7 @@ --- synopsis: > Learn about the flow feature in CAP Java. -status: draft +status: draft TODO: released (only valid status) --- # Flow: Modeling State Transitions From ed3d02718e592ce448eb3e204c4cc41aae235a2f Mon Sep 17 00:00:00 2001 From: Jennifer Stamm Date: Tue, 29 Apr 2025 11:32:30 +0200 Subject: [PATCH 3/3] PR feedback --- java/flows.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/java/flows.md b/java/flows.md index 2acdffc2c..e3baa0646 100644 --- a/java/flows.md +++ b/java/flows.md @@ -1,7 +1,7 @@ --- synopsis: > Learn about the flow feature in CAP Java. -status: draft TODO: released (only valid status) +status: released --- # Flow: Modeling State Transitions @@ -22,8 +22,8 @@ To use the flow feature, add a dependency to [cds-feature-flows](TODO) in the `s ```xml com.sap.cds - cds-feature-flows - runtime + cds-feature-flows + runtime ``` @@ -77,9 +77,9 @@ TODO: does readonly mean using the persistence service in custom handlers? Let's take a look at the [CAP SFLIGHT App](https://github.com/SAP-samples/cap-sflight) sample and how we can update it using the flow feature. -The `cds-feature-flow` has been added to the dependenies. +Let's add `cds-feature-flow` to the dependencies. -Following is an extract of the relevant parts of the entity model that has been extended with the `@flow.status` annotation: +Annotate the travel status element with the `@flow.status` annotation. Following is an extract of the relevant parts of the entity model: ```cds entity Travel : managed { @@ -89,6 +89,10 @@ entity Travel : managed { TravelStatus : Association to TravelStatus default 'O' @readonly; }; +entity TravelStatus : CodeList { + key code : TravelStatusCode; +} + type TravelStatusCode : String(1) enum { Open = 'O'; Accepted = 'A'; @@ -96,7 +100,7 @@ type TravelStatusCode : String(1) enum { }; ``` -Now, let's have a look at the flow annotations in the service model: +Now, let's have a look at the added flow annotations in the service model: ```cds service TravelService @(path:'/processor') { @@ -117,7 +121,8 @@ service TravelService @(path:'/processor') { } ``` -We can simply remove the [AcceptRejectHandler](https://github.com/SAP-samples/cap-sflight/blob/main/srv/src/main/java/com/sap/cap/sflight/processor/AcceptRejectHandler.java). All of the logic is taken care of by the flow feature. The flow feature will validate that entry state is `Open`. The flow feature will transit the status to `Accepted` and `Canceled` respectively. +Finally, in the CAP SFLIGHT App, no action handler is needed. All of the logic is taken care of by the flow feature. The flow feature will validate that entry state is `Open`. The flow feature will transit the status to `Accepted` and `Canceled` respectively. +If you followed along, with the CAP SFLIGHT App, simply remove the [AcceptRejectHandler](https://github.com/SAP-samples/cap-sflight/blob/main/srv/src/main/java/com/sap/cap/sflight/processor/AcceptRejectHandler.java). TODO: validate that draft will work the same as in contracts/tests. It looks different here.