Caused by: java.lang.ClassNotFoundException: org.apache.dubbo.config.ReferenceConfig

I customized an UserStorageProviderFactory, implemented the UserStorageProviderFactory interface, and placed the UserStorageProviderFactory in the 【services】 package. In the pom.xml file under services, I also introduced the dubbo dependency, but when executing the code, the following error is reported: How can I solve this problem?

package org.keycloak.authentication.authenticators.custom;

import com.jdsc.atom.identity.client.credential.facade.CredentialQueryFacade;
import com.jdsc.atom.identity.client.spoperator.facade.SpOperatorInfoFacade;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.storage.UserStorageProviderFactory;

import java.util.Collections;
import java.util.List;

/**
 * @author zhengzhijie
 * @Date 2025/2/28 14:57
 */
public class ExternalUserStorageProviderFactory implements UserStorageProviderFactory<ExternalUserStorageProvider> {

    public static final String PROVIDER_NAME = "external-user-storage";

    @Override
    public ExternalUserStorageProvider create(KeycloakSession session, ComponentModel model) {
        // 创建并返回您的UserStorageProvider实例
        // 这里可以传递任何必要的配置或服务实例
//        ExternalUserService externalUserService = new ExternalUserService(); // 您的外部服务实例

        // 配置当前应用的信息
        ApplicationConfig applicationConfig = new ApplicationConfig("sso-api");

        // 配置服务引用
        ReferenceConfig<SpOperatorInfoFacade> spOperatorInfoFacadeReference = new ReferenceConfig<>();
        spOperatorInfoFacadeReference.setInterface(SpOperatorInfoFacade.class);
        spOperatorInfoFacadeReference.setTimeout(3000);

        ReferenceConfig<CredentialQueryFacade> credentialQueryFacadeReference = new ReferenceConfig<>();
        credentialQueryFacadeReference.setInterface(CredentialQueryFacade.class);
        credentialQueryFacadeReference.setTimeout(3000);

        // 初始化 Dubbo
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
            .reference(spOperatorInfoFacadeReference)
            .reference(credentialQueryFacadeReference)
            .start();

        // 获取服务实例
        SpOperatorInfoFacade spOperatorInfoFacade = spOperatorInfoFacadeReference.get();

        return new ExternalUserStorageProvider(session, model, spOperatorInfoFacade);
    }

    @Override
    public String getId() {
        // 返回该Provider的唯一标识符
        return PROVIDER_NAME;
    }

    @Override
    public void init(org.keycloak.Config.Scope config) {
        // 初始化配置(如果需要)
    }

    @Override
    public void postInit(KeycloakSessionFactory factory) {
        // 在Keycloak初始化后执行的操作
    }

    @Override
    public void close() {
        // 清理资源(如果需要)
    }

    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        // 返回配置属性(如果需要)
        return Collections.emptyList();
    }

    @Override
    public String getHelpText() {
        return "External User Storage Provider";
    }
}

2025-03-01 14:03:54,553 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-2) Uncaught server error: java.lang.NoClassDefFoundError: org/apache/dubbo/config/ReferenceConfig
        at org.keycloak.authentication.authenticators.custom.ExternalUserStorageProviderFactory.create(ExternalUserStorageProviderFactory.java:35)
        at org.keycloak.authentication.authenticators.custom.ExternalUserStorageProviderFactory.create(ExternalUserStorageProviderFactory.java:21)
        at org.keycloak.storage.AbstractStorageManager.getStorageProviderInstance(AbstractStorageManager.java:228)
        at org.keycloak.storage.AbstractStorageManager.lambda$getEnabledStorageProviders$0(AbstractStorageManager.java:98)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:400)
        at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
        at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:528)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
        at org.keycloak.storage.UserStorageManager.getUserByUsername(UserStorageManager.java:429)
        at org.keycloak.models.cache.infinispan.UserCacheSession.getUserByUsername(UserCacheSession.java:275)
        at org.keycloak.authentication.authenticators.custom.captcha.CaptchaAuthenticator.action(CaptchaAuthenticator.java:161)
        at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:149)
        at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:1055)
        at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:378)
        at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:349)
        at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:341)
        at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:407)
        at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_13d428b70e62601585246c086a52f40868a3208e.invoke(Unknown Source)
        at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
        at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:639)
        at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
        at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: java.lang.ClassNotFoundException: org.apache.dubbo.config.ReferenceConfig
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
        at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:114)
        at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:72)
        ... 36 more


Are you including the “dubbo” jar in your /opt/keycloak/providers/ directory when you deploy your custom extension? Simply adding it to the pom is insufficient – you have to include everything it depends on that isn’t already included in Keycloak.