Wednesday, March 21, 2012

Fix javax.ejb.NoSuchEJBException: Could not find stateful bean on Seam and JBPM4

When I was using Google to look for answers to my problem, I found a lot of posts asking for a solution, just like me, but not a concrete answer (IMHO, JBoss has really poor documentation, compared with Spring, even their forums have less information), like this case

But I got a solution!!! (u_u)
Let me tell you my story...

On one of my Handlers I was using a ServiceImpl, just like this:
This is my ServiceImpl
And my getSeamComponentInstance method

As you can see, this doesn't have anything really weird, I just injecting a Bean into another class, and invoke one its methods! Simple (pure DI)

When you test it, it works! After it's been deployed, it works again, but...

After some period of inactivity... Boooom! The same line of code (the one where I invoke one of the methods of my ServiceImpl) was throwing an this
javax.ejb.NoSuchEJBException: Could not find stateful bean: 4sg5nl-4371oh-gsvwkdiv-1-gsvwst2j-1b
 at org.jboss.ejb3.cache.simple.SimpleStatefulCache.get(SimpleStatefulCache.java:492)
 at org.jboss.ejb3.cache.simple.SimpleStatefulCache.get(SimpleStatefulCache.java:443)
 at org.jboss.ejb3.stateful.StatefulInstanceInterceptor.invoke(StatefulInstanceInterceptor.java:61)
 at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
 at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
 at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:106)
 at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
 at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
 at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
 at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
 at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
 at org.jboss.ejb3.stateful.StatefulContainer.localInvoke(StatefulContainer.java:204)
 at org.jboss.ejb3.stateful.StatefulLocalProxy.invoke(StatefulLocalProxy.java:117)
 at $Proxy81.afterTransactionRollback(Unknown Source)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
 at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32)
 at org.jboss.seam.intercept.ClientSideInterceptor$1.proceed(ClientSideInterceptor.java:76)
 at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
 at org.jboss.seam.intercept.ClientSideInterceptor.invoke(ClientSideInterceptor.java:54)
 at org.javassist.tmp.java.lang.Object_$$_javassist_seam_5.afterTransactionRollback(Object_$$_javassist_seam_5.java)
 at org.jboss.seam.transaction.UTTransaction.rollback(UTTransaction.java:70)
 at org.jboss.seam.util.Work.workInTransaction(Work.java:68)
 at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91)
 at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
 at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
 at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
 at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
 at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)
 at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)
 at com.kaplan.service.impl.StudentDetailsServiceImpl_$$_javassist_seam_11.updateStudentDetails(StudentDetailsServiceImpl_$$_javassist_seam_11.java)
 at com.kaplan.jbpm.action.integration.jbpm4.UpdateStudentActionHandler.execute(UpdateStudentActionHandler.java:44)
 at org.jbpm.pvm.internal.wire.usercode.UserCodeActivityBehaviour.execute(UserCodeActivityBehaviour.java:42)
 at org.jbpm.pvm.internal.model.op.ExecuteActivity.perform(ExecuteActivity.java:60)
 at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperationSync(ExecutionImpl.java:672)
 at org.jbpm.pvm.internal.model.op.ExecuteActivityMessage.executeVoid(ExecuteActivityMessage.java:45)
 at org.jbpm.pvm.internal.job.MessageImpl.execute(MessageImpl.java:46)
 at org.jbpm.pvm.internal.job.MessageImpl.execute(MessageImpl.java:32)
 at org.jbpm.pvm.internal.cmd.ExecuteJobCmd.execute(ExecuteJobCmd.java:79)
 at org.jbpm.pvm.internal.cmd.ExecuteJobCmd.execute(ExecuteJobCmd.java:41)
 at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)
 at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:50)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
 at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:56)
 at org.jbpm.pvm.internal.svc.SkipInterceptor.execute(SkipInterceptor.java:43)
 at org.jbpm.pvm.internal.jobexecutor.JobParcel.run(JobParcel.java:48)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
 at java.util.concurrent.FutureTask.run(FutureTask.java:138)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:619)

WTF!!!

What!!! I'm not even using stateful beans!!!, I'm using plain POJO's not even stateless!
This is how it works Seam, when you inject a Component using Components.getInstance, you just get a Proxy, and that proxy references the REAL instance of the class you want to invoke, but for any weird reason, that instance it has been removed! Then, why the freaking Proxy points to a nonexistent object? No idea (u_u).

Let's force Seam to create a new instance if it doesn't exist and specify that I don't want a Stateful bean by passing the scope Stateless (you can try with another one, but Stateless seems to be working just fine) and this is it


And after 1 night of inactivity, the error was gone (one for the team!)