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

问题描述

使用 org.jboss.resteasy:resteasy-client:4.5.9.Final 时,我收到此异常:Caused by: java.lang.IncompatibleClassChangeError: Expected static method 'java.lang.Object org.jboss.resteasy.spi.ResteasyProviderFactory.getContextData(java.lang.class)'

但是,当我使用早期版本时,它似乎工作正常。 (或者至少它的效果足以欺骗我。)

这是我的简化 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>

这是我的代码

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());
    }
}

似乎有效,我得到了对我来说足够像不记名令牌的东西:eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2bWhhWUQ..etc...

但是,当我将 resteasy.version 更新到更高版本✳ (4.5.9.Final) 时,出现错误

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

✳ 注意:升级到更高版本时,ResteasyClientBuilder被抽象了,构造函数调用需要替换为new ResteasyClientBuilderImpl()

解决方法

我正在输入我的问题,在提交前最后一次调查时,我发现了这个问题,并想我会把它扔掉,以防其他人遇到这个问题。

事实证明,还有另一个 resteasy 依赖需要被拉入,否则,一个旧版本被拉入。当使用新版本的 resteasy-client 时,另一个被拉入的依赖是 {{ 1}}。我将较新的版本添加到我的 pom (org.jboss.resteasy:resteasy-jaxb-provider:3.9.1.Final) 中,现在似乎一切正常。

不知道为什么会这样。我想,如果 org.jboss.resteasy:resteasy-jaxb-provider:4.5.9.Final 无论如何都拉入了依赖项,它应该拉入相同的版本。