quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.53k stars 2.61k forks source link

@CacheResult on legacy @RegisterRestClient throws CCE on 3.4.2 #36336

Open Maldivia opened 11 months ago

Maldivia commented 11 months ago

Describe the bug

Using @CacheResult with legacy @RegisterRestClient throws ClassCastException on 3.4.2

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

Using the following dependencies:

Given the below example service and resource classes:

package org.acme.cache;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@Path("/ip")
public class IpResource {
    @Inject
    @RestClient
    IpService service;

    @GET
    public String getIp() {
        return service.getIp();
    }
}
package org.acme.cache;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.cache.CacheResult;

@Path("/")
@RegisterRestClient(configKey="ip")
public interface IpService {
  @GET
  @CacheResult(cacheName = "ip")
  String getIp();
}

and ip/mp-rest/url=https://api.ipify.org/ entry in application.properties.

On Quarkus 3.3.3, it works:

$ curl localhost:8080/ip 90.xxx.xx.xxx

On Quarkus 3.4.2:

$ curl localhost:8080/ip {"details":"Error id 778dc968-4c07-44eb-b8ab-983596bce955-1, org.jboss.resteasy.spi.UnhandledException: java.lang.ClassCastException: class jdk.proxy3.$Proxy65 cannot be cast to class io.quarkus.arc.AbstractAnnotationLiteral .....

Exception stack trace:

Caused by: java.lang.ClassCastException: class jdk.proxy3.$Proxy65 cannot be cast to class io.quarkus.arc.AbstractAnnotationLiteral (jdk.proxy3.$Proxy65 is in module jdk.proxy3 of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @77e9807f; io.quarkus.arc.AbstractAnnotationLiteral is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @77e9807f)
        at io.quarkus.cache.runtime.CacheInterceptor.getArcCacheInterceptionContext(CacheInterceptor.java:76)
        at io.quarkus.cache.runtime.CacheInterceptor.getInterceptionContext(CacheInterceptor.java:56)
        at io.quarkus.cache.runtime.CacheResultInterceptor.intercept(CacheResultInterceptor.java:38)

Commenting out the @CacheResult lines makes the rest client work on 3.4.2 as well.

Output of uname -a or ver

No response

Output of java -version

openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7) OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

3.4.2

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.5 (57804ffe001d7215b5e7bcb531cf83df38f93546)

Additional information

No response

quarkus-bot[bot] commented 11 months ago

/cc @gwenneg (cache)

gwenneg commented 11 months ago

Thanks for reporting this @Maldivia!

I am able to reproduce the bug locally with quarkus-resteasy but quarkus-resteasy-reactive is surprisingly not affected. A recent change in quarkus-resteasy may have caused the bug. Since our integration tests for the cache extension rely on quarkus-resteasy-reactive, we did not detect the issue before Quarkus 3.4 was released.

Switching from quarkus-resteasy to quarkus-resteasy-reactive may be another way to work around the bug until it's fixed.

gwenneg commented 11 months ago

@geoand Are you aware of a recent change in quarkus-resteasy that could have caused this?

With that extension, InterceptorBindings#getInterceptorBindingLiterals can now return a collection containing a dynamic proxy instead of the AbstractAnnotationLiteral it used to contain.

gwenneg commented 11 months ago

Could be related to quarkus-rest-client as well. ~Let me double check which one of quarkus-resteasy and quarkus-rest-client is causing this.~ I'm not sure.

geoand commented 11 months ago

I have no idea, maybe @jamezp knows

geoand commented 11 months ago

Switching from quarkus-resteasy to quarkus-resteasy-reactive may be another way to work around the bug until it's fixed.

The later is where are focus is on anyway

Maldivia commented 11 months ago

Switching from quarkus-resteasy to quarkus-resteasy-reactive may be another way to work around the bug until it's fixed.

Yeah, as a workaournd/fix, I switched to the reactive versions of the extensions, and applied @Blocking as needed, and that seems to be working as expected.

geoand commented 11 months ago

You don't need @Blocking if you are not returning Reactive / Async types

Maldivia commented 11 months ago

I'm using Qute as well, so updated to using quarkus-resteasy-reactive-qute, which I assume causes TemplateInstance to be seen as a reactive type, so I needed Blocking (was getting BlockingNotAllowedException)

geoand commented 11 months ago

Ah, good point!

jamezp commented 11 months ago

There has been changes in RESTEasy I can think of that would cause this. One thing I find a bit odd in the stack trace is that both the class loaders seem to have the same id, @77e9807f, however one is in a module named jdk.proxy3 and one is in an unnamed module.

hanMue commented 2 weeks ago

I have the same problem, even in newer versions (I have tried up to current release 3.13.2). Is anyone working on this bug or has another solution?