You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prefer showing targets via Messages API, as this allows collecting
multiple error messages and should be preferred in applications.
Also reduced usage of the String-based API, as this has limitations in
draft messages scenarios.
---------
Co-authored-by: René Jeglinsky <[email protected]>
Copy file name to clipboardExpand all lines: java/event-handlers/indicating-errors.md
+32-68Lines changed: 32 additions & 68 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -149,8 +149,7 @@ To know which error codes and messages are available by default, you can have a
149
149
## Target
150
150
151
151
When SAP Fiori interprets messages it can handle an additional `target` property, which, for example, specifies which element of an entity the message refers to. SAP Fiori can use this information to display the message along the corresponding field on the UI.
152
-
When specifying messages in the `sap-messages` HTTP header, SAP Fiori mostly ignores the `target` value.
153
-
Therefore, specifying the `target` can only correctly be used when throwing a `ServiceException` as SAP Fiori correctly handles the `target` property in OData V4 error responses.
152
+
SAP Fiori interprets `target` property in OData V4 error messages and [draft state messages](../../advanced/fiori#validating-drafts). You can specify the `target` when throwing a `ServiceException` or when setting a validation error using the [Messages API](#messages).
154
153
155
154
A message target is always relative to an input parameter in the event context.
156
155
For CRUD-based events this is always the `cqn` parameter, which represents and carries the payload of the request.
@@ -162,7 +161,7 @@ By default a message target always refers to the CQN statement of the event. In
162
161
As CRUD event handlers are often called from within bound actions or functions (e.g. `draftActivate`), CAP's OData adapter adds a parameter prefix to a message target referring to the `cqn` parameter only when required.
163
162
164
163
::: info
165
-
When using the `target(String)` API, which specifices the full target as a `String`, no additional parameter prefixes are added by CAP's OData adapter. The `target` value is used as specified.
164
+
When using the `target(String)` API, which specifies the full target as a `String`, no additional parameter prefixes are added by CAP's OData adapter. When using this API, [draft state messages](../../advanced/fiori#validating-drafts) can't be invalidated automatically on `PATCH`.
166
165
:::
167
166
168
167
Let's illustrate this with the following example:
@@ -208,63 +207,39 @@ Here, we have a `CatalogService` that exposes et al. the `Books` entity and a `B
208
207
209
208
### CRUD Events
210
209
211
-
Within a `Before` handler that triggers on inserts of new books a message target can only refer to the `cqn` parameter:
210
+
Within a `Before` handler that triggers on inserts of new books, a message target can only refer to the `cqn` parameter. You can use generic `String`-based APIs or a typed API backed by the interfaces generated from the CDS model:
thrownewServiceException(ErrorStatuses.BAD_REQUEST, "No title specified")
250
-
.messageTarget(Books_.class, b -> b.title());
251
-
}
252
-
```
229
+
Depending on the OData request context, the resulting target in this example is either `title` (assuming a `POST` or `PATCH` request) or `in/title` (assuming a bound action like `draftActivate`).
253
230
254
-
This also works for nested paths with associations:
231
+
You can also specify targets that point to elements within associations:
thrownewServiceException(ErrorStatuses.BAD_REQUEST, "Invalid book description")
317
-
.messageTarget(b -> b.get("descr"));
318
-
319
-
// or (using the typed API, referring to "cqn" implicitly)
320
-
thrownewServiceException(ErrorStatuses.BAD_REQUEST, "Invalid book description")
321
-
.messageTarget(Books_.class, b -> b.descr());
285
+
messages.error("Invalid book description").target(b -> b.get("descr"));
322
286
323
-
// which is the same as using plain string
324
-
thrownewServiceException(ErrorStatuses.BAD_REQUEST, "Invalid book description")
325
-
.messageTarget("in/descr");
287
+
// or using the typed API
288
+
messages.error("Invalid book description").target(Books_.class, b -> b.descr());
326
289
}
327
290
```
328
291
292
+
In the case of OData the resulting target is `in/descr`, assuming the default name `in` is used for the binding parameter name.
293
+
329
294
::: tip
330
-
The previous examples showcase the target creation with the `ServiceException` API, but the same can be done with the `Message` API and the respective `target(...)` methods.
295
+
The previous examples showcase the target creation with the `Messages` API, but the same can be done with the `ServiceException` API and the respective `messageTarget(...)` methods.
331
296
:::
332
297
333
-
334
298
## Error Handler { #errorhandler}
335
299
336
300
An [exception](#exceptions) thrown in an event handler will stop the processing of the request. As part of that, protocol adapters trigger the `ERROR_RESPONSE` event of the [Application Lifecycle Service](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/application/ApplicationLifecycleService.html). By default, this event combines the thrown exception and the [messages](#messages) from the `RequestContext` in a list to produce the error response. OData V4 and V2 protocol adapters will use this list to create an OData error response with the first entry being the main error and the remaining entries in the details section.
0 commit comments