Skip to content
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

RESTEasy ExceptionMapper is not called when using Hibernate Validator on QueryParams #12006

Closed
tlvlp opened this issue Sep 9, 2020 · 12 comments
Assignees
Labels
area/hibernate-validator Hibernate Validator kind/question Further information is requested

Comments

@tlvlp
Copy link

tlvlp commented Sep 9, 2020

Describe the bug
When using Hibernate validator to check query parameters in a RestEasy endpoint the validation error is returned before it could be caught and altered by a custom ExceptionMapper.

Expected behavior
ExceptionMapper should catch and be able to override all exception responses in the controller.

Actual behavior
The hibernate validation error response is returned to the caller without even calling the ExceptionMapper.

To Reproduce

ExceptionMapper. I'm using "not implemented" as the default exception to be easy to spot in the response.

@Provider
public class ExceptionMapperConfig implements ExceptionMapper<Throwable> {

    @Override
    public Response toResponse(Throwable e) {
        Response.Status status = NOT_IMPLEMENTED;
        // business logic for overriding the status is omitted

        return Response
                .status(status)
                .entity(e.getMessage())
                .type(MediaType.TEXT_PLAIN)
                .build();
    }
}

Case 1: Controller with Hibernate Validator:

    @GET
    @Path("/hello")
    @Produces(MediaType.APPLICATION_JSON)
    public String hello(@QueryParam @NotNull @NotEmpty String hello) {
        return hello;
    }

When calling it without a @QueryParam (violating @NotNull) the default Hibernate response is returned,
not calling ExceptionMapper at all:

http :8080/hello

HTTP/1.1 400 Bad Request
Content-Length: 299
Content-Type: application/json
validation-exception: true

{
    "classViolations": [],
    "exception": null,
    "parameterViolations": [
        {
            "constraintType": "PARAMETER",
            "message": "must not be null",
            "path": "hello.hello",
            "value": ""
        },
        {
            "constraintType": "PARAMETER",
            "message": "must not be empty",
            "path": "hello.hello",
            "value": ""
        }
    ],
    "propertyViolations": [],
    "returnValueViolations": []
}

Case 2: Controller without a Hibernate Validator:

    @GET
    @Path("/hello")
    @Produces(MediaType.APPLICATION_JSON)
    public String hello(@QueryParam String hello) {
        throw new RuntimeException("custom exception");
    }

When calling it and running into any exception during execution they will be properly caught and handled by the ExceptionMapper:

http :8080/hello
HTTP/1.1 501 Not Implemented
Content-Length: 16
Content-Type: text/plain;charset=UTF-8

custom exception

Environment (please complete the following information):

  • Quarkus 1.7.2.Final
  • Maven
  • Running in dev-mode UPDATE: the same is true for running a packaged jar. Haven't tested in native.
  • IntelliJ IDEA 2020.2.1
@tlvlp tlvlp added the kind/bug Something isn't working label Sep 9, 2020
@quarkusbot
Copy link

/cc @gsmet

@quarkusbot quarkusbot added the area/hibernate-validator Hibernate Validator label Sep 9, 2020
@geoand
Copy link
Contributor

geoand commented Sep 9, 2020

Unless I am reading this wrong, I am pretty sure what you are seeing is the desired behavior, because JAX-RS will use the ExceptionMapper whose generic type best matches the exception - which is QuarkusRestViolationExceptionMapper in this case (this is JAX-RS spec behavior).

So to get the described behavior, you need to use the specific exception type you want to handle in your exception mapper.

@gsmet do you agree? If so, we can close this issue.

@tlvlp
Copy link
Author

tlvlp commented Sep 9, 2020

@geoand thanks, it makes sense.

What I was trying to achieve is to have a central exception mapper, assuming that it would override all exception mappers, instead of creating a separate class for each exception type and having other handlers working in the background without being clearly visible for whoever has to maintain the code after me.

@geoand
Copy link
Contributor

geoand commented Sep 9, 2020

Yeah, I don't think you can do that AFAIK

@gsmet
Copy link
Member

gsmet commented Sep 9, 2020

I don't know if @Priority would help there. Maybe @asoldano can say for sure?

@asoldano
Copy link
Contributor

CC @ronsigal

@kostacasa
Copy link

kostacasa commented Sep 11, 2020

I also tried to define a "catch-all" style ExceptionMapper and ran into this issue. @priority didn't do the trick for me. There are many different ExceptionMappers defined on the classpath that "overtake" exceptions and return all sorts of weird and unpredictable responses. This is undesirable behavior, especially when trying to standardize an API error response format.

@fxnn
Copy link

