Austin Brown
Austin Brown

Reputation: 937

RestEasyClient IncompatibleClassChangeError (ResteasyProviderFactory.getContextData(java.lang.Class))

When using org.jboss.resteasy:resteasy-client:4.5.9.Final, I'm getting this exception: Caused by: java.lang.IncompatibleClassChangeError: Expected static method 'java.lang.Object org.jboss.resteasy.spi.ResteasyProviderFactory.getContextData(java.lang.Class)'

However, when I use an earlier version, it seems to work fine. (Or at least it works well enough to fool me.)

Here's my simplified pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>example-project</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.source>15</maven.compiler.source>
    <maven.compiler.target>15</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <keycloak.version>12.0.4</keycloak.version>
    <!-- Seems to work with this version, but not 4.5.9.Final -->
    <resteasy.version>3.6.2.Final</resteasy.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.keycloak</groupId>
      <artifactId>keycloak-admin-client</artifactId>
      <version>${keycloak.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-client</artifactId>
      <version>${resteasy.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jackson2-provider</artifactId>
      <version>${resteasy.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-multipart-provider</artifactId>
      <version>${resteasy.version}</version>
    </dependency>
  </dependencies>
</project>

And here's my code:

package org.example.keycloak;

import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;

public class KeycloakClientAuthExample {
    public static void main(String[] args) {
        Keycloak keycloak = KeycloakBuilder.builder()
                .serverUrl("http://localhost:8080/auth")
                .grantType(OAuth2Constants.PASSWORD)
                .realm("DungeoneersDemo")
                .clientId("dungeoneers-data")
                .clientSecret("11111111-2222-3333-4444-555555555555")
                .username("user")
                .password("pass")
                .resteasyClient(
                     // new ResteasyClientBuilderImpl() // <-- For 4.5.9.Final 
                        new ResteasyClientBuilder()
                                .connectionPoolSize(10).build()
                ).build();

        keycloak.tokenManager().getAccessToken();

        AccessTokenResponse atr =
                keycloak.tokenManager().getAccessToken();
        System.out.println(atr.getToken());
    }
}

Seems to work and I get what looks enough to me like a bearer token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2bWhhWUQ..etc...

However, when I update my resteasy.version to the a later version✳ (4.5.9.Final), I get an error:

Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    at org.jboss.resteasy.plugins.providers.RegisterBuiltin.register(RegisterBuiltin.java:78)
    at org.jboss.resteasy.plugins.providers.RegisterBuiltin.getClientInitializedResteasyProviderFactory(RegisterBuiltin.java:54)
    at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.getProviderFactory(ResteasyClientBuilderImpl.java:372)
    at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.build(ResteasyClientBuilderImpl.java:390)
    at org.sandbox.security.openidc.keycloak.KeycloakClientAuthExample.main(KeycloakClientAuthExample.java:22)
Caused by: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    at org.jboss.resteasy.core.providerfactory.CommonProviders.processProviderContracts(CommonProviders.java:93)
    at org.jboss.resteasy.core.providerfactory.ClientHelper.processProviderContracts(ClientHelper.java:104)
    at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.processProviderContracts(ResteasyProviderFactoryImpl.java:841)
    at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.registerProvider(ResteasyProviderFactoryImpl.java:829)
    at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.registerProvider(ResteasyProviderFactoryImpl.java:816)
    at org.jboss.resteasy.plugins.providers.RegisterBuiltin.registerProviders(RegisterBuiltin.java:109)
    at org.jboss.resteasy.plugins.providers.RegisterBuiltin.register(RegisterBuiltin.java:74)
    ... 4 more
Caused by: java.lang.RuntimeException: RESTEASY003325: Failed to construct public org.jboss.resteasy.plugins.providers.jaxb.JAXBElementProvider()
    at org.jboss.resteasy.core.ConstructorInjectorImpl.constructOutsideRequest(ConstructorInjectorImpl.java:250)
    at org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:209)
    at org.jboss.resteasy.core.providerfactory.Utils.createProviderInstance(Utils.java:102)
    at org.jboss.resteasy.core.providerfactory.CommonProviders.processProviderContracts(CommonProviders.java:87)
    ... 10 more
Caused by: java.lang.IncompatibleClassChangeError: Expected static method 'java.lang.Object org.jboss.resteasy.spi.ResteasyProviderFactory.getContextData(java.lang.Class)'
    at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.<init>(AbstractJAXBProvider.java:52)
    at org.jboss.resteasy.plugins.providers.jaxb.JAXBElementProvider.<init>(JAXBElementProvider.java:46)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
    at org.jboss.resteasy.core.ConstructorInjectorImpl.constructOutsideRequest(ConstructorInjectorImpl.java:225)
    ... 13 more

Process finished with exit code 1

✳ Note: When upgrading to the later version, ResteasyClientBuilder was abstracted and the constructor call needed to be replaced with new ResteasyClientBuilderImpl().

Upvotes: 2

Views: 6237

Answers (2)

Alberto Soto
Alberto Soto

Reputation: 164

We were facing the same issue and your reply really helped to find out the mistake. To let other users check the error in detail, further details are:

  • KC 15.* and KC16.1 uses, in their main pom.xml, resteasy version 3.*
       <resteasy.version>3.15.1.Final</resteasy.version>
        <resteasy.undertow.version>${resteasy.version}</resteasy.undertow.version>
  • When you check the version for the container in the server, you can see that, from KC16, the new Widlfly server uses resteasy v4.*
  • This concept causes a difference in the jars, while it has the behavior to have scope provided (but is not). As you mentioned, the solution to that is the following.
    <properties>        
        <resteasy.version>4.5.9.Final</resteasy.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-client</artifactId>
                <version>${resteasy.version}</version>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jackson2-provider</artifactId>
                <version>${resteasy.version}</version>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-multipart-provider</artifactId>
                <version>${resteasy.version}</version>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxb-provider</artifactId>
                <version>${resteasy.version}</version>
            </dependency>
           </dependencies></dependencyManagement>
  • This will force 3 main API changes to consider:
    final ResteasyClient client = new ResteasyClientBuilder()
            .disableTrustManager()
            .socketTimeout(60, TimeUnit.SECONDS)
            .establishConnectionTimeout(10, TimeUnit.SECONDS)
/// will need to change to the new methods:
        final ResteasyClient client = new ResteasyClientBuilderImpl()
            .disableTrustManager()
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
  • And also this change:
HttpServletResponse contextData = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
//Change to
ResteasyProviderFactory resteasyProviderFactory = ResteasyProviderFactoryImpl.getInstance();
HttpServletResponse contextData = resteasyProviderFactory.getContextData(HttpServletResponse.class);

You r previous reply help us to understand under the hood the problem, but, anyway, users shall have more info. See the image bellow as a running KC16 container showing all related libs kc 16 related libs

Upvotes: 1

Austin Brown
Austin Brown

Reputation: 937

I was typing out my question and, while looking into it one last time before submitting, I found the issue and figured I'd throw it out there just in case someone else has this issue.

It turns out that there is another resteasy dependency that needed to be pulled in because, otherwise, an old version is pulled in. When using the newer version of resteasy-client, the other dependency being pulled in was org.jboss.resteasy:resteasy-jaxb-provider:3.9.1.Final. I added the newer version to my pom (org.jboss.resteasy:resteasy-jaxb-provider:4.5.9.Final) and everything seems to now work.

Not sure why this is the case. I would think if the dependency was being pulled in anyway by resteasy-client, it should've been pulling in the same version.

Upvotes: 1

Related Questions