-
Notifications
You must be signed in to change notification settings - Fork 535
7134 refactor errorhandlers #7136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
poikilotherm
wants to merge
11
commits into
IQSS:develop
from
poikilotherm:7134-refactor-errorhandlers
Closed
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
24c464b
Remove obsolete handlers first. #7134
poikilotherm 5961abf
Refactor ThrowableHandler to provide a common set of logging and resp…
poikilotherm 7ebf241
Dogfooding the new methods to the ThrowableHandler toResponse(). #7134
poikilotherm 3584e19
Finally implement the WebApplicationExceptionHandler, reducing duplic…
poikilotherm eec0641
Further reduce boilerplate and duplicated code by removing handlers f…
poikilotherm c9bca3a
Mask unblock-key query parameter in logs and responses to avoid clear…
poikilotherm ead241d
Add default message from Jersey WebApplicationException message to JS…
poikilotherm e17a1ee
Create a new unified JSON responses and logging infrastructure for th…
poikilotherm 5193cce
Switch ThrowableHandler and WebApplicationExceptionHandler to the new…
poikilotherm 485ff80
Add docs about API development and exceptiond handling. #7134
poikilotherm a08b290
Rename JSONResponseBuilder into more CamelCased JsonResponseBuilder. …
poikilotherm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| API development | ||
| =============== | ||
|
|
||
| All features of Dataverse are mostly "API too", if not "API first". Making APIs great again helps building integrations | ||
| for Dataverse with third party systems, automation and many other use cases. | ||
|
|
||
| Dataverse API is based on `Jersey <https://eclipse-ee4j.github.io/jersey>`_ using JSON all over for both requests and | ||
| responses. | ||
|
|
||
| Response Creation | ||
| ----------------- | ||
|
|
||
| To provide a consistent experience for developers, integrators and users, it's important to streamline what is sent | ||
| over the wire as responses. | ||
|
|
||
| .. warning:: To be extended and changed with refactoring of API code to align code paths. | ||
|
|
||
| `JsonResponseBuilder` | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| To make response building easier and aligned throught the API code base, a factory and decorator pattern based helper | ||
| utility has been introduced in `edu.harvard.iq.dataverse.api.util.JsonResponseBuilder`_. | ||
|
|
||
| *Hint: Right now, only the exception handlers listed below use it.* | ||
|
|
||
| Create a response builder by using ``JsonResponseBuilder.error()``. | ||
|
|
||
| 1. Add decorations as you see fit (messages, incident identifiers, ...). For current options, see the classes extensive Javadoc. | ||
| 2. You can also use the same builder to log your response for the admins by using ``.log()`` before you ``.build()``. | ||
| 3. When writing a filter for the servlet container, you may use ``.apply()`` to sent a response looking and feeling like | ||
| when used from a JAX-RS endpoint method. | ||
|
|
||
| .. code-block:: java | ||
| :caption: A full fledged example (copied from the ``ThrowableHandler`` described below) | ||
|
|
||
| // Create an instance (contains a human friendly message by default, but may be overridden) | ||
| return JSONResponseBuilder.error(Response.Status.INTERNAL_SERVER_ERROR) | ||
| // Add an identifier, so admins can find exceptions easier in the logs when users report | ||
| .randomIncidentId() | ||
| // Hint what went wrong internally by adding exception name & cause | ||
| .internalError(ex) | ||
| // Add the complete URL & HTTP method the client tried to use | ||
| .request(request) | ||
| // Write all this to the logs, including the stack trace from the exception | ||
| .log(logger, Level.SEVERE, Optional.of(ex)) | ||
| // Build the JAX-RS response. Done! | ||
| .build(); | ||
|
|
||
| Exception Handling | ||
| ------------------ | ||
|
|
||
| We have to differ between three types of exceptions thrown during API usage: | ||
|
|
||
| 1. Servlet exceptions, based on `javax.servlet.ServletException <https://jakarta.ee/specifications/platform/8/apidocs/javax/servlet/ServletException.html>`_ | ||
| 2. JAX-RS-native exceptions, based on `javax.ws.rs.WebApplicationException <https://jakarta.ee/specifications/platform/8/apidocs/javax/ws/rs/WebApplicationException.html>`_ | ||
| 3. Any other Java exception | ||
|
|
||
| When accessing the API, requests are handled by the servlet container before handing over to Jersey and from there to | ||
| the lower layers of bean validation, database connections and all other stuff you might use through the API: | ||
|
|
||
| .. graphviz:: | ||
|
|
||
| digraph G { | ||
| rankdir = LR | ||
|
|
||
| node [shape=plain] Client; | ||
| node [shape=egg] Network; | ||
|
|
||
| subgraph cluster_0 { | ||
| node [shape=box,label="Filters, ..."] F; | ||
| node [shape=box,label="JAX-RS/Jersey"] J; | ||
| node [shape=box,label="Services/Persistence/..."] D; | ||
|
|
||
| label = "Servlet Container"; | ||
| color = black; | ||
| } | ||
| Client -> Network -> F -> J -> D; | ||
| } | ||
|
|
||
| Exceptions before handing over to JAX-RS | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| The servlet container usually offers limited options to handle errors in elegant ways for an API, which is why you want | ||
| to avoid throwing exceptions there. However, it is possible: `see examples by Eugen Baeldung <https://www.baeldung.com/servlet-exceptions>`_ | ||
|
|
||
| You better avoid throwing exceptions from places like | ||
| `Filter <https://jakarta.ee/specifications/platform/8/apidocs/javax/servlet/Filter.html>`_\ s or similar, as those | ||
| require specialized code handling instead of going with the below JAX-RS exception handling. | ||
|
|
||
| Exceptions after handing over to JAX-RS | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| Cases 2) and 3) above are both happening in code easy to control in API code without fiddling with ``web.xml`` or similar. | ||
|
|
||
| Easy to follow code examples and explanations: | ||
|
|
||
| - https://www.baeldung.com/jersey-rest-api-with-spring#using-exceptionmapper (never mind this is about Spring, the technology is the same!) | ||
| - https://www.baeldung.com/jersey-bean-validation#custom-exception-handler | ||
|
|
||
| For Dataverse, all API exception handlers live in package `edu.harvard.iq.dataverse.api.errorhandlers`_. | ||
| *Remember, this does not handle exceptions popping via web UI, thus not served by Jersey JAX-RS!* | ||
|
|
||
| 1. ``ThrowableHandler`` catches any Java exception thrown and uncatched in business logic (either by accident or on purpose) | ||
| or not having a more specialized ``ExceptionMapper``. It allows for handing out nice JSON error messages to users and | ||
| detailed logging for admins. | ||
| 2. ``WebApplicationExceptionHandler`` catches all JAX-RS typed exceptions, which usually depict HTTP statuses. | ||
| Those "native" exceptions are commonly used for redirection, client and server errors, so better watch out what you | ||
| catch and what you do when the fish bit. | ||
| 3. ``ConstraintViolationExceptionHandler`` allows for catching and formating bean validation exception from any | ||
| layer of validation (JAX-RS itself, persistence, ...) | ||
| 4. ``JsonParseExceptionHandler`` catches and formats error messages when a user or admin send an invalid JSON document | ||
| to and endpoint and validation failed. (Usually contains hints about what is wrong...) | ||
|
|
||
| .. _edu.harvard.iq.dataverse.api.errorhandlers: https://github.com/IQSS/dataverse/tree/develop/src/main/java/edu/harvard/iq/dataverse/api/errorhandlers | ||
| .. _edu.harvard.iq.dataverse.api.util.JSONResponseBuilder: https://github.com/IQSS/dataverse/tree/develop/src/main/java/edu/harvard/iq/dataverse/api/util/JSONResponseBuilder.java | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 0 additions & 38 deletions
38
...ain/java/edu/harvard/iq/dataverse/api/errorhandlers/ArrayOutOfBoundsExceptionHandler.java
This file was deleted.
Oops, something went wrong.
49 changes: 0 additions & 49 deletions
49
src/main/java/edu/harvard/iq/dataverse/api/errorhandlers/BadRequestExceptionHandler.java
This file was deleted.
Oops, something went wrong.
36 changes: 0 additions & 36 deletions
36
src/main/java/edu/harvard/iq/dataverse/api/errorhandlers/ForbiddenExceptionHandler.java
This file was deleted.
Oops, something went wrong.
39 changes: 0 additions & 39 deletions
39
.../java/edu/harvard/iq/dataverse/api/errorhandlers/InternalServerErrorExceptionHandler.java
This file was deleted.
Oops, something went wrong.
31 changes: 0 additions & 31 deletions
31
src/main/java/edu/harvard/iq/dataverse/api/errorhandlers/NotAllowedExceptionHandler.java
This file was deleted.
Oops, something went wrong.
43 changes: 0 additions & 43 deletions
43
src/main/java/edu/harvard/iq/dataverse/api/errorhandlers/NotFoundExceptionHandler.java
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really minor tweak:
uncatchedmight better be expressed asuncaughtornot caught