Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NPE when calling a ClientResponseFilter #41749

Merged
merged 1 commit into from
Jul 10, 2024

Conversation

rober710
Copy link
Contributor

@rober710 rober710 commented Jul 8, 2024

When using the resteasy-reactive-client to make http calls, an NPE is thrown when using a custom filter and exception mapper. Here's the code to reproduce this:

private Configuration buildHttpConfig() {
    ConfigurationImpl configuration = new ConfigurationImpl(RuntimeType.CLIENT);
    configuration.property(QuarkusRestClientProperties.CONNECTION_TTL, 7);
    configuration.property(QuarkusRestClientProperties.CONNECTION_POOL_SIZE, 21);
    configuration.property(QuarkusRestClientProperties.KEEP_ALIVE_ENABLED, true);
    configuration.property(QuarkusRestClientProperties.MAX_REDIRECTS, 10);
    return configuration;
}

// Code in test service
ClientBuilder clientBuilder = ClientBuilder.newBuilder();
List<ResponseExceptionMapper<?>> exceptionMappers = Collections.singletonList(new DefaultMicroprofileRestClientExceptionMapper());
Client httpClient = clientBuilder.withConfig(buildHttpConfig())
                .register(new MicroProfileRestClientResponseFilter(exceptionMappers)).build();
try {
    String res = httpClient.target("http://httpbin.org/status/418").request().get(String.class);
    System.out.println(res);
} catch (Exception e) {
    if (e instanceof WebApplicationException webApplicationException) {
        String entity = webApplicationException.getResponse().readEntity(String.class);
        System.out.println(e.getMessage() + " entity " + entity);
    }
    e.printStackTrace();
}

Here's the stacktrace of the exception:

jakarta.ws.rs.ProcessingException: java.lang.NullPointerException: Cannot invoke "org.jboss.resteasy.reactive.client.impl.ClientRequestContextImpl.getRestClientRequestContext()" because "requestContext" is null
        at org.jboss.resteasy.reactive.client.handlers.ClientResponseFilterRestHandler.handle(ClientResponseFilterRestHandler.java:25)
        at org.jboss.resteasy.reactive.client.handlers.ClientResponseFilterRestHandler.handle(ClientResponseFilterRestHandler.java:10)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.invokeHandler(AbstractResteasyReactiveContext.java:231)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
        at org.jboss.resteasy.reactive.client.impl.RestClientRequestContext$1.lambda$execute$0(RestClientRequestContext.java:314)
        at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:279)
        at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:261)
        at io.vertx.core.impl.ContextInternal.lambda$runOnContext$0(ContextInternal.java:59)
        at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:566)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.NullPointerException: Cannot invoke "org.jboss.resteasy.reactive.client.impl.ClientRequestContextImpl.getRestClientRequestContext()" because "requestContext" is null
        at io.quarkus.rest.client.reactive.runtime.MicroProfileRestClientResponseFilter.filter(MicroProfileRestClientResponseFilter.java:38)
        at org.jboss.resteasy.reactive.client.handlers.ClientResponseFilterRestHandler.handle(ClientResponseFilterRestHandler.java:21)
        ... 15 more

This happens in Quarkus 3.11.0 and also tested in latest 3.12.1. When making the change in this PR, compiling and using the generated snapshot, I'm able to read the response as expected.

@quarkus-bot

This comment was marked as resolved.

@rober710 rober710 changed the title Fix NPE when calling a ClientResponseFilter. Jul 8, 2024
@geoand
Copy link
Contributor

geoand commented Jul 8, 2024

Thanks for this!

I am actually very interested in seeing a sample that exhibits the NPE you mention so we can understand the exact conditions under which it occurs.

@geoand geoand added the triage/needs-feedback We are waiting for feedback. label Jul 8, 2024
@rober710
Copy link
Contributor Author

rober710 commented Jul 8, 2024

@geoand Sure! This is the test project I was working on to debug this: https://github.com/rober710/resteasy-reactive-reproducer

Note that this is a workaround for another issue: currently using the resteasy-reactive-client it's not possible to read the response on error, due to this:


super("Server response is: " + responseStatus, null, new DummyResponse(responseStatus, responseReasonPhrase));

Is it ok to make changes to those classes so that the response can be passed to the exception and made available to consumers? I'm working on a PR on that as well. Just wanted to understand if there's a reason a DummyResponse is created instead of a full response object with the entity returned by the server.

@geoand geoand removed the triage/needs-feedback We are waiting for feedback. label Jul 8, 2024
@geoand
Copy link
Contributor

geoand commented Jul 9, 2024

Thanks for the explanation!

I think that we should actually do context.getOrCreateClientRequestContext() in ClientSetResponseEntityRestHandler#handle, instead of the change made here.
Do you want to try that?

@rober710
Copy link
Contributor Author

rober710 commented Jul 9, 2024

@geoand Done! It works calling the method there as well.

@geoand
Copy link
Contributor

geoand commented Jul 9, 2024

Great!

Can you please squash the commits?

@quarkus-bot
Copy link

quarkus-bot bot commented Jul 10, 2024

Status for workflow Quarkus CI

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

✅ 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.

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!

@geoand geoand merged commit 36902ce into quarkusio:main Jul 10, 2024
32 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.13 - main milestone Jul 10, 2024
@rober710 rober710 deleted the fix-npe-client-filter branch July 10, 2024 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants