Keycloak自定义事件监听器启动报错:无法加载User_expleo类
问题描述
使用Keycloak 23.0.7 + JDK17,在Spring Boot项目中开发自定义事件监听器,执行mvn clean install后将jar包放入Keycloak的providers目录,启动Keycloak时报错无法找到com.expleo.msauth.entity.User_expleo类。
错误日志
Updating the configuration and installing your custom providers, if any. Please wait.
2024-03-12 09:39:04,854 WARN [io.quarkus.deployment.steps.ClassTransformingBuildStep] (build-18) Cannot transform com.expleo.msauth.entity.User_expleo as its containing application archive could not be found.
2024-03-12 09:39:11,757 INFO [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 16764ms
ERROR: Unexpected error when starting the server in (development) mode
ERROR: Failed to start quarkus
ERROR: Unable to load class [com.expleo.msauth.entity.User_expleo]
ERROR: com.expleo.msauth.entity.User_expleo
For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.
相关代码
自定义事件监听器(CustomEventListener.java)
package com.expleo.msauth.event; import org.keycloak.events.Event; import org.keycloak.events.EventListenerProvider; import org.keycloak.events.EventType; import org.keycloak.events.admin.AdminEvent; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmProvider; public class CustomEventListener implements EventListenerProvider { private KeycloakSession session; public CustomEventListener(KeycloakSession session) { this.session = session; } @Override public void onEvent(Event event) { System.out.println("Hi this event listner when user had registration + "+event.getType().name()); } @Override public void onEvent(AdminEvent adminEvent, boolean b) { System.out.println("Hi this event listner for admin when user had registration + "+adminEvent.getId()); } @Override public void close() { } }
自定义事件监听器工厂类(CustomEventListenerProviderFactory.java)
package com.expleo.msauth.event; import org.keycloak.Config; import org.keycloak.events.EventListenerProvider; import org.keycloak.events.EventListenerProviderFactory; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListenerFactory; import java.lang.reflect.Method; public class CustomEventListenerProviderFactory implements EventListenerProviderFactory { @Override public EventListenerProvider create(KeycloakSession keycloakSession) { return new CustomEventListener(keycloakSession); } @Override public void init(Config.Scope scope) { } @Override public void postInit(KeycloakSessionFactory keycloakSessionFactory) { } @Override public void close() { } @Override public String getId() { return "CustomEventListener"; } }
User_expleo实体类(User_expleo.java)
package com.expleo.msauth.entity; import com.expleo.msauth.enums.Status; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @Builder @NoArgsConstructor @AllArgsConstructor @Entity public class User_expleo { @Id private String id; private String firstName; private String lastName; private String userName; private String email; private String password; @Enumerated(EnumType.STRING) @Column(columnDefinition = "varchar(255) default 'OFFLINE'") private Status status; }
解决方案
1. 检查jar包是否包含缺失类
解压生成的jar包,确认com/expleo/msauth/entity/User_expleo.class文件是否存在:
- 若不存在,检查Maven配置,确保该类所在模块未被打包插件排除;多模块项目需确认监听器模块已正确依赖包含该实体类的模块。
2. 移除Spring相关依赖与代码
Keycloak基于Quarkus运行,不兼容Spring上下文,需清理工厂类中的Spring相关内容:
- 删除以下导入语句:
import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListenerFactory; - 移除未使用的
java.lang.reflect.Method导入。
3. 按Keycloak扩展规范打包
普通Spring Boot jar无法直接作为Keycloak扩展使用,需调整打包配置:
- 在
pom.xml中添加Keycloak扩展打包插件:<build> <plugins> <plugin> <groupId>org.keycloak</groupId> <artifactId>keycloak-maven-plugin</artifactId> <version>23.0.7</version> <executions> <execution> <id>build</id> <goals> <goal>build</goal> </goals> </execution> </executions> </plugin> </plugins> </build> - 执行
mvn clean install后,将target目录下生成的扩展jar(通常带-keycloak-extension后缀)放入Keycloak的providers目录。
4. 重新构建Keycloak配置
放入扩展jar后,执行构建命令让Keycloak识别扩展:
# Linux/macOS ./kc.sh build # Windows kc.bat build
完成后再启动Keycloak。
5. 确保实体类依赖被打包
User_expleo使用了JPA和Lombok,需确保这些依赖被包含进jar:
- 在
pom.xml中设置相关依赖的scope为compile,避免设为provided或test; - 若需,使用
maven-shade-plugin将所有依赖打包成一个jar,防止依赖缺失。
内容的提问来源于stack exchange,提问作者youssef elmesbahi

