Showing posts with label JBPM. Show all posts
Showing posts with label JBPM. Show all posts

Sunday, July 1, 2012

Logging Optimistic Concurrency Exceptions: org.hibernate.StaleObjectStateException and JBPM

When it is running in a cluster configuration, the jBPM synchronizes with the database by using optimistic locking. This means that each operation is performed in a transaction and if, at the end, a collision is detected, then the transaction in question is rolled back and has to be handled with a retry. This can cause org.hibernate.StateObjectStateException exceptions. When this happens, Hibernate will log the exceptions with a simple message: optimistic locking failed

Hibernate can also log the StateObjectStateException with a stack trace:
15:35:07,123 [DispatcherThread] ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#960071]
 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1769)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2412)
 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
 at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
 at org.jbpm.pvm.internal.tx.HibernateSessionResource.prepare(HibernateSessionResource.java:56)
 at org.jbpm.pvm.internal.tx.StandardTransaction.commit(StandardTransaction.java:107)
 at org.jbpm.pvm.internal.tx.StandardTransaction.complete(StandardTransaction.java:64)
 at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:57)
 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.DispatcherThread.acquireJobs(DispatcherThread.java:126)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.run(DispatcherThread.java:67)

To remove these stack traces, set the org.hibernate.event.def.AbstractFlushingEventListener class to FATAL. Do so in log4j by using the following configuration:
log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=FATAL

Remember, this exception will not affect your process execution!, you can ignore it :)

Source: http://docs.redhat.com/docs/en-US/JBoss_Enterprise_SOA_Platform/5/html/JBPM_Reference_Guide

Tuesday, May 1, 2012

JBPM and Clustering

I'll be precise: "Can JBPM be deployed in a Distributed environment?"
In other words, Can I deploy multiple instances of JBPM? (but I want only 1 JVM to control all the executions)

My answer is Yes, you can have that mode! Just need to disable the JobExecutor on the other instances (by altering the configuration file)


Otherwise, you'll see this exception on your consoles (If your JVM's fight for the JOB's):
15:51:55,379 [DispatcherThread] ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#385014]
 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1769)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2412)
 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
 at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
 at org.jbpm.pvm.internal.tx.HibernateSessionResource.prepare(HibernateSessionResource.java:56)
 at org.jbpm.pvm.internal.tx.StandardTransaction.commit(StandardTransaction.java:107)
 at org.jbpm.pvm.internal.tx.StandardTransaction.complete(StandardTransaction.java:64)
 at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:57)
 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.DispatcherThread.acquireJobs(DispatcherThread.java:126)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.run(DispatcherThread.java:67)

If you're too lazy to have specific configuration per JVM, and you don't care about those exceptions, you're good to go (because that exception does not impact the Execution of your process instance), however, you can hide it by using Log4J (I'll explain that in another post)

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

Sunday, February 5, 2012

StaleObjectStateException on JBPM4

When I was doing some testing to my recently implemented JBPM4 process, I faced a really ugly error, which ended abruptly my process :(

Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#17]

After researching on Jboss.org, I just found very few bread crumbs instead of the whole slice of bread:
StaleObjectException on Timer execution
My process was different, because mine was completely ASYNC, then I realize, what would happen if I make SYNC just the WAIT state (which was causing the problem) and keep ASYNC my other states. After my first test, I got what I was expecting :D

Wednesday, January 18, 2012

Migrating to JBPM4

As you well know, I was using for one of my projects JBPM3, but then I decided to to jump into something more stable and even cool! (which will give me more automatization and the ability to recover from server crashes - in other words, restart a process previously interrupted :) )

The API changed completely, some classes were renamed others were removed, methods are not the same, configuration is different, in a few words "It doesn't have any relation with the previous version"

Cons:


You won't be able to keep your logs or comments on your tables, no more Transient variables, no more stoping process due to Exceptions, no more suspend or resume process (using the API), poor history of each execution - but it really helps what you see (if you want more details, I recommend you to use wisely your Log4J), if you don't believe me, look at my base handler after I migrated


Pros:


Process definition is the same file which describes de Diagram spec (no more hidden files), configuration file is much simpler (the default params work really nice - It's almost ready for production out of the box), hibernate configuration is much easy to read, process could be started easily by using code (FEWER lines that in JBPM3), ASYNC process really work!, resume processes interrupted, you can define a business key for each execution - look into table JBPM4_HIST_PROCINST, Timer really works! - you'll see it on my process definition

This is how I started my process (due to my process is ASYNC, it doesn't wait until process is completed to return a response - which is great for Fire and Forget, obviously the first request will be the one which takes longer, because it will have to wait until everything is loaded but the next request will be super fast! - I've seen and Avg. of 70ms)

My process definition is cleaner and I really like it


Finally, let me show you a couple of Handlers, except for a few changes, I didn't change them a lot compared with my original JBPM3 code :) Cool beans!

Wednesday, November 9, 2011

Building from source BPM Console (for JBPM4)

For some personal reasons I wanted to customize the JBPM Console, so the only way to do it is by building from source code.
The first thing I had to do is get the sources and compile them using Maven :)

