[英]Keycloak and RESTEasy client: ClassNotFoundException: org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl
I need to add a RESTEasy
client to keycloak
( WildFly
based distribution).我需要将
RESTEasy
客户端添加到keycloak
(基于WildFly
的发行版)。
org.keycloak.broker.provider.AbstractIdentityProviderMapper
org.keycloak.broker.provider.AbstractIdentityProviderMapper
Client client = ClientBuilder.newBuilder().build();
ClientWebTarget target = (ClientWebTarget) client.target(UriBuilder.fromPath(URL_PATH));
CustomFetcher fetcher = target.proxy(CustomFetcher.class);
src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
When I copy the jar to keycloak
's standalone/deployments
directory I get当我将 jar 复制到
keycloak
的standalone/deployments
目录时,我得到
20:55:01,522 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit."keycloak-user-mapper-0.0.1-SNAPSHOT.jar".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.unit."keycloak-user-mapper-0.0.1-SNAPSHOT.jar".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "keycloak-user-mapper-0.0.1-SNAPSHOT.jar"
at org.jboss.as.server@18.0.4.Final//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:189)
at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads@2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.util.ServiceConfigurationError: org.keycloak.broker.provider.IdentityProviderMapper: Provider org.myorg.UserAttributeMapper could not be instantiated
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:582)
at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:804)
at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:722)
at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1395)
at org.keycloak.keycloak-services@17.0.0//org.keycloak.provider.DefaultProviderLoader.load(DefaultProviderLoader.java:60)
at org.keycloak.keycloak-services@17.0.0//org.keycloak.provider.ProviderManager.load(ProviderManager.java:94)
at org.keycloak.keycloak-services@17.0.0//org.keycloak.services.DefaultKeycloakSessionFactory.loadFactories(DefaultKeycloakSessionFactory.java:294)
at org.keycloak.keycloak-services@17.0.0//org.keycloak.services.DefaultKeycloakSessionFactory.deploy(DefaultKeycloakSessionFactory.java:154)
at org.keycloak.keycloak-services@17.0.0//org.keycloak.provider.ProviderManagerRegistry.deploy(ProviderManagerRegistry.java:42)
at org.keycloak.keycloak-wildfly-server-subsystem@17.0.0//org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor.deploy(KeycloakProviderDeploymentProcessor.java:58)
at org.jboss.as.server@18.0.4.Final//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:182)
... 8 more
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl from [Module "org.jboss.as.server" version 18.0.4.Final from local module loader @66c92293 (finder: local module finder @332796d3 (roots: /opt/jboss/keycloak/modules,/opt/jboss/keycloak/modules/system/layers/keycloak,/opt/jboss/keycloak/modules/system/layers/base))]
at org.jboss.resteasy.resteasy-client-api@4.7.4.Final//org.jboss.resteasy.client.jaxrs.ProxyBuilder.builder(ProxyBuilder.java:41)
at org.jboss.resteasy.resteasy-client@4.7.4.Final//org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.createProxyBuilder(ClientWebTarget.java:107)
at org.jboss.resteasy.resteasy-client@4.7.4.Final//org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.proxy(ClientWebTarget.java:94)
at deployment.keycloak-user-mapper-0.0.1-SNAPSHOT.jar//org.myorg.UserAttributeMapper.<init>(UserAttributeMapper.java:55)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:780)
... 17 more
Caused by: java.lang.ClassNotFoundException: org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl from [Module "org.jboss.as.server" version 18.0.4.Final from local module loader @66c92293 (finder: local module finder @332796d3 (roots: /opt/jboss/keycloak/modules,/opt/jboss/keycloak/modules/system/layers/keycloak,/opt/jboss/keycloak/modules/system/layers/base))]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:200)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
at org.jboss.resteasy.resteasy-client-api@4.7.4.Final//org.jboss.resteasy.client.jaxrs.ProxyBuilder.builder(ProxyBuilder.java:35)
... 25 more
Apparently Wildfly
's own org.jboss.as.server
module is not configured properly, so it doesn't have org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl
on its CLASSPATH
, but it exists on the my jar's CLASSPATH
, because I can successfully execute显然
Wildfly
自己的org.jboss.as.server
模块配置不正确,所以它的CLASSPATH
上没有org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl
,但它存在于我的 jar 上CLASSPATH
,因为我可以成功执行
Class.forName("org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl")
in the constructor of my class.在我的 class 的构造函数中。
WORKAROUND I added <module name="org.jboss.resteasy.resteasy-client"/>
to modules/system/layers/base/org/jboss/as/server/main/module.xml
and it works now, but it doesn't seem like a good solution, how do I approach this configuration?解决方法我将
<module name="org.jboss.resteasy.resteasy-client"/>
添加到modules/system/layers/base/org/jboss/as/server/main/module.xml
并且它现在可以工作,但它没有这似乎是一个很好的解决方案,我该如何处理这个配置?
UPDATE I suspect the problem might be with hot redeploy, if I copy the jar
to keycloak
first and after it I start keycloak
, no problems with the CLASSPATH
exist.更新我怀疑问题可能出在热重新部署上,如果我
jar
复制到keycloak
,然后再启动keycloak
,则CLASSPATH
不存在任何问题。 But if I copy the jar
into standalone/deployments
when keycloak
is running, then ClassNotFoundException
is thrown.但是,如果我在
keycloak
运行时将jar
复制到standalone/deployments
中,则会抛出ClassNotFoundException
。 I have tried keycloak-17.0.0.zip
, keycloak-17.0.1.zip
, keycloak-18.0.0.zip
( WildFly
based)我试过
keycloak-17.0.0.zip
, keycloak-17.0.1.zip
, keycloak-18.0.0.zip
(基于WildFly
)
Here is a script to reproduce the issue.这是重现该问题的脚本。 Invoke it with:
调用它:
bash script.sh [17.0.0 | 17.0.1 | 18.0.0]
to deploy the jar
to local keycloak
(the script will download keycloak
's zip
archive automatically if it hasn't been downloaded previously).将
jar
部署到本地keycloak
(如果之前未下载过,脚本将自动下载keycloak
的zip
存档)。
(*) Parameters in square brackets are optional, default version is 18.0.0
(*) 方括号内参数可选,默认版本为
18.0.0
#! /bin/bash
set -x
mkdir -p so72280865 && cd so72280865 || {
echo "Unable to create a working directory"
exit 1
}
cat <<EOF > pom.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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.myorg</groupId>
<artifactId>keycloak-so-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>17.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
EOF
mkdir -p src/main/java/org/myorg/
cat <<EOF > src/main/java/org/myorg/App.java
package org.myorg;
import org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.provider.ProviderConfigProperty;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.UriBuilder;
import java.util.Collections;
import java.util.List;
public class App extends AbstractIdentityProviderMapper {
private static final String URL_PATH = "https://api.myip.com";
private final CustomFetcher fetcher;
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
protected static final List<ProviderConfigProperty> configProperties = Collections.emptyList();
public App() {
final Client client = ClientBuilder.newBuilder()
.register(new org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider())
.build();
ClientWebTarget target = (ClientWebTarget) client.target(UriBuilder.fromPath(URL_PATH));
fetcher = target.proxy(CustomFetcher.class);
System.out.println(fetcher.get().toString());
}
@Path("/")
public interface CustomFetcher {
@GET String get();
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Custom Fetcher";
}
@Override
public String getHelpText() {
return "Custom Fetcher";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return "custom-fetcher-idp-mapper";
}
}
EOF
mkdir -p src/main/resources/META-INF/services
cat <<EOF > src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
org.myorg.App
EOF
mvn package
if [ "$?" -ne "0" ] ; then
exit 1
fi
KEYCLOAK_VERSION=${1:-18.0.0}
[ -f "keycloak-legacy-${KEYCLOAK_VERSION}.zip" ] || {
curl -LO "https://github.com/keycloak/keycloak/releases/download/${KEYCLOAK_VERSION}/keycloak-legacy-${KEYCLOAK_VERSION}.zip"
}
[ -d "keycloak-${KEYCLOAK_VERSION}" ] || {
unzip "keycloak-legacy-${KEYCLOAK_VERSION}.zip"
} && cp target/keycloak-so-demo-0.0.1-SNAPSHOT.jar "keycloak-${KEYCLOAK_VERSION}"/standalone/deployments &&
./"keycloak-${KEYCLOAK_VERSION}"/bin/standalone.sh &
trap "./keycloak-${KEYCLOAK_VERSION}/bin/jboss-cli.sh --connect --command=:shutdown" EXIT
TIMEOUT=180
while true ; do
started=$(ss -lt | grep 9990 | wc -l)
[ "$started" -eq "1" ] && break
[ "$TIMEOUT" -le "0" ] && {
echo "Timeout reached starting keycloak"
exit 1
}
TIMEOUT=$((TIMEOUT - 10))
sleep 10
done
cp target/keycloak-so-demo-0.0.1-SNAPSHOT.jar "keycloak-${KEYCLOAK_VERSION}"/standalone/deployments
sleep 10
The org.jboss.as.server
should not have a dependency on the RESTEasy module. org.jboss.as.server
不应依赖于 RESTEasy 模块。 You need your deployment to have a dependency on it.您需要您的部署依赖于它。 This should happen by default if the
jaxrs
subsystem is defined.如果定义了
jaxrs
子系统,这应该默认发生。
If the jaxrs subsystem is not present, you can add the dependencies to your deployment with either a jboss-deployment-structure.xml
or with a manifest entry.如果 jaxrs 子系统不存在,您可以使用
jboss-deployment-structure.xml
或清单条目将依赖项添加到您的部署中。 For the manifest entry simply add Dependencies: org.jboss.resteasy.resteasy-client services
to your META-INF/MANIFEST.MF
in your JAR. Note these are comma separated entries so if you need something like the JSON provider you'd need something like:对于清单条目,只需将
Dependencies: org.jboss.resteasy.resteasy-client services
添加到您的 JAR 中的META-INF/MANIFEST.MF
中。请注意,这些条目是逗号分隔的,因此如果您需要类似 JSON 提供商的内容,您将需要就像是:
Dependencies: org.jboss.resteasy.resteasy-client services, org.jboss.resteasy.resteasy-json-p-provider services
The "services" part just imports the services. “服务”部分只是导入服务。 This may not be required in some cases.
在某些情况下可能不需要这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.