fxnn commented Oct 27, 2020

@geoand

Unless I am reading this wrong, I am pretty sure what you are seeing is the desired behavior, because JAX-RS will use the ExceptionMapper whose generic type best matches the exception - which is QuarkusRestViolationExceptionMapper in this case (this is JAX-RS spec behavior).

Thank you for the information. Can you please check that? I can't find anything about that class.

Also, when just getting the 400 response, it's hard to find out how to change it, so it should be documented -- I guess in the validation guide.

@geoand
Copy link
Contributor

geoand commented Oct 27, 2020

@geoand

Unless I am reading this wrong, I am pretty sure what you are seeing is the desired behavior, because JAX-RS will use the ExceptionMapper whose generic type best matches the exception - which is QuarkusRestViolationExceptionMapper in this case (this is JAX-RS spec behavior).

Thank you for the information. Can you please check that? I can't find anything about that class.

Check what exactly?

Also, when just getting the 400 response, it's hard to find out how to change it, so it should be documented -- I guess in the validation guide.

I'm not really following here, can you explain?

@fxnn
Copy link

fxnn commented Oct 27, 2020

Unless I am reading this wrong, I am pretty sure what you are seeing is the desired behavior, because JAX-RS will use the ExceptionMapper whose generic type best matches the exception - which is QuarkusRestViolationExceptionMapper in this case (this is JAX-RS spec behavior).

Thank you for the information. Can you please check that? I can't find anything about that class.

Check what exactly?

The name of the class you mentioned. As my links show, there's no such class in the Quarkus source code. But meanwhile, I think you meant io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyViolationExceptionMapper, right?

Also, when just getting the 400 response, it's hard to find out how to change it, so it should be documented -- I guess in the validation guide.

I'm not really following here, can you explain?

Sorry. As a developer using Quarkus, when I see that my application returns just the 400 Bad Request created by the ResteasyViolationExceptionMapper, but I want my application to behave differently, I need to find out how to change the behavior, so that I can adapt it to my specific requirements.

However, without googling and finding your hint here on the GitHub issue, it would've been hard for me to know that I need to implement a ExceptionMapper<javax.validation.ValidationException>. Therefore, some instructions in the validation guide would be really helpful.

@geoand
Copy link
Contributor

geoand commented Oct 29, 2020

Unless I am reading this wrong, I am pretty sure what you are seeing is the desired behavior, because JAX-RS will use the ExceptionMapper whose generic type best matches the exception - which is QuarkusRestViolationExceptionMapper in this case (this is JAX-RS spec behavior).

Thank you for the information. Can you please check that? I can't find anything about that class.

Check what exactly?

The name of the class you mentioned. As my links show, there's no such class in the Quarkus source code. But meanwhile, I think you meant io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyViolationExceptionMapper, right?

You are absolutely right, I was thinking a few days into the future :)

Also, when just getting the 400 response, it's hard to find out how to change it, so it should be documented -- I guess in the validation guide.

I'm not really following here, can you explain?

Sorry. As a developer using Quarkus, when I see that my application returns just the 400 Bad Request created by the ResteasyViolationExceptionMapper, but I want my application to behave differently, I need to find out how to change the behavior, so that I can adapt it to my specific requirements.

However, without googling and finding your hint here on the GitHub issue, it would've been hard for me to know that I need to implement a ExceptionMapper<javax.validation.ValidationException>. Therefore, some instructions in the validation guide would be really helpful.

This is a good point because although this is standard JAX-RS behavior, however it probably does make sense to mention this. @gsmet as this is your wheelhouse, WDYT?

@gsmet gsmet self-assigned this Dec 12, 2022
@geoand geoand added kind/question Further information is requested and removed kind/bug Something isn't working labels Sep 30, 2024
geoand added a commit to geoand/quarkus that referenced this issue Sep 30, 2024
@geoand
Copy link
Contributor

geoand commented Sep 30, 2024

Closing as this is a question instead of a bug. Moreover I opened #43592 to enhance the docs.

@geoand geoand closed this as completed Sep 30, 2024
gsmet added a commit that referenced this issue Sep 30, 2024
Add note about `ExceptionMapper<ValidationException>` in validation guide
mskacelik pushed a commit to mskacelik/quarkus that referenced this issue Oct 2, 2024
gsmet pushed a commit to gsmet/quarkus that referenced this issue Oct 21, 2024
bschuhmann pushed a commit to bschuhmann/quarkus that referenced this issue Nov 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/hibernate-validator Hibernate Validator kind/question Further information is requested
Projects
None yet
Development

No branches or pull requests

7 participants