@Singleton bean failed to initialize because of not expected transaction status 4 when it's marked TransactionAttribute=NOT_SUPPORTED

旧时模样 提交于 2019-12-05 19:17:52

N.B. This was not originally an answer but just some more useful info in digging in to find answers to such problems as there really isn't much on-line in this area. After some additional effort, the cause and an answer have since been found. The answer has been left in its original format with new findings documented as edits and debug help left in-tact to hopefully ease the debugging of others with similar issues. This is a dark place.

Well, still no firm answer to the above issue and the problem seems to have gone away.

I have found though (looking at a different NoSuchEJBException issue) that the underlying cause is swallowed by the WLS stack.

This is the sensible place to start looking for SingletonBean failed to init NosuchEJBException issues in cases where you don't make it into your PostConstruct method (i.e. your bean could not be created):

SingletonSessionManager$SingletonLifecycleManager.doActualInit() line: 819   
SingletonSessionManager$SingletonLifecycleManager.initInternal(boolean) line: 744     
SingletonSessionManager$SingletonLifecycleManager.getBean() line: 648           
SingletonSessionManager.getBeanFor(InvocationWrapper) line: 285      

Initially, root exceptions are caught and included into the NoSuchEJBExceptions raised in the lower levels, as above. However, at the point in the stack below, the NoSuchEJBException is replaced with an InternalError that gets wrapped and the cause(s) lost. Curiously, it may even set itself as the cause (debugger goes a bit haywire):

SingletonSessionManager#getBeanFor

So, this is a prime place for finding what the root exception may be.

FYI: My problem in the second instance was a spring-injection issue within WLS (spring-repackaged) where a datasource wasn't beig properly injected into my ELB service impl as the datasource didn't exist with the @Resource(name="...") JNDI name. This wasn't logged at all due to the aforementioned exception-handling issue. Once I'd stepped through and found the cause, it was an easy fix. Shame to have to spend so much time finding it out.

[EDIT] FYI: It seems my problem causing the "InternalException Transaction Rolled-back status 4" exception may have been due to the EJB init (PostConstruct) exceeding the transaction timeout. This should be irrelevant if my EJB is set as @TransactionAttribute(NOT-SUPPORTED) but apparently not so. Debugging revealed that for this and @TransactionAttribute(NEVER), there is an invokeTx used at the level of the SingletonSessionManager#constructAndInitBean and managed within the InvocationWrapper. So, the timeout would cause the rollback, leading to the InternalException, mapped to the NoSuchEJBException, swallowed by the other NoSuchEJBException leading to a rubbish error message.

[EDIT2] FYI: It seems this is due to a bug in WLS where the invokeTx is set and managed when it shouldn't be for @TransactionAttribute(NOT-SUPPORTED). We've raised a bug with Oracle who have given it a sev 2. In the meantime, we've moved potentially time-consuming (network-dependent) code out of the @PostConstruct method as a workaround.

[EDIT3] FYI: From Oracle ... The class level transaction attribute annotation is not enforced on singleton lifecycle interceptors postconstrcut/predestroy, so it defaults to REQUIRED.

They concur that this is an issue and are looking into it. In the meantime, ensure transaction timeouts aren't breached by code within your @PostConstruct. This would include latency-based timeouts (our issue was intermittent as it depended on which geographical "server" was accessed).

Debugging tips

As a debugging process, btw, I suppose I would:

  1. Put a breakpoint in your EJB init (@PostConstruct) method and unwind until you see the exception occur in your debug values.
  2. If you don't hit your init, put breakpoints as close as possible to the WLS #doActualInit listed above and find your way into the init methods. then, just watch for when the exception is first raised. Note, you may have to put your breakpoint inside InvocationHandler#invoke to get near this through the proxy layers (or roll your own).
  3. If you do hit it, watch the unwinding stack by putting a breakpoint in your init and unwinding or in EjbComponentCreatorImpl.invokePostConstruct(Object, String) and watching.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!