Skip to content

Commit 9022b3a

Browse files
committed
RESTEasy Reactive Client: propagate declared exceptions
RESTEasy Reactive Client generates a `$$CDIWrapper` class for each MP RestClient interface, which is then discovered by ArC. The generated classes however used to not declare any exceptions on methods, even if the interface did declare some. This is wrong at least in case the bean is intercepted (for example using MP Fault Tolerance), because undeclared checked exceptions are wrapped into `ArcUndeclaredThrowableException` by interception subclasses. This commit fixes that by propagating all exception types from the interface methods to the `$$CDIWrapper` methods.
1 parent d80a848 commit 9022b3a

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-0
lines changed

extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,11 @@ void addRestClientBeans(Capabilities capabilities,
594594
// return InterfaceClass.super.get();
595595
// }
596596
MethodCreator methodCreator = classCreator.getMethodCreator(MethodDescriptor.of(method));
597+
for (Type exception : method.exceptions()) {
598+
// declared exceptions are important in case the client is intercepted, because interception
599+
// subclasses wrap undeclared checked exceptions into `ArcUndeclaredThrowableException`
600+
methodCreator.addException(exception.name().toString());
601+
}
597602
methodCreator.setSignature(method.genericSignatureIfRequired());
598603

599604
// copy method annotations, there can be interceptors bound to them:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.quarkus.it.rest.client.main;
2+
3+
import jakarta.ws.rs.GET;
4+
import jakarta.ws.rs.Path;
5+
6+
import org.eclipse.microprofile.faulttolerance.Retry;
7+
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
8+
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
9+
10+
import io.quarkus.it.rest.client.main.MyResponseExceptionMapper.MyException;
11+
12+
@Path("/unprocessable")
13+
@RegisterProvider(MyResponseExceptionMapper.class)
14+
@RegisterRestClient(configKey = "w-exception-mapper-and-interceptor")
15+
public interface ClientWithExceptionMapperAndInterceptor {
16+
@GET
17+
@Retry(maxRetries = 1, jitter = 0) // any interceptor would do here
18+
String get() throws MyException;
19+
}

integration-tests/rest-client-reactive/src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
w-client-logger/mp-rest/url=${test.url}
22
w-exception-mapper/mp-rest/url=${test.url}
3+
w-exception-mapper-and-interceptor/mp-rest/url=${test.url}
34
w-fault-tolerance/mp-rest/url=${test.url}
45
correlation/mp-rest/url=${test.url}
56
io.quarkus.it.rest.client.main.ParamClient/mp-rest/url=${test.url}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.quarkus.it.rest.client;
2+
3+
import static org.junit.jupiter.api.Assertions.assertThrows;
4+
5+
import jakarta.inject.Inject;
6+
7+
import org.eclipse.microprofile.rest.client.inject.RestClient;
8+
import org.junit.jupiter.api.Test;
9+
10+
import io.quarkus.it.rest.client.main.ClientWithExceptionMapperAndInterceptor;
11+
import io.quarkus.it.rest.client.main.MyResponseExceptionMapper;
12+
import io.quarkus.test.junit.QuarkusTest;
13+
14+
@QuarkusTest
15+
public class CheckedExceptionWithInterceptionTest {
16+
@Inject
17+
@RestClient
18+
ClientWithExceptionMapperAndInterceptor client;
19+
20+
@Test
21+
public void test() {
22+
assertThrows(MyResponseExceptionMapper.MyException.class, () -> {
23+
client.get();
24+
});
25+
}
26+
}

0 commit comments

Comments
 (0)