Skip to content

Commit b5231da

Browse files
authored
Merge pull request #42290 from geoand/#42275
Don't convert WebApplicationException in REST Client when produced by a custom mapper
2 parents 5f2d29b + c6b03f9 commit b5231da

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

extensions/resteasy-reactive/rest-client-jackson/deployment/src/test/java/io/quarkus/rest/client/reactive/jackson/test/BadRequestNotPropagatedTestCase.java

+30-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.net.URL;
44
import java.util.List;
55

6-
import jakarta.inject.Inject;
76
import jakarta.ws.rs.Consumes;
87
import jakarta.ws.rs.GET;
98
import jakarta.ws.rs.Path;
@@ -22,6 +21,7 @@
2221
import org.junit.jupiter.api.Test;
2322
import org.junit.jupiter.api.extension.RegisterExtension;
2423

24+
import io.quarkus.rest.client.reactive.ClientExceptionMapper;
2525
import io.quarkus.test.QuarkusUnitTest;
2626
import io.quarkus.test.common.http.TestHTTPResource;
2727

@@ -55,6 +55,12 @@ public void testBadRequest() {
5555
Assertions.assertEquals(500, data.getStatus());
5656
}
5757

58+
@Test
59+
public void testBadRequestWithCusterMapper() {
60+
Response data = client.target(url.toExternalForm() + "/bad-server/with-custom-mapper").request().get();
61+
Assertions.assertEquals(999, data.getStatus());
62+
}
63+
5864
@Path("/bad")
5965
public static class Bad {
6066

@@ -75,17 +81,32 @@ public interface BadClient {
7581
JsonObject get(String json);
7682
}
7783

84+
@Path("/bad")
85+
@RegisterRestClient(baseUri = "http://localhost:8081")
86+
public interface BadClientWithCustomMapper extends BadClient {
87+
88+
@ClientExceptionMapper
89+
static RuntimeException toException(Response response) {
90+
if (response.getStatus() == 400) {
91+
return new WebApplicationException(999);
92+
}
93+
return null;
94+
}
95+
}
96+
7897
static class JsonObject {
7998
String name;
8099
}
81100

82101
@Path("/bad-server")
83102
public static class BadServer {
84103

85-
@Inject
86104
@RestClient
87105
BadClient badClient;
88106

107+
@RestClient
108+
BadClientWithCustomMapper badClientWithCustomMapper;
109+
89110
@GET
90111
public JsonObject get() {
91112
try {
@@ -104,5 +125,12 @@ public JsonObject get() {
104125
return null;
105126
}
106127
}
128+
129+
@GET
130+
@Path("with-custom-mapper")
131+
public JsonObject getWithCustomMapper() {
132+
return badClientWithCustomMapper.get("{name:foo}");
133+
}
134+
107135
}
108136
}

extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/MicroProfileRestClientResponseFilter.java

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.quarkus.rest.client.reactive.runtime;
22

3+
import static org.jboss.resteasy.reactive.client.impl.RestClientRequestContext.INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP;
4+
35
import java.io.IOException;
46
import java.util.ArrayList;
57
import java.util.List;
@@ -51,6 +53,7 @@ public void filter(ClientRequestContext requestContext, ClientResponseContext re
5153
} else {
5254
throwable = exceptionMapper.toThrowable(response);
5355
}
56+
requestContext.setProperty(INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP, exceptionMapper.getClass().getName());
5457
if (throwable != null) {
5558
throw new UnwrappableException(throwable);
5659
}

independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/RestClientRequestContext.java

+14-4
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,14 @@ public class RestClientRequestContext extends AbstractResteasyReactiveContext<Re
5858

5959
public static final String INVOKED_METHOD_PROP = "org.eclipse.microprofile.rest.client.invokedMethod";
6060
public static final String INVOKED_METHOD_PARAMETERS_PROP = "io.quarkus.rest.client.invokedMethodParameters";
61+
public static final String INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP = "io.quarkus.rest.client.invokedExceptionMapperClass";
6162
public static final String DEFAULT_CONTENT_TYPE_PROP = "io.quarkus.rest.client.defaultContentType";
6263
public static final String DEFAULT_USER_AGENT_VALUE = "Quarkus REST Client";
6364
private static final String TMP_FILE_PATH_KEY = "tmp_file_path";
6465

6566
static final MediaType IGNORED_MEDIA_TYPE = new MediaType("ignored", "ignored");
67+
// TODO: the following property should really be provided by an SPI
68+
private static final String DEFAULT_EXCEPTION_MAPPER_CLASS_NAME = "io.quarkus.rest.client.reactive.runtime.DefaultMicroprofileRestClientExceptionMapper";
6669

6770
private final HttpClient httpClient;
6871
// Changeable by the request filter
@@ -179,12 +182,19 @@ public Annotation[] getMethodDeclaredAnnotationsSafe() {
179182
@Override
180183
protected Throwable unwrapException(Throwable t) {
181184
var res = super.unwrapException(t);
182-
if (res instanceof WebApplicationException) {
183-
var webApplicationException = (WebApplicationException) res;
185+
186+
var invokedExceptionMapperClassNameObj = properties.get(INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP);
187+
if (invokedExceptionMapperClassNameObj instanceof String invokedExceptionMapperClassName) {
188+
if (!DEFAULT_EXCEPTION_MAPPER_CLASS_NAME.equals(invokedExceptionMapperClassName)) {
189+
// in this case a custom exception mapper provided the exception, so we honor it
190+
return res;
191+
}
192+
}
193+
194+
if (res instanceof WebApplicationException webApplicationException) {
184195
var message = webApplicationException.getMessage();
185196
var invokedMethodObject = properties.get(INVOKED_METHOD_PROP);
186-
if ((invokedMethodObject instanceof Method) && !disableContextualErrorMessages) {
187-
var invokedMethod = (Method) invokedMethodObject;
197+
if ((invokedMethodObject instanceof Method invokedMethod) && !disableContextualErrorMessages) {
188198
message = "Received: '" + message + "' when invoking: Rest Client method: '"
189199
+ invokedMethod.getDeclaringClass().getName() + "#"
190200
+ invokedMethod.getName() + "'";

0 commit comments

Comments
 (0)