problem-spring-web icon indicating copy to clipboard operation
problem-spring-web copied to clipboard

Rework Spring Specific Exception Handling

Open danielrohe opened this issue 2 years ago • 10 comments

Description

#817 - Analyze the similarities and differences between the handling of exceptions of this library and spring's problem-web. Remove default behavior for Spring-specific exceptions and integrate Problem-Web specifics.

Motivation and Context

Separates functionality that is provided by Spring from this library so that the library focuses on valuable extensions.

Types of changes

  • [X] Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • [ ] My change requires a change to the documentation.
  • [ ] I have updated the documentation accordingly.
  • [ ] I have added tests to cover my changes.

danielrohe avatar Feb 24 '23 15:02 danielrohe

removed handling of MissingServletRequestPartException because similar response

zalando-problem
status: 400
content-type: application/problem+json
{
  "title": "Bad Request",
  "status": 400,
  "detail": "Required part 'payload2' is not present."
}

spring-problem
status: 400
content-type: application/json
{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Required part 'payload2' is not present.",
  "instance":"/api/handler-multipart"
}

danielrohe avatar Feb 24 '23 15:02 danielrohe

removed handling of NoHandlerFoundException because similar response

zalando-problem
status: 404
content-type: application/problem+json
{
  "title":"Not Found",
  "status":404,
  "detail":"No endpoint <method> <request_url>."
}

spring-problem
status: 
content-type: application/json
{
  "type":"about:blank",
  "title":"Not Found",
  "status":404,
  "detail":"No endpoint <method> <request_url>.",
  "instance":"<request_url>"
}

danielrohe avatar Feb 24 '23 15:02 danielrohe

removed handling of ServletRequestBindingException which includes UnsatisfiedServletRequestParameterException, MissingRequestValueException, MissingMatrixVariableException, MissingPathVariableException, MissingRequestCookieException, MissingRequestHeaderException, because similar response

zalando-problem
status: 400
content-type: application/problem+json
{
  "title": "Bad Request",
  "status": 400,
  "detail": "Required request header 'X-Custom-Header' for method parameter type String is not present"
}

spring-problem
status: 400
content-type: application/json
{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Required header 'X-Custom-Header' is not present.",
  "instance":"/api/handler-headers"
}

danielrohe avatar Feb 24 '23 16:02 danielrohe

removed handling of MissingServletRequestParameterException because similar response

zalando-problem
status: 400
content-type: application/problem+json
{
  "title":"Bad Request",
  "status":400,
  "detail":"Required request parameter 'params1' for method parameter type String[] is not present"
}

spring-problem
status: 400
content-type: application/json
{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Required parameter 'params1' is not present.",
  "instance":"/api/handler-params"
}

danielrohe avatar Feb 24 '23 16:02 danielrohe

removed handling of HttpRequestMethodNotSupportedException because similar response

zalando-problem
status: 405
content-type: application/problem+json
{
  "title":"Method Not Allowed",
  "status":405,
  "detail":"Request method 'POST' is not supported"
}

spring-problem
status: 405
content-type: application/json
{
  "type":"about:blank",
  "title":"Method Not Allowed",
  "status":405,
  "detail":"Method 'POST' is not supported.",
  "instance":"/api/handler-problem"
}

danielrohe avatar Feb 24 '23 16:02 danielrohe

removed handling of HttpMediaTypeNotAcceptableException and HttpMediaNotSupportedException which are subclasses of HttpMediaTypeException because similar responses.

HttpMediaTypeNotAcceptableException

zalando-problem
status: 406
content-type: application/problem+json
{
  "title":"Not Acceptable",
  "status":406,
  "detail":"No acceptable representation"
}

spring-problem
status: 406
content-type: application/json
{
  "type":"about:blank",
  "title":"Not Acceptable",
  "status":406,
  "detail":"Acceptable representations: [application/json].",
  "instance":"/api/handler-ok"
}

