[英]Calling non-transactional method after transaction is rolled back
I've just found some EJB behaviour which looks rather surprizing to me. 我刚刚发现了一些EJB行为,这对我来说似乎很令人惊讶。
Here is the code sample (for sure MyBean, beanA, beanB are EJBs using CMT): 这是代码示例(确保MyBean,beanA,beanB是使用CMT的EJB):
@Stateless
public class MyBean {
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void myMethod(){
try {
beanA.methodA(); /* annotated as REQUIRED */
} catch (Exception e) {
beanB.methodB(); /* annotated as NOT_SUPPORTED */
}
}
}
Lets's say methodA takes more than transaction timeout to execute, so once it returns myMethod receives TransactionRolledbackException, which is successfully caught then in "myMethod". 假设methodA花费了超过事务超时的时间,因此一旦返回myMethod,它就会收到TransactionRolledbackException,然后成功将其捕获到“ myMethod”中。
I would expect "methodB" be called so far, as accordingly with EJB spec it must be called without any transaction context. 我希望到目前为止,“ methodB”将被调用,因此,根据EJB spec,必须在没有任何事务上下文的情况下调用它。 But actually, the "beanB" proxy simply returns another TransactionRolledbackException, the "methodB" is not executed.
但实际上,“ beanB”代理仅返回另一个TransactionRolledbackException,“ methodB”未执行。
Looking through EJB spec I do not see anything to prove that container should or even might behave that way. 查看EJB规范,我没有发现任何证据可以证明容器应该甚至可能以这种方式运行。
Do I miss something? 我想念什么吗? Any hint would be appreciated.
任何提示将不胜感激。
UPDATE UPDATE
At least for Websphere, this behaviour appears to be timeout-specific. 至少对于Websphere,此行为似乎是特定于超时的。 The "rollbackOnly" flag which for example is set when "methodA" throws a RuntimeException, does not prevent "methodB" from execution.
例如,当“ methodA”引发RuntimeException时设置的“ rollbackOnly”标志不会阻止“ methodB”的执行。 Only timeout flag does.
只有超时标志可以。
The EJB specification does not specifically address this scenario, other than to indicate that once a transaction has been marked for rollback, then " Continuing transaction is fruitless ", and for the handling of NOT_SUPPORTED
, the specification indicates it " does not prescribe how the container should manage the execution of a method with an unspecified transaction context ". EJB规范没有专门针对这种情况,只是指出一旦将事务标记为回滚,然后“ 继续事务是没有结果的 ”,并且对于
NOT_SUPPORTED
的处理,规范表明它“ 没有规定容器如何应该使用未指定的事务上下文来管理方法的执行 ”。
All versions of WebSphere Application Server have taken the approach that the best way to handle the scenario where an EJB method has been marked for rollback only is to prevent all further actions the container has control over, so that the transaction may be rolled back as quickly as possible, ensuring the timely release of resources (such as database locks). 所有版本的WebSphere Application Server都采用这样的方法来处理仅将EJB方法标记为回滚的方案的最佳方法是防止容器可以控制的所有其他操作,以便可以尽快回滚事务。尽可能确保及时释放资源(例如数据库锁)。 Allowing a call to a
NOT_SUPPORTED
EJB method would result in the marked for rollback transaction being suspended; 允许调用
NOT_SUPPORTED
EJB方法将导致标记为回滚的事务被挂起。 and thus continue to hold onto resources that could block or already be blocking other transactions. 因此会继续保留可能阻止或已经阻止其他事务的资源。 For this reason, WebSphere prevents such activity.
因此,WebSphere阻止了这种活动。
Faced the similar issue a while back . 不久前面临类似问题。 When the container mark the transaction for rollback you will not be able to do any other EJB calls after that.
当容器将事务标记为回滚时,此后您将无法执行任何其他EJB调用。 You can think about a solution of annotating @RequiresNew for beanA.methodA() , so that it will not share the global transaction of myMethod() and will always use new transaction.
您可以考虑为beanA.methodA()注释@RequiresNew的解决方案,以便它不会共享myMethod()的全局事务,并且将始终使用新事务。 Therefore anything happens to this new transaction will not affect the global transaction so that you can proceed with your further EJB calls.
因此,此新事务发生的任何事情都不会影响全局事务,因此您可以继续进行进一步的EJB调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.