Joe Developer

Thursday Sep 07, 2006

jBPM 3.1 Domain Object auto persistence

I just went through an upgrade from jBPM 3.0 to 3.1.2. There are a number of changes, some large, some small. One of the welcome changes is more exposure of the underlying persistence mechanism - Hibernate.

jBPM allows you to store variables in a process instance - and if you write a converter to translate from a primative (or wrapper) to your type, you can easily persist user defined types in your process.

In an action handler it looks like:

  executionContext.setVariable("foo", myInstanceOfFoo);
Where you've written and reistered a converter for whatever class myInstanceOfFoo is. The converter registration was SO 3.0, particularly if your type, we'll call it com.example.Foo is persisted by Hibernate. You ended writing boilerplate code.

In 3.1.x the engine is smart enough to use the hibernate configuration that it's already using to see if your type is persistable by hibernate, and if so, will use its internal session factory to save and retrieve your variable when you reference it in the process.
That's neat. There's a problem though... what if your domain object implements Serializable? As it turns out, this will cause you all sorts of issues when you'd like transparent persistence if you're relying on the default configuration for variable handling.

This is due to the way jBPM looks for a way to handle persisting a variable.
jBPM first figures out how to save a variable by looking in the config file: org/jbpm/context/exe/jbpm.varmapping.xml.

As the engine is doing its magic, it is checking against each type of built in persistence strategy to figure out which one to use for your variable. When it finds one that matches, that's what it uses for saving and fetching your object. For fun, look in the DB and you'll notice there's a column in the variable_instance table that tells you what strategy it uses.
When your object is serializable, the engine by default will use the org.jbpm.context.exe.converter.SerializableToByteArrayConverter to persist it. That's not actually what I'm looking for, and I'm not sure when that WOULD be the desired behavior, but since the engine is looking at persistence strategies in order and that's found before the hibernate persisters, that's what's used...

The "desired behavior", at least in my case, was to have Hibernate persist things, and have jBPM just go to MY DB tables to rehydrate objects as needed, not pull them from some serialized blob in the DB that is frequently out of date with the domain. I want to be able to have the "variables" that jBPM is using be accurate reflections of the state of the data when the process access it.

The fix? Take the 3 hibernate based variable instance converters and move them to the top of the config file, rather than the bottom. (ok, so one of them is EJB3 based, but the same issue applies if you're in that space). jBPM will then attempt to use Hibernate persistence for your object BEFORE it attempts to serialize it.
Rebuild jBPM (or point to your modified var mapping file from a user supplied jbpm.config file), and off you go.

After that, I have to say that the variable handling is perfect - exactly what I was looking for. It is intuitive and allows a deep integration between the objects in the domain and the workflow engine.

Assuming your object is "hibernatable", say an instance of Foo, then in a handler you can "save" a foo in the process instance like so:
  executionContext.setVariable("myFoo", instanceOfFoo);
Fetching the fully hydrated object that is fresh from your domain in a later node/script/handler is then as easy as:
  Foo myFoo = (Foo)executionContext.getVariable("myFoo");
  ... some interesting stuff.
This makes it easy to use your persistent domain objects, from your tables, in a transparent manner within a process - a powerful feature.

Just be warned - without a custom config OR a modification of their config, you'll have no end of wondering what's going on if you happen to have domain objects that are Serializable.

An additional note - see the first comment from Tom Baeyens (the creator of jBPM) - this issue is fixed in CVS - so if you're running head you'll not have this, and I look forward to un-doing my change upon the next release.

Comments:

it's fixed. the order of detection is reversed in CVS: http://jira.jboss.com/jira/browse/JBPM-748

thanks for the feedback !

regards, tom.

Posted by Tom Baeyens on September 08, 2006 at 03:10 AM CDT #

Post a Comment:
Comments are closed for this entry.

Calendar

Feeds

Search

Links

Navigation

Referrers