diff --git a/java/application-services.md b/java/application-services.md index 31e087b70..1fe0c285e 100644 --- a/java/application-services.md +++ b/java/application-services.md @@ -204,7 +204,7 @@ Actions or functions are handled - just like CRUD events - using event handlers. ### Implement Event Handler -The CAP Java runtime doesn't provide any default `On` handlers. Actions and functions are therefore implemented through event handlers. For each action or function an event handler of the [`On`](provisioning-api#on) phase should be defined, which implements the business logic and provides the return value of the operation, if applicable. The event handler needs to take care of [completing the event processing](provisioning-api#eventcompletion). If an action or function is __bound to an entity__, the entity needs to be specified while registering the event handler. The following example shows how to implement an event handler for an action: +The CAP Java runtime doesn't provide any default `On` handlers for actions and functions. For each action or function an event handler of the [`On`](provisioning-api#on) phase should be defined, which implements the business logic and provides the return value of the operation, if applicable. The event handler needs to take care of [completing the event processing](provisioning-api#eventcompletion). If an action or function is __bound to an entity__, the entity needs to be specified while registering the event handler. The following example shows how to implement an event handler for an action: Given this CDS model: @@ -224,6 +224,30 @@ service CatalogService { } ``` +The `cds-maven-plugin` generates event context interfaces for the action or function, based on its CDS model definition. These event context interfaces provide direct access to the parameters and the return value of the action or function. +For bound actions or functions the event context interface provides a [CqnSelect](query-api#select) statement, which targets the entity the action or function was triggered on. + +Action-specific event context, generated by the CAP Java SDK Maven Plugin: + +```java +@EventName("review") +public interface ReviewEventContext extends EventContext { + + // CqnSelect that points to the entity the action was called on + CqnSelect getCqn(); + void setCqn(CqnSelect select); + + // The 'stars' input parameter + Integer getStars(); + void setStars(Integer stars); + + // The return value + void setResult(Reviews review); + Reviews getResult(); + +} +``` + The event handler registration and implementation is as follows: ```java @@ -284,46 +308,18 @@ Now, just call the review action from custom handler code: ... ``` -Besides that, the `cds-maven-plugin` generates also event-specific event context interfaces for the action or function, based on its CDS model definition. These event context interfaces give direct access to the parameters and the return value of the action or function. -For bound actions or functions the event context interface provides a [CqnSelect](query-api#select) statement, which targets the entity the action or function was triggered on. - -Event-specific event context, generated by the CAP Java SDK Maven Plugin: +Alternatively, the event context can be used to trigger the action or function. This approach is useful for generic use cases, where typed interfaces are not available. The event context needs to be filled with the parameter values and emitted on the service: ```java -@EventName("review") -public interface ReviewEventContext extends EventContext { - - // CqnSelect that points to the entity the action was called on - CqnSelect getCqn(); - void setCqn(CqnSelect select); - - // The 'stars' input parameter - Integer getStars(); - void setStars(Integer stars); - - // The return value - void setResult(Reviews review); - Reviews getResult(); - -} -``` - -To trigger the action or function, the event context needs to be filled with the parameter values and emitted on the service: - -```java - ReviewEventContext context = ReviewEventContext.create(); - context.setCqn(Select.from(BOOKS).byId("myBookId")); - context.setStars(review.getRating()); + EventContext context = EventContext.create("review", "CatalogService.Books"); + context.put("cqn", Select.from("CatalogService.Books").byId("myBookId")); + context.put("rating", review.getRating()); this.catService.emit(context); - Reviews result = context.getResult(); + Map result = (Map) context.get("result"); ``` -::: tip -The unused methods `setCqn(CqnSelect)`, `setStars(Integer)`, and `getResult()` are useful when [triggering the event](consumption-api#customevents) on the service. -::: - ## Best Practices and FAQs diff --git a/java/consumption-api.md b/java/consumption-api.md index 941feafca..4ffb55853 100644 --- a/java/consumption-api.md +++ b/java/consumption-api.md @@ -47,6 +47,12 @@ Application Services are created with the fully qualified name of their CDS defi ApplicationService adminService = catalog.getService(ApplicationService.class, "AdminService"); ``` +As of version 2.4.0, the [CAP Java SDK Maven Plugin](./development/#cds-maven-plugin) is capable of generating specific interfaces for services in the CDS model. These service interfaces also provide Java methods for actions and functions, which allows easily calling actions and functions with their parameters. These specific interfaces can also be used to get access to the service: + +```java +AdminService adminService = catalog.getService(AdminService.class, "AdminService"); +``` + Technical services, like the Persistence Service have a `DEFAULT_NAME` constant defined in their interface: ```java @@ -69,36 +75,23 @@ public class EventHandlerClass implements EventHandler { } ``` -### Triggering Custom Events { #customevents} - -Services can be extended with custom events, for example through [Actions and Functions](application-services#actions). -In that case, the custom event can be triggered by passing the corresponding Event Context to the `emit` method of the service. -In case of model-defined actions and functions, the CDS Maven Plugin is capable of generating Event Context interfaces. -Alternatively developers can always define their own custom event contexts. - -In addition developers can define their own API layer around the `emit` method, to make it more convenient to trigger the custom event. -The following example shows how this can be achieved for the [action example from the Application Services chapter](application-services#actions) in a Spring Boot application. +Instead of the generic service interface, also the more specific service interfaces can be injected: ```java -import static bookshop.Bookshop_.BOOKS; - @Component -public class CatalogServiceAPI { +public class EventHandlerClass implements EventHandler { @Autowired - @Qualifier(CatalogService_.CDS_NAME) - CqnService catalogService; // get access to the service + private PersistenceService db; - public Reviews review(String bookId, Integer stars) { - ReviewEventContext context = ReviewEventContext.create(); - context.setCqn(Select.from(BOOKS).byId(bookId)); // set target entity - context.setStars(stars); // set input parameters - catalogService.emit(context); // emit the event - return context.getResult(); // return the result - } + @Autowired + private AdminService adminService; } ``` +::: tip +For the injection of specific service interfaces the annotation `@Qualifier` is usually not required. +::: ## Services Accepting CQN Queries { #cdsservices}