JBoss EAP中@TransactionAttribute注解偶发失效问题求助
EJB方法级@TransactionAttribute偶发失效问题分析
环境信息
- JBoss EAP 7.3.9(standalone-full模式)
- ORM框架:EclipseLink
- EJB类:
UserServiceImpl(标注@Stateless,类级@TransactionAttribute(TransactionAttributeType.NEVER)),其中重写方法getUserByUsername标注@TransactionAttribute(TransactionAttributeType.SUPPORTS)
偶发错误栈
Caused by: javax.ejb.EJBException: WFLYEJB0063: Transaction present on server in Never call (EJB3 13.6.2.6) at org.jboss.as.ejb3.tx.CMTTxInterceptor.never(CMTTxInterceptor.java:349) at org.jboss.as.ejb3.tx.LifecycleCMTTxInterceptor.processInvocation(LifecycleCMTTxInterceptor.java:62)
相关代码
@Stateless @TransactionAttribute(TransactionAttributeType.NEVER) @Interceptors(ServiceExceptionInterceptor.class) public class UserServiceImpl extends GenericCountry<LanguageDefinition> implements UserService { @Override @TransactionAttribute(TransactionAttributeType.SUPPORTS) public UserDto getUserByUsername(String username) { return userFacade.getUserByUsername(username); } } public interface UserService { UserDto getUserByUsername(String username); }
数据源配置(standalone-full.xml)
<datasources> <datasource jta="true" jndi-name="java:/jdbc/test" pool-name="test2" enabled="true" use-java-context="true" use-ccm="true"> <connection-url>jdbc:oracle:thin:@localhost:9090:ddjboss</connection-url> <driver>oracle</driver> <pool> <min-pool-size>1</min-pool-size> <max-pool-size>15</max-pool-size> <prefill>true</prefill> <use-strict-min>false</use-strict-min> <flush-strategy>FailingConnectionOnly</flush-strategy> <allow-multiple-users>false</allow-multiple-users> </pool> <security> <user-name>111</user-name> <password>111</password> </security> </datasource> </datasources>
Persistence配置(persistence.xml)
<persistence-unit name="test" transaction-type="JTA" > <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/test2</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <properties> <property name="eclipselink.target-database" value="Oracle"/> <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/> </properties> </persistence-unit>
可能的问题原因
1. JBoss EJB代理的元数据加载异常
JBoss EAP在处理EJB代理实例时,偶发会出现方法级注解元数据读取不完整的情况。尤其是当EJB存在继承关系(UserServiceImpl继承自GenericCountry)且方法为接口重写方法时,容器在实例池复用、类加载器状态异常等场景下,可能错误地优先使用类级事务注解,忽略方法级的覆盖配置。
2. 自定义拦截器的干扰
@Interceptors(ServiceExceptionInterceptor.class)可能在某些执行路径中打乱了事务拦截器的优先级。如果自定义拦截器涉及事务上下文操作,或者拦截器排序配置异常,会导致事务拦截器无法正确读取方法级的注解配置。
3. JBoss EAP版本已知BUG
JBoss EAP 7.3.x系列存在部分EJB事务注解继承的偶发BUG,尤其是类级注解为NEVER、方法级覆盖为其他属性的场景。可以排查官方补丁记录,确认7.3.10及后续版本是否修复了该类问题。
4. 事务上下文泄漏
调用方代码偶发存在未正确关闭的事务上下文,导致调用getUserByUsername时,当前线程仍绑定了未提交/回滚的事务。此时若容器误读取类级NEVER注解,就会触发异常。需要排查调用链路的事务管理是否存在资源泄漏。
5. EclipseLink隐式事务的影响
虽然方法标注SUPPORTS,但userFacade.getUserByUsername内部若触发EclipseLink的隐式事务(如缓存刷新、懒加载),且外部存在未清理的事务上下文,可能导致容器误判当前方法的事务属性,进而触发类级注解的校验逻辑。
内容的提问来源于stack exchange,提问作者Олег Гаврилів
相关产品推荐
相关产品推荐

