升级TomEE 9.1.0至9.1.1/9.1.2后JakartaEE应用出现注入解析异常
升级JakartaEE 9.1(TomEE 9.1.1+)时CDI注入UnsatisfiedResolutionException问题排查
问题背景
我们正在将应用从JavaEE 7(JDK 1.8,TomEE-7.1.X)升级至JakartaEE 9.1(JDK 11,TomEE-9.1.X)。由于TomEE 9.1.0使用的cxf-3.5存在问题,我们尝试升级到TomEE 9.1.1/9.1.2版本(从9.1.1开始改用cxf-4.0.3,可解决部分问题)。但使用9.1.1及以上版本时,Web应用无法部署,报错为特定@Inject注入引发的UnsatisfiedResolutionException。移除使用该注入的3个bean后,应用即可正常运行。注意三个TomEE 9.1.X版本使用的OpenWebBeans(CDI实现)版本一致。
上下文:被注入的是一个@ApplicationScoped注解的bean,作为与IAM服务器通信的单点联系人。
控制台报错信息
INFORMATION: Deployment of web application directory [C:\dev\srv\apache-tomee-plus-9.1.2\SheepWeb-local\webapps\manager] has finished in [2.120] ms Feb. 01, 2024 2:30:09 NACHM. org.apache.openejb.cdi.OpenEJBLifecycle startApplication SCHWERWIEGEND: CDI Beans module deployment failed org.apache.webbeans.exception.WebBeansDeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Api type [ch.qual.base.web.auth.oic.OpenIDConnectService] is not found with the qualifiers Qualifiers: [@jakarta.enterprise.inject.Default()] for injection into Field Injection Point, field name : openIDConnectService, Bean Owner : [Authentication, WebBeansType:MANAGED, Name:Auth_m, API Types:[java.lang.Object,ch.qual.base.web.auth.beans.Authentication,java.io.Serializable], Qualifiers:[jakarta.enterprise.inject.Default,jakarta.enterprise.inject.Any,jakarta.inject.Named]]
相关代码
接口代码
package ch.qual.base.web.auth.oic; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import java.net.URL; import java.util.Locale; public interface OpenIDConnectService { boolean iamEnabled(); String createAuthenticationURL( Integer clientIndex, String redirectURL, Locale userLocale); AuthenticationInfo registerUser( Integer clientIndex, AuthenticationInfo authenticationInfo, String accessCode); //更多方法省略 }
实现类代码
package ch.qual.base.web.auth.oic; imports... @ApplicationScoped public class QOpenIDConnectServiceImpl implements OpenIDConnectService, Serializable { private static final long serialVersionUID = -3637502198182884565L; private static final Logger log = LoggerFactory.getLogger(QOpenIDConnectServiceImpl.class); //大量私有静态常量已省略 private static final String URLPATH_AUTHSERVER_REALM_BASE = "auth/realms/"; private static final String URLPATH_AUTHSERVER_ADMIN_BASE = "auth/admin/"; @Inject private SecurityModuleConfiguration securityModuleConfiguration; @Inject private ClientConfig clientConfig; private boolean iamInitialized = false; private String serverURL; private HashMap<Integer, AuthenticationRealmConfiguration> realmStore; // 初始化与销毁 @PostConstruct public void init() { //从IAM服务器加载信息 } ... }
beans.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd" bean-discovery-mode="all" version="3.0"> </beans>
排查方向与解决方案
- 确认JakartaEE注解包名迁移彻底:检查
QOpenIDConnectServiceImpl上的@ApplicationScoped是否属于jakarta.enterprise.context.ApplicationScoped,而非旧的javax包下注解。混用旧包注解会导致OpenWebBeans无法识别该bean。 - 排查实现类依赖注入有效性:实现类中注入的
SecurityModuleConfiguration和ClientConfig是否能被CDI容器正常识别?可暂时注释这两个注入点,测试应用是否能部署,以此判断是否是依赖bean的问题。 - 检查类加载冲突:TomEE 9.1.1+升级了CXF版本,可能引发类加载冲突。通过JVM参数
-verbose:class查看OpenIDConnectService接口和实现类的加载路径,确保类只被加载一次,避免lib目录与WEB-INF/lib重复存在相关jar。 - 验证CDI扫描范围:即使
beans.xml设置了bean-discovery-mode="all",仍需确认QOpenIDConnectServiceImpl所在包被CDI容器扫描到。若类在外部jar中,需确保jar放置在WEB-INF/lib,且jar内包含有效的beans.xml(若为CDI模块)。 - 检查PostConstruct方法异常:
init()方法若抛出未捕获异常,会导致bean初始化失败,容器会判定该bean不存在。可添加完整异常捕获,或暂时注释init方法内逻辑,测试部署情况。 - 查看OpenWebBeans详细日志:将
org.apache.webbeans日志级别设为DEBUG,查看CDI容器启动时的扫描与注册日志,确认QOpenIDConnectServiceImpl是否被注册为bean,以及是否存在注册失败原因。
内容的提问来源于stack exchange,提问作者Raphael_S
相关产品推荐
相关产品推荐

