Skip to content

Commit

Permalink
docs(java): Add @CdsName to example (#1328)
Browse files Browse the repository at this point in the history
A section in "Event Handlers" mentions `@CdsName`, but does not show any
example. This commit adds an example and fixes a few typos/grammar
issues.

It also fixes the name `AddReviewContext`, which either changed in CAP
Java or was wrong before, because for the bound action,
`BooksAddReviewContext` is generated.
  • Loading branch information
bugwelle authored Oct 23, 2024
1 parent 8e39dfa commit ac28c74
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 16 deletions.
5 changes: 3 additions & 2 deletions java/event-handlers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Result result = context.getResult();
```

The getter and setter methods, still operate on the simple get/put API shown in the previous example. They just provide a type-safe layer on top of it.
The `as` method makes use of Java Proxies behind the scenes. Therefore an interface definition is all that is required to enable this functionality.
The `as` method makes use of Java Proxies behind the scenes. Therefore, an interface definition is all that is required to enable this functionality.

::: tip
Use these event-specific type-safe Event Context interfaces whenever possible.
Expand Down Expand Up @@ -183,6 +183,7 @@ public interface MyEventContext extends EventContext {
return EventContext.create(MyEventContext.class, null);
}

@CdsName("Param")
String getParam();
void setParam(String param);

Expand Down Expand Up @@ -215,7 +216,7 @@ import com.sap.cds.services.handler.annotations.ServiceName;
@Component
@ServiceName("AdminService")
public class AdminServiceHandler implements EventHandler {

// ...
}
```
:::
Expand Down
18 changes: 9 additions & 9 deletions java/event-handlers/indicating-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ throw new ServiceException(ErrorStatuses.CONFLICT, "Not enough stock available")
throw new ServiceException(ErrorStatuses.BAD_REQUEST, "No book title specified", originalException);
```

The OData V4 adapter turns all exceptions into an OData error response to indicate the error to the client.
The OData adapters turn all exceptions into an OData error response to indicate the error to the client.

## Messages

Expand Down Expand Up @@ -81,15 +81,15 @@ messages.throwIfError();
```

If there are any collected error messages, this method creates a [ServiceException](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/ServiceException.html) from _one_ of these error messages.
The OData V4 adapter turns this exception into an OData error response to indicate the error to the client. The remaining error messages are written into the `details` section of the error response.
The OData adapter turns this exception into an OData error response to indicate the error to the client. The remaining error messages are written into the `details` section of the error response.

If the CDS property [`cds.errors.combined`](../developing-applications/properties#cds-errors-combined) is set to true (default), `Messages.throwIfError()` is automatically called at the end of the `Before` handler phase to abort the event processing in case of errors. It is recommended to use the Messages API for validation errors and rely on the framework calling `Messages.throwIfError()` automatically, instead of throwing a `ServiceException`.


## Formatting and Localization

Texts passed to both `ServiceException` and the `Messages` API can be formatted and localized.
By default you can use [SLF4J's messaging formatting style](https://www.slf4j.org/api/org/slf4j/helpers/MessageFormatter.html) to format strings passed to both APIs.
By default, you can use [SLF4J's messaging formatting style](https://www.slf4j.org/api/org/slf4j/helpers/MessageFormatter.html) to format strings passed to both APIs.

```java
// message with placeholders
Expand Down Expand Up @@ -249,7 +249,7 @@ public void validateTitle(CdsCreateEventContext context, Books book) {
}
```
This also works for nested paths that with associations:
This also works for nested paths with associations:
``` java
@Before
Expand All @@ -273,7 +273,7 @@ The same applies to message targets that refer to an action or function input pa
``` java
@Before
public void validateReview(AddReviewContext context) {
public void validateReview(BooksAddReviewContext context) {
// ...
// event context contains the keys "reviewer", "rating", "title", "text",
Expand All @@ -285,7 +285,7 @@ public void validateReview(AddReviewContext context) {
// which is equivalent to using the typed API
throw new ServiceException(ErrorStatuses.BAD_REQUEST, "Invalid reviewer first name")
.messageTarget("reviewer", Reviewer_.class, r -> r.firstName());
.messageTarget(BooksAddReviewContext.REVIEWER, Reviewer_.class, r -> r.firstName());
// targeting "rating"
throw new ServiceException(ErrorStatuses.BAD_REQUEST, "Invalid review rating")
Expand All @@ -307,7 +307,7 @@ For the `addReview` action that is the `Books` entity, as in the following examp
``` java
@Before
public void validateReview(AddReviewContext context) {
public void validateReview(BooksAddReviewContext context) {
// ...
// referring to the bound entity `Books`
Expand Down Expand Up @@ -385,9 +385,9 @@ public class ExceptionServiceErrorMessagesHandler implements EventHandler {
Message message = messages.get(i);
if (CdsErrorStatuses.VALUE_OUT_OF_RANGE.getCodeString().equals(message.getCode())) { // filter by error code
if (Books.PRICE.equals(message.getTarget().getRef().targetSegment().id())) { // filter by target
messages.set(i, Message.create(Severity.ERROR, "The exceptional price is not in defined range!", message));
messages.set(i, Message.create(Message.Severity.ERROR, "The exceptional price is not in defined range!", message));
} else if (Books.STOCK.equals(message.getTarget().getRef().targetSegment().id())) {
messages.set(i, Message.create(Severity.ERROR, "The exceptional stock of specified items is not available!", message));
messages.set(i, Message.create(Message.Severity.ERROR, "The exceptional stock of specified items is not available!", message));
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions java/event-handlers/request-contexts.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public void afterHandler(EventContext context){

![The graphic is explained in the accompanying text.](./assets/switchprovidertenant.drawio.svg)

The application offers an action for one of its CDS entities. Within the action, a communication happens with a remote CAP service using an internal technical user from the provider account. The corresponding `on` handler of the action needs to create a new Request Context by calling `requestContext()`. Using the `systemUserProvider()` method, the existing user information is removed and the tenant is automatically set to the provider tenant. This allows the application to perform an HTTP call to the remote CAP service, which is secured using the pseudo-role `internal-user`.
The application offers an action for one of its CDS entities. Within the action, the application communicates with a remote CAP service using an internal technical user from the provider account. The corresponding `on` handler of the action needs to create a new Request Context by calling `requestContext()`. Using the `systemUserProvider()` method, the existing user information is removed and the tenant is automatically set to the provider tenant. This allows the application to perform an HTTP call to the remote CAP service, which is secured using the pseudo-role `internal-user`.

```java
@On(entity = Books_.CDS_NAME)
Expand Down Expand Up @@ -211,7 +211,7 @@ Similarly, it's possible to fully control the `UserInfo` instance provided in th
Some more examples:

- `modifyUser(user -> user.removeRole("read").setTenant(null).run(...)`: Creates a context with a user that is similar to the outer context but without role `read` and tenant.
- `modifyParameters(param -> param.setHeader("MY-HEADER", "my value"))`: Adds a header parameter `MY-HEADER:my value`.
- `modifyParameters(param -> param.setHeader("MY-HEADER", "my value"))`: Adds or sets a header parameter `MY-HEADER:my value`.

The modifications can be combined arbitrarily in fluent syntax.

Expand All @@ -222,14 +222,14 @@ Any modifications that you perform are applied on the information obtained by th
- A new nested Request Context, created within a scope that already has a Request Context, inherits copies of all values from its parent Request Context.
- Modifications in that scenario are applied on the inherited information.

Special care needs to be taken with regards to the CDS model and feature toggles.
Special care needs to be taken with regard to the CDS model and feature toggles.
- Both of these are _only_ determined in the initial Request Context.
- It's not possible to modify the CDS Model and feature toggles when creating a nested Request Context.

There's one exception to that rule: When modifying the user's tenant the CDS model is also redetermined.

::: tip
When changing the user's tenant it's required to open a new ChangeSet, to ensure that database transactions and connections are directed to the new tenant. In case you miss this step CAP Java SDK detects this error and prevent any database access to avoid leaking information between tenants.
When changing the user's tenant it's required to open a new [ChangeSet](./changeset-contexts#changeset-contexts), to ensure that database transactions and connections are directed to the new tenant. In case you miss this step CAP Java SDK detects this error and prevent any database access to avoid leaking information between tenants.
:::

## Registering Global Providers { #global-providers}
Expand Down Expand Up @@ -279,7 +279,8 @@ public class CustomUserInfoProvider implements UserInfoProvider {
}
}
if (userInfo != null) {
userInfo.setName(userInfo.getName().toLowerCase()); // Normalize user name
// Normalize user name
userInfo.setName(userInfo.getName().toLowerCase(Locale.ENGLISH));
}

return userInfo;
Expand Down

0 comments on commit ac28c74

Please sign in to comment.