![](/img/trans.png)
[英]ClassNotFoundException: org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder
[英]Keycloak and RESTEasy client: ClassNotFoundException: org.jboss.resteasy.client.jaxrs.internal.proxy.ProxyBuilderImpl
我需要将RESTEasy
客户端添加到keycloak
(基于WildFly
的发行版)。
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
当我将 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
显然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")
在我的 class 的构造函数中。
解决方法我将<module name="org.jboss.resteasy.resteasy-client"/>
添加到modules/system/layers/base/org/jboss/as/server/main/module.xml
并且它现在可以工作,但它没有这似乎是一个很好的解决方案,我该如何处理这个配置?
更新我怀疑问题可能出在热重新部署上,如果我jar
复制到keycloak
,然后再启动keycloak
,则CLASSPATH
不存在任何问题。 但是,如果我在keycloak
运行时将jar
复制到standalone/deployments
中,则会抛出ClassNotFoundException
。 我试过keycloak-17.0.0.zip
, keycloak-17.0.1.zip
, keycloak-18.0.0.zip
(基于WildFly
)
这是重现该问题的脚本。 调用它:
bash script.sh [17.0.0 | 17.0.1 | 18.0.0]
将jar
部署到本地keycloak
(如果之前未下载过,脚本将自动下载keycloak
的zip
存档)。
(*) 方括号内参数可选,默认版本为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
org.jboss.as.server
不应依赖于 RESTEasy 模块。 您需要您的部署依赖于它。 如果定义了jaxrs
子系统,这应该默认发生。
如果 jaxrs 子系统不存在,您可以使用jboss-deployment-structure.xml
或清单条目将依赖项添加到您的部署中。 对于清单条目,只需将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
“服务”部分只是导入服务。 在某些情况下可能不需要这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.