diff --git a/extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java b/extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java index 9fa08c45b54d2..8debcec04ede8 100644 --- a/extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java +++ b/extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java @@ -72,7 +72,6 @@ import io.quarkus.resteasy.reactive.jackson.EnableSecureSerialization; import io.quarkus.resteasy.reactive.jackson.SecureField; import io.quarkus.resteasy.reactive.jackson.runtime.ResteasyReactiveServerJacksonRecorder; -import io.quarkus.resteasy.reactive.jackson.runtime.mappers.DefaultMismatchedInputException; import io.quarkus.resteasy.reactive.jackson.runtime.mappers.NativeInvalidDefinitionExceptionMapper; import io.quarkus.resteasy.reactive.jackson.runtime.security.RolesAllowedConfigExpStorage; import io.quarkus.resteasy.reactive.jackson.runtime.security.SecurityCustomSerialization; @@ -108,6 +107,7 @@ public class ResteasyReactiveJacksonProcessor { private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final List HANDLED_MEDIA_TYPES = List.of(MediaType.APPLICATION_JSON, APPLICATION_NDJSON, APPLICATION_STREAM_JSON); + public static final String DEFAULT_MISMATCHED_INPUT_EXCEPTION = "io.quarkus.resteasy.reactive.jackson.runtime.mappers.DefaultMismatchedInputException"; @BuildStep void feature(BuildProducer feature) { @@ -130,9 +130,16 @@ ReinitializeVertxJsonBuildItem vertxJson() { } @BuildStep - ExceptionMapperBuildItem exceptionMappers() { - return new ExceptionMapperBuildItem(DefaultMismatchedInputException.class.getName(), - MismatchedInputException.class.getName(), Priorities.USER + 100, false); + void exceptionMappers(BuildProducer producer) { + try { + Thread.currentThread().getContextClassLoader().loadClass(DEFAULT_MISMATCHED_INPUT_EXCEPTION); + } catch (NoClassDefFoundError | ClassNotFoundException e) { + // the class is not available, likely due to quarkus.class-loading.removed-resources."io.quarkus\:quarkus-rest-jackson"=io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.class + return; + } + + producer.produce(new ExceptionMapperBuildItem(DEFAULT_MISMATCHED_INPUT_EXCEPTION, + MismatchedInputException.class.getName(), Priorities.USER + 100, false)); } @BuildStep diff --git a/extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/ExceptionInReaderWithExcludedBuiltInAndIncludedCustomMapperTest.java b/extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/ExceptionInReaderWithExcludedBuiltInAndIncludedCustomMapperTest.java new file mode 100644 index 0000000000000..e0ca92a987963 --- /dev/null +++ b/extensions/resteasy-reactive/rest-jackson/deployment/src/test/java/io/quarkus/resteasy/reactive/jackson/deployment/test/ExceptionInReaderWithExcludedBuiltInAndIncludedCustomMapperTest.java @@ -0,0 +1,46 @@ +package io.quarkus.resteasy.reactive.jackson.deployment.test; + +import java.util.function.Supplier; + +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import com.fasterxml.jackson.databind.DatabindException; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class ExceptionInReaderWithExcludedBuiltInAndIncludedCustomMapperTest { + + @RegisterExtension + static QuarkusUnitTest test = new QuarkusUnitTest() + .setArchiveProducer(new Supplier<>() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(FroMage.class, FroMageEndpoint.class, DatabindExceptionMapper.class); + } + }).overrideConfigKey("quarkus.class-loading.removed-resources.\"io.quarkus\\:quarkus-rest-jackson\"", + "io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.class"); + + @Test + public void test() { + RestAssured.with().contentType("application/json").body("{\"name\": \"brie\"}").put("/fromage") + .then().statusCode(999); + } + + @Provider + public static class DatabindExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(DatabindException exception) { + return Response.status(999).build(); + } + } +} diff --git a/extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.java b/extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.java index 54783b513b961..151ab715d69c4 100644 --- a/extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.java +++ b/extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/mappers/DefaultMismatchedInputException.java @@ -10,6 +10,7 @@ import io.quarkus.runtime.LaunchMode; +@SuppressWarnings("unused") public class DefaultMismatchedInputException implements ExceptionMapper {