HttpMediaTypeNotSupportedException


zalando-problem
status: 415
content-type: application/problem+json
{
  "title":"Unsupported Media Type",
  "status":415,
  "detail":"Content-Type 'application/atom+xml' is not supported"
}

spring-problem
status: 415
content-type: application/json
{
  "type":"about:blank",
  "title":"Unsupported Media Type",
  "status":415,
  "detail":"Content-Type 'application/atom+xml' is not supported.",
  "instance":"/api/handler-put"
}

danielrohe avatar Feb 24 '23 18:02 danielrohe

Interesting that spring doesn't seem to use the problem specific JSON media subtype

On Fri, 24 Feb 2023, 19:02 Daniel Rohe, @.***> wrote:

removed handling of HttpMediaTypeNotAcceptableException and HttpMediaNotSupportedException which are subclasses of HttpMediaTypeException because similar responses.

— Reply to this email directly, view it on GitHub https://github.com/zalando/problem-spring-web/pull/867#issuecomment-1444155524, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADI7HLLJUUE4KZM3EVJ6VLWZDZS5ANCNFSM6AAAAAAVG75VAM . You are receiving this because you are subscribed to this thread.Message ID: @.***>

whiskeysierra avatar Feb 24 '23 18:02 whiskeysierra

Interesting that spring doesn't seem to use the problem specific JSON media subtype

That's what the test cases show when running with spring's advice :)

danielrohe avatar Feb 24 '23 18:02 danielrohe

The handling of HttpMessageNotReadableException in MessageNotReadableAdviceTrait with Spring Problem Exception handling is slightly different. This library uses the exception message that unveils possible application internals in details attribute where as the Spring problem handling uses a common string in details attribute. In my opinion the Spring handling is safer as it does not expose application internals. So I'm going to remove handling of this exception, too

zalando-problem
status: 400
content-type: application/problem+json
{
  "title":"Bad Request",
  "status":400,
  "detail":"JSON parse error: Cannot deserialize value of type `java.math.BigDecimal` from String \"foobar\": not a valid representation"
}

{
  "title":"Bad Request",
  "status":400,
  "detail":"JSON parse error: Unexpected end-of-input: expected close marker for Object (start marker at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1])"
}

{
  "title":"Bad Request",
  "status":400,
  "detail":"JSON parse error: Cannot construct instance of `org.zalando.problem.spring.web.advice.example.User` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)"
}

{
  "title":"Bad Request",
  "status":400,
  "detail":"JSON parse error: Cannot deserialize value of type `java.util.LinkedHashMap<java.lang.String,java.lang.Object>` from Array value (token `JsonToken.START_ARRAY`)"
}

{
  "title":"Bad Request",
  "status":400,
  "detail":"Required request body is missing: public org.springframework.http.ResponseEntity<java.lang.String> org.zalando.problem.spring.web.advice.example.ExampleRestController.put(java.lang.String)"
}
spring-problem
status: 400
content-type: application/json
{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to read request",
  "instance":"/api/json-decimal"
}

{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to read request",
  "instance":"/api/json-object"
}

{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to read request",
  "instance":"/api/json-user"
}

{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to read request",
  "instance":"/api/json-object"
}

{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to read request",
  "instance":"/api/handler-put"
}

danielrohe avatar Feb 24 '23 18:02 danielrohe

removed handling of TypeMismatchException because of similar response.

zalando-problem
status: 400
content-type: application/problem+json
{
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to convert value of type 'java.lang.String' to required type 'java.time.OffsetDateTime'; Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam java.time.OffsetDateTime] for value 'abc'"
}

spring-problem
status: 400
content-type: application/json
{
  "type":"about:blank",
  "title":"Bad Request",
  "status":400,
  "detail":"Failed to convert 'null' with value: 'abc'",
  "instance":"/api/handler-conversion"
}

danielrohe avatar Feb 24 '23 18:02 danielrohe