Skip to content

Commit

Permalink
Incorporate feedback about actions and functions (#572)
Browse files Browse the repository at this point in the history
* rephrase section

* moved section

* moved sample code

* hint

* Update java/application-services.md

Co-authored-by: BraunMatthias <[email protected]>

* hint about trigger actions and functions

* fixes

* Update java/application-services.md

* Update java/application-services.md

Co-authored-by: Marc Becker <[email protected]>

* Update java/application-services.md

Co-authored-by: Marc Becker <[email protected]>

* replaced ReviewEventContext with EventContext

* Revert "replaced ReviewEventContext with EventContext"

This reverts commit 7a53c33.

* use generic event context to trigger action

* fixes in event context sample, removed obsolete tip

* removed section Triggering Custom Events

* added details about specific service interfaces

* Update java/consumption-api.md

Co-authored-by: Marc Becker <[email protected]>

* Update java/consumption-api.md

Co-authored-by: Marc Becker <[email protected]>

* Update java/application-services.md

Co-authored-by: Marc Becker <[email protected]>

---------

Co-authored-by: BraunMatthias <[email protected]>
Co-authored-by: Marc Becker <[email protected]>
  • Loading branch information
3 people authored Dec 11, 2023
1 parent 6e276c9 commit ea1a01f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 55 deletions.
64 changes: 30 additions & 34 deletions java/application-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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
Expand Down Expand Up @@ -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<String, Object> result = (Map<String, Object>) 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

Expand Down
35 changes: 14 additions & 21 deletions java/consumption-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}

Expand Down

0 comments on commit ea1a01f

Please sign in to comment.