If by any chance you're having a hard time with this error (like me)
[ERROR] Failed to execute goal on project gwt-console: Could not resolve dependencies for project org.jboss.bpm:gwt-console:war:2.2.3-Final: The following artifacts could not be resolved: org.timepedia.chronoscope:chronoscope:jar:2.0_jboss-SNAPSHOT, org.timepedia.chronoscope:chronoscope-api:jar:2.0_jboss-SNAPSHOT: Failure to find org.timepedia.chronoscope:chronoscope:jar:2.0_jboss-SNAPSHOT in https://repository.jboss.org/nexus/content/groups/public/ was cached in the local repository, resolution will not be reattempted until the update interval of jboss-public-repository-group has elapsed or updates are forced -> [Help 1]

Just do as I did. Go to Maven Hub and search for your missing jar, on my case I found it on Thirdparty-uploads repository (from JBoss);

Unfortunately, the version I was looking for (according to the previous error) was chronoscope:jar:2.0_jboss-SNAPSHOT and I found 2.0_jboss, I guess you know what to do now, don't you?

Just cheat Maven by installing on your local repository version "2.0_jboss" as "2.0_jboss-SNAPSHOT"

Voila!!!

As result you should get these 4 artifacts:
  • Console UI: gwt-console.war
  • Console Server: gwt-console-server.war
  • Domain model: gwt-console-rpc.jar
  • Integration Layer: gwt-console-server-integration.jar

Also, don't forget to include the bpaf-explorer jars. To avoid this:
14:52:32,728 [main] ERROR [ContainerBase] StandardWrapper.Throwable
com.google.inject.ProvisionException: Guice provision errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: org/jboss/bpm/monitor/model/metric/Timespan
  at org.jboss.errai.bus.server.service.ErraiServiceImpl.(ErraiServiceImpl.java:50)
  while locating org.jboss.errai.bus.server.service.ErraiServiceImpl
  while locating org.jboss.errai.bus.server.service.ErraiService

1 error
 at com.google.inject.InjectorImpl$4.get(InjectorImpl.java:767)
 at com.google.inject.InjectorImpl.getInstance(InjectorImpl.java:793)
 at org.jboss.errai.bus.server.servlet.AbstractErraiServlet.buildService(AbstractErraiServlet.java:117)
 at org.jboss.errai.bus.server.servlet.AbstractErraiServlet.init(AbstractErraiServlet.java:88)
 at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)


Saturday, October 15, 2011

My first encounter with jBPM


Long story, short story. When I was working in one of my projects in Mexico, somebody mentioned something about BPM or BPEL and how practical de idea/concept was, because now we can mix the knowledge of the Business People with the Developers, by using some kind of cool diagrams to do Process Modeling.

And now I had to create a project which essentially it's a WorkFlow but we need some features like keeping the state of each execution (so we can trace it easily and resume the process if by any chance is stopped) "et all" and then, when I saw that One of the requirements was to integrate this miniworkflow with an existing App deployed on jBoss 4 with Seam 2.1 (I'd talk later about this framework, for all those like me who love Spring Framework), then I have to use jBPM 3 instead of 4 or 5 OUCH :'(
"But then, I realize that JBPM4 can work flawlessly on JBoss 4"
What do we need???
No much, Eclipse Helios (3.6)
Install these features:

  • JBoss Tools - http://download.jboss.org/jbosstools/updates/development/helios (don't forget to install jBPM support!)
  • Graphiti - http://download.eclipse.org/graphiti/updates/0.7.1
  • BPMN2 - http://codehoop.com/bpmn2


The concept is really simple, we just need to model the flow (I'll use the Designer to do this)


But it needs some logic inside its guts, so I'll add something called Handlers and some personalized tags (which is a really cool feture)
This is our model translated into XML
On my implementation, the process will run by itself, it's going to be a "FIRE AND FORGET";

On my case the process will wait for a certain amount of time and the it will start, it'll make one decision and it will execute something and then the End :)

The logic will be implemented by Implementing some Interfaces:



And Voila!!!

Soon I'll talk a little bit about jBoss SEAM! (How I implemented a REST Service FACILITO!)