Skip to content

Conversation

@kevinferrare-1a
Copy link
Contributor

@kevinferrare-1a kevinferrare-1a commented Oct 27, 2025

Adds support for the strategy attribute in @UnwrapException annotation to control exception unwrapping behaviour.

This makes tests in the reproducer pass with following annotation:

@UnwrapException(value={ WebApplicationException.class }, strategy=ExceptionUnwrapStrategy.UNWRAP_IF_NO_EXACT_MATCH)

https://github.com/user-attachments/files/20574949/quarkus-48197-reproducer.zip

Main Changes:

  • Added strategy boolean parameter to @UnwrapException annotation (default: UNWRAP_IF_NO_MATCH) and propagated it.

  • Updated RuntimeExceptionMapper exception mapping strategy to handle it:

    • If strategy=ALWAYS, unwrap even if exception is directly mapped in a mapper
    • If strategy=UNWRAP_IF_NO_EXACT_MATCH and exception is not directly mapped anywhere, unwrap
    • If strategy=UNWRAP_IF_NO_MATCH, check if the exception or one of its subtypes is mapped (existing behaviour)
    • If exception couldnt be mapped, unwrap it and repeat the process for the wrapped exception (existing behaviour)
  • Reworked UnwrappedExceptionTest to add more cases and more explicit names, and achieve 100% coverage on new code in RuntimeExceptionMapper.

  • Closes: UnwrapException ineffective when a subclass of the declared exception is mapped via ServerExceptionMapper #48197

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a changed the title Allow forcing exception unwrapping even when parent type mappers exist. Allow forcing exception unwrapping even when parent type mappers exist Oct 27, 2025
@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from 56ef700 to a84b26d Compare October 27, 2025 09:35
@quarkus-bot

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Oct 27, 2025

🙈 The PR is closed and the preview is expired.

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from a84b26d to d10b3c1 Compare October 27, 2025 17:26
@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from d10b3c1 to d2d9f1f Compare October 28, 2025 08:26
@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from 8b4a024 to 543975d Compare November 7, 2025 07:48
@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from 543975d to 47682be Compare November 7, 2025 14:31
@quarkus-bot

This comment has been minimized.

@quarkus-bot

This comment has been minimized.

Comment on lines 243 to 252
() -> searchMapperForExceptionsToUnwrap(clazz, mappers, throwable, ExceptionUnwrapStrategy.ALWAYS),
// If the exception type is directly mapped, ignore the unwrapping.
() -> buildMapperEntryIfExists(clazz, mappers, throwable),
// Check if the exception should be unwrapped if no exact match (if strategy=UNWRAP_IF_NO_EXACT_MATCH).
() -> searchMapperForExceptionsToUnwrap(clazz, mappers, throwable,
ExceptionUnwrapStrategy.UNWRAP_IF_NO_EXACT_MATCH),
// Walk up the class hierarchy looking for a mapper for the type
() -> searchMapperInClassHierarchy(clazz, mappers, throwable),
// If no mapper found and exception is marked for unwrapping (if strategy=UNWRAP_IF_NO_MATCH), unwrap it
() -> searchMapperForExceptionsToUnwrap(clazz, mappers, throwable, ExceptionUnwrapStrategy.UNWRAP_IF_NO_MATCH));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try hard to avoid lambdas in code that executes at runtime. Can you please update the code to remove them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented, waiting for a green build 😄

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from 47682be to bd474ea Compare November 10, 2025 07:45
Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@quarkus-bot

This comment has been minimized.

@kevinferrare-1a kevinferrare-1a force-pushed the feature/unwrap-exception-always branch from bd474ea to 434ca0a Compare November 10, 2025 09:50
@quarkus-bot
Copy link

quarkus-bot bot commented Nov 10, 2025

Status for workflow Quarkus Documentation CI

This is the status report for running Quarkus Documentation CI on commit 434ca0a.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

Warning

There are other workflow runs running, you probably need to wait for their status before merging.

@geoand geoand added the triage/waiting-for-ci Ready to merge when CI successfully finishes label Nov 10, 2025
@geoand geoand merged commit 4424b0c into quarkusio:main Nov 10, 2025
57 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.30 - main milestone Nov 10, 2025
@quarkus-bot quarkus-bot bot added kind/bugfix and removed triage/waiting-for-ci Ready to merge when CI successfully finishes labels Nov 10, 2025
@quarkus-bot
Copy link

quarkus-bot bot commented Nov 10, 2025

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit 434ca0a.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

You can consult the Develocity build scans.


Flaky tests - Develocity

⚙️ JVM Tests - JDK 25

📦 extensions/smallrye-graphql/deployment

io.quarkus.smallrye.graphql.deployment.CompletionStageTest.testSourcePost - History

  • 1 expectation failed. Expected status code <200> but was <500>. - java.lang.AssertionError
Details
java.lang.AssertionError: 
1 expectation failed.
Expected status code <200> but was <500>.

	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:73)
  • 1 expectation failed. Expected status code <200> but was <500>. - java.lang.AssertionError
Details
java.lang.AssertionError: 
1 expectation failed.
Expected status code <200> but was <500>.

	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:73)
  • 1 expectation failed. Expected status code <200> but was <500>. - java.lang.AssertionError
Details
java.lang.AssertionError: 
1 expectation failed.
Expected status code <200> but was <500>.

	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:73)

⚙️ JVM Tests - JDK 17 Windows

📦 extensions/micrometer-opentelemetry/deployment

io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni - History

  • Stream has no elements - java.lang.IllegalArgumentException
Details
java.lang.IllegalArgumentException: Stream has no elements
	at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lambda$lastReading$2(MetricDataFilter.java:213)
	at java.base/java.util.Optional.orElseThrow(Optional.java:403)
	at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReading(MetricDataFilter.java:213)
	at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReadingDataPoint(MetricDataFilter.java:231)
	at io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni(MicrometerTimedInterceptorTest.java:174)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at io.quarkus.test.QuarkusUnitTest.runExtensionMethod(QuarkusUnitTest.java:534)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UnwrapException ineffective when a subclass of the declared exception is mapped via ServerExceptionMapper

3 participants