Skip to content

Commit

Permalink
Don't convert WebApplicationException in REST Client when produced by…
Browse files Browse the repository at this point in the history
… a custom mapper

The idea is that if a user has opted to create an exception,
we should always honor it - even if it's a WebApplicationException

Fixes: quarkusio#42275
  • Loading branch information
geoand committed Aug 5, 2024
1 parent 5f2d29b commit c6b03f9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.net.URL;
import java.util.List;

import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
Expand All @@ -22,6 +21,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.rest.client.reactive.ClientExceptionMapper;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

Expand Down Expand Up @@ -55,6 +55,12 @@ public void testBadRequest() {
Assertions.assertEquals(500, data.getStatus());
}

@Test
public void testBadRequestWithCusterMapper() {
Response data = client.target(url.toExternalForm() + "/bad-server/with-custom-mapper").request().get();
Assertions.assertEquals(999, data.getStatus());
}

@Path("/bad")
public static class Bad {

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

@Path("/bad")
@RegisterRestClient(baseUri = "http://localhost:8081")
public interface BadClientWithCustomMapper extends BadClient {

@ClientExceptionMapper
static RuntimeException toException(Response response) {
if (response.getStatus() == 400) {
return new WebApplicationException(999);
}
return null;
}
}

static class JsonObject {
String name;
}

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

@Inject
@RestClient
BadClient badClient;

@RestClient
BadClientWithCustomMapper badClientWithCustomMapper;

@GET
public JsonObject get() {
try {
Expand All @@ -104,5 +125,12 @@ public JsonObject get() {
return null;
}
}

@GET
@Path("with-custom-mapper")
public JsonObject getWithCustomMapper() {
return badClientWithCustomMapper.get("{name:foo}");
}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.rest.client.reactive.runtime;

import static org.jboss.resteasy.reactive.client.impl.RestClientRequestContext.INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -51,6 +53,7 @@ public void filter(ClientRequestContext requestContext, ClientResponseContext re
} else {
throwable = exceptionMapper.toThrowable(response);
}
requestContext.setProperty(INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP, exceptionMapper.getClass().getName());
if (throwable != null) {
throw new UnwrappableException(throwable);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ public class RestClientRequestContext extends AbstractResteasyReactiveContext<Re

public static final String INVOKED_METHOD_PROP = "org.eclipse.microprofile.rest.client.invokedMethod";
public static final String INVOKED_METHOD_PARAMETERS_PROP = "io.quarkus.rest.client.invokedMethodParameters";
public static final String INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP = "io.quarkus.rest.client.invokedExceptionMapperClass";
public static final String DEFAULT_CONTENT_TYPE_PROP = "io.quarkus.rest.client.defaultContentType";
public static final String DEFAULT_USER_AGENT_VALUE = "Quarkus REST Client";
private static final String TMP_FILE_PATH_KEY = "tmp_file_path";

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

private final HttpClient httpClient;
// Changeable by the request filter
Expand Down Expand Up @@ -179,12 +182,19 @@ public Annotation[] getMethodDeclaredAnnotationsSafe() {
@Override
protected Throwable unwrapException(Throwable t) {
var res = super.unwrapException(t);
if (res instanceof WebApplicationException) {
var webApplicationException = (WebApplicationException) res;

var invokedExceptionMapperClassNameObj = properties.get(INVOKED_EXCEPTION_MAPPER_CLASS_NAME_PROP);
if (invokedExceptionMapperClassNameObj instanceof String invokedExceptionMapperClassName) {
if (!DEFAULT_EXCEPTION_MAPPER_CLASS_NAME.equals(invokedExceptionMapperClassName)) {
// in this case a custom exception mapper provided the exception, so we honor it
return res;
}
}

if (res instanceof WebApplicationException webApplicationException) {
var message = webApplicationException.getMessage();
var invokedMethodObject = properties.get(INVOKED_METHOD_PROP);
if ((invokedMethodObject instanceof Method) && !disableContextualErrorMessages) {
var invokedMethod = (Method) invokedMethodObject;
if ((invokedMethodObject instanceof Method invokedMethod) && !disableContextualErrorMessages) {
message = "Received: '" + message + "' when invoking: Rest Client method: '"
+ invokedMethod.getDeclaringClass().getName() + "#"
+ invokedMethod.getName() + "'";
Expand Down

0 comments on commit c6b03f9

Please sign in to comment.