Friday, April 13, 2012

Delegate to Seam the management of my JBPM4 engine

The problem was really simple, it's just implement a Singleton without writing it :P

I have a simple class, but I just need it to be loaded when the app starts, because my class will load the JBPM4 engine (and that should be done only once - this process may take up to 4 seconds, which will make really slow the first request coming to my End-Point)
But let me write more code and less words
Just add to your class these tags
Define which method will be your Creation method (Initialization method), on my case the one which will load the Engine
Now the one which will Destroy your class (shutdown my JBPM4 engine) and release resources
and optionally, your Constructor

Simple, Isnt' it?
Now you can inject this Seam Component using Injection into another Seam Component, just like this


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!)