我的 EJB3.1 bean 初始化遇到了困难,更具体地说,由于感知到的事务回滚而导致它失败,即使我已经用@TransactionAttribute(NOT_SUPPORTED)
. 这应该意味着任何客户端事务都会在 bean 方法进入时暂停,直到退出(何时恢复。这绝对是我想要的事务方法。
代码和错误的“要点”如下(注意其中一些是手动操作以隐藏细节,但都是相关且具有代表性的):
@Singleton(name = "MyClass")
@ConcurrencyManagement(value = BEAN)
@TransactionAttribute(value = NOT_SUPPORTED)
@Local(MyInterface.class)
public class MyClass implements MyInterface {
@PostConstruct
public void init() throws MyException {
try {
...
} catch LowerLevelException e) {
throw new MyException("problem", e);
}
}
public Object doSomething(...) throws MyException {
...
}
...
}
这会引发以下错误:
javax.ejb.NoSuchEJBException: Singleton MyClass(Application: my-ear, EJBComponent: my-ejb.jar) failed to initialize.
其中,当我调试时实际上包装了以下异常:
weblogic.ejb.container.InternalException: Transaction marked rollback or not expected transaction status: 4
同样,调试提出了一些有趣的细节:
- 首先,我
MyClass#init
的执行完全成功,没有任何问题/异常。 - 在第 一次从客户端代码
#init
调用我的#doSomething
方法时调用(作为构建后的一部分)。 MyClass#doSomething
因此,在客户端调用down to#init
和在这些层之一内部引发异常之间存在大量堆栈间接级别。它是在 WLS Singleton 会话 bean 管理代码中提出的。见下文...
堆栈类似于下面的(MyClass 名称已更改):
MyClass_fefgu8_Impl(MyClass).init() line: 96
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 601
Jsr250Metadata.invokeLifecycleMethod(Object, Method, Object[]) line: 393
InterceptionMetadata(Jsr250Metadata).invokeLifecycleMethods(Object, LifecycleEvent) line: 365
InterceptionMetadata.invokeLifecycleMethods(Object, LifecycleEvent) line: 403
EjbComponentCreatorImpl.invokePostConstruct(Object, String) line: 80
SingletonSessionManager.constructAndInitBean() line: 369
SingletonSessionManager.access$300(SingletonSessionManager) line: 63
SingletonSessionManager$SingletonLifecycleManager.doActualInit() line: 798 <== InternalException raised here
SingletonSessionManager$SingletonLifecycleManager.initInternal(boolean) line: 744
SingletonSessionManager$SingletonLifecycleManager.getBean() line: 648
SingletonSessionManager.getBeanFor(InvocationWrapper) line: 285
SingletonSessionManager.preInvoke(InvocationWrapper) line: 147
SingletonLocalObject(BaseLocalObject).getBeanInstance(InvocationWrapper) line: 146
SingletonLocalObject(BaseLocalObject).preInvoke(InvocationWrapper, ContextHandler, boolean, boolean) line: 103
SingletonLocalObject(BaseLocalObject).__WL_preInvoke(InvocationWrapper, ContextHandler) line: 67
SessionLocalMethodInvoker.invoke(Invokable, BaseLocalObject, InvocationWrapper, Object[], int) line: 20
MyClass_fefgu8_MyInterfaceImpl.doSomething(String, String, String, String) line: not available
并且事务回滚异常实际上是在堆栈帧中引发的:
SingletonSessionManager$SingletonLifecycleManager.doActualInit() line: 798
这个级别确实与事务管理器打交道,但我不知道为什么它应该尝试将事务标记为回滚,尤其是在从主应用程序代码成功初始化之后。
我正在使用此 EJB 组件来编译此 bean,但我们在服务器(或课程)上使用 WLS EJB 代码:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.ejb</artifactId>
<version>3.1</version>
<scope>provided</scope>
</dependency>
我把它放在那里的原因是它被证明很棘手,网上很少有宝贵的东西(尤其是交易状态 4),我在上面花了太长时间,需要继续前进。我正在继续寻找,但我想我周一回来时可能会获得更多线索。
我已经重新阅读了很多关于 EJB 事务处理的内容,但没有发现任何明显的问题。我相信我正在使用正确的机制来处理我的 bean 中的事务(即它是非事务性的)。我还没有尝试将它放在描述符中(我只是想到并会试一试)。我还没有深入研究它是如何SingletonSessionManager$SingletonLifecycleManager.doActualInit
工作的,但是关于它的在线信息并不多。
问题
换句话说,问题是...... - 我错过了什么,所以我的 bean 方法不参与任何提供的事务,或者更具体地说,不试图将事务标记为回滚?- 如果我明确告诉它不要“支持”(关心)任何交易,为什么它会因为这个错误而无法初始化?
注意我已经检查了这个@Singleton bean 未能初始化,因为不是预期的事务状态 1问题,但我的场景与 Java EE 安全角色权限无关(我不认为!)
谢谢。
更新 1
好吧,最新的是删除我的@TransactionAttribute
注释似乎让我摆脱了失败。这很奇怪,因为默认值应该是TransactionAttributeType#Required,实际上,我们在堆栈跟踪中有一个附加层,如果我调试时间过长,那么我的 bean init 中就会出现事务超时。
查看堆栈跟踪中的以下级别(慢慢接下来),我看到有一个事务(实际上是两个):
SingletonSessionManager.constructAndInitBean() line: 377
wrap weblogic.ejb.container.internal.InvocationWrapper (id=15676)
L callerTx weblogic.transaction.internal.ServerTransactionImpl (id=15681)
L invokeTx weblogic.transaction.internal.ServerTransactionImpl (id=15683)
我将检查这些是否存在于预删除@TransactionAttribute
场景中,并尝试观看ServerTransactionImpl
。
更新 2
上次更新了一段时间......但是,我想我已经在上面的原始堆栈跟踪中追踪到SingletonSessionManager#postCallback
了这个问题。SingletonSessionManager#constructAndInitBean
(我需要确认这一点,因为我的线索是通过交易案例来确定的)。如果/何时会报告,但似乎我们在此处尝试回滚不存在的事务时可能会失败。