quarkus: built-in ExceptionMappers cause unexpected behavior

Describe the bug Quarkus includes several JAX-RS ExceptionMappers out of the box. Those are actually not considered built-in as per the JAX-RS specification, they are just built into Quarkus to improve user experience.

However, they can also make the user experience worse. For example, if I create an ExceptionMapper for all Exceptions, it isn’t used if I throw a JAX-RS NotFoundException, because Quarkus includes an exception mapper for it (NotFoundExceptionMapper). Per the JAX-RS specification, RESTEasy will “use the provider whose generic type is the nearest superclass of the exception.”

For example, if my application communicates using JSON and my exception mapper produces some meaningful JSON structure for all Exceptions, I get an empty response body for NotFoundException (which is what io.quarkus.resteasy.runtime.NotFoundExceptionMapper does for JSON). It took me a while to figure out what’s going on here.

As a workaround, I have to create my own NotFoundExceptionMapper.

Expected behavior My own generic exception mapper is used.

Actual behavior Quarkus “built-in” exception mapper is used, because it targets a more specific exception.

I understand this is kinda by design, but unexpected still. I don’t know if it would help or not if RESTEasy would consider the “built-in” exception mappers in Quarkus as actually built-in per JAX-RS spec.

To Reproduce Steps to reproduce the behavior:

  1. Add an implementation of ExceptionMapper<Exception>.
  2. Throw NotFoundException.
  3. Observe that my own exception mapper is not used.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 5
  • Comments: 37 (32 by maintainers)

Commits related to this issue

Most upvoted comments

What is the status on this issue? We just ran into it and where very confused until we found this bug report.

Is it guaranteed, that this will only happen in dev mode? And that it only happens with the NotFoundException? Or are you planning to add mappers for more Exceptions in the future or for the normal build as well?

I think this issue should be fixed and not forgotten.

I agree, a config would be better, as it makes the change explicit instead of “magic”. Also it would allow me to have a “catch all” mapper and still use the internal mappers for the standard exceptions. So it is a bit more flexible.

Any news regarding this issue? We also ran into this unexpected behavior and still can’t find a decent walkaround. We whish to declare a “catch-all” exception mapper - and log these to our DB. But any pre-defined mapper keeps overriding our generic one. We tried changing our priority but it doesn’t help, probably since the more specific pre-defined mapper always “wins”…

Quarkus has one for NotFoundException (low prio, but nearest superclass), the user has one for Exception (high prio, but furthest superclass).

I guess the user would like his mapper to override the Quarkus one.

No, I wouldn’t want to get rid of it altogether. It provides a nice HTML output, but it gets in the way in other cases. I think I would probably pretend that it doesn’t exist in case the user provides a more general exception mapper.

That’s a big just 😆

@ronsigal I can think of several workarounds – your one is interesting, but still a workaround, from my perspective. I think this is something that needs to be solved between Quarkus and RESTEasy. I understand that from RESTEasy perspective, whatever Quarkus adds is part of the application, but from application developer’s perspective, it is not.