Tuesday, June 7, 2011

JBPM 3.2.9 on JBoss 6

Introduction

And the third installment in my series of JBPM on JBoss X.X. This time I'll deal with getting JBPM, and more specifically the JBPM manager, to work on JBossAS 6.

First of all, everything I wrote in my JBPM 3.2.9 on JBoss 5.1 guide still applies, except for the JMS queue stuff which is again different on JBoss 6. So I suggest you read that article now and apply it. Then come back here and we'll finish the last steps to get it to work on JBossAS 6.

http://entjavastuff.blogspot.com/2010/11/jbpm-329-on-jboss-51.html

Patching jbpm-identity

The jbpm-identity library unfortunately has a conflict with Hibernate 3.6 that is part of JBossAS 6. We have to replace some deprecated code to get it to work again.

The source code for jbpm-identity can be found in the JBPM 3.2.9 runtime installation directory, in the file src/jbpm-identity-sources.jar. Create a project for it in your favorite IDE and apply the following source changes.

org.jbpm.identity.hibernate.PermissionUserType
From:

private static final Type[] PROPERTY_TYPES = new Type[] { Hibernate.STRING, Hibernate.STRING, Hibernate.STRING };

To:
private static final Type[] PROPERTY_TYPES = new Type[] { StandardBasicTypes.STRING, StandardBasicTypes.STRING,StandardBasicTypes.STRING };

(don't forget to fix imports).


org.jbpm.identity.hibernate.IdentitySessionFactory
From:

public void evictCachedIdentities() {
    sessionFactory.evict(User.class);
    sessionFactory.evict(Membership.class);
    sessionFactory.evict(Group.class);
}

To:

public void evictCachedIdentities() {
    sessionFactory.getCache().evictEntityRegion(User.class);
    sessionFactory.getCache().evictEntityRegion(Membership.class);
    sessionFactory.getCache().evictEntityRegion(Group.class);
}

(again, fix imports).

That is all. Build this into a jar and replace the deploy/jbpm/jbpm-service.sar/jbpm-identity.jar file with your newly built one.


JBPM and HornetQ

A new JBossAS, a new JMS engine. To get JBPM talking to HornetQ, create a file called *jbpm-hornetq-jms.xml* in the *deploy/jbpm* subdirectory (or wherever you deploy the JBPM manager). Add the following content to it:

<configuration xmlns="urn:hornetq"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">

  <queue name="JbpmJobQueue">
    <entry name="/queue/JbpmJobQueue"/>
  </queue>
  <queue name="JbpmCommandQueue">
    <entry name="/queue/JbpmCommandQueue"/>
  </queue>
</configuration>

Remove an old JBPM 5.1 jbpm-jbm-service.xml file if there is one. Those are all the changes you have to do. Starting the server at this point may net you some exceptions however.

Cannot authenticate user 'null'

If you at this point try to start your server, you will most likely get exceptions stating 'cannot authenticate user 'null'. I have also described this problem in my JBoss 4.2.3 to JBoss 5.1 and JBoss 6 migration guide. Let me put it in the context of JBPM.

It stems from the fact that jbpm-enterprise.jar tries to connect to the HornetQ queues without providing any user credentials. This should trigger HornetQ to use the default user, but this is not happening, probably because the HornetQ user authentication is rewired to use that of JBossAS itself. I'm not sure about that yet, more investigation needed.

The only 'solution' to this problem I have found so far is to disable JMS authentication completely. Do this by opening the file deploy/hornetq/hornetq-configuration.xml in a text editor and adding the following line:

<security-enabled>false</security-enabled>

I am on the fence for now if this is a proper solution or not; at the moment my opinion is that JMS security only really should take effect when you start to have external clients communicating with your system through JMS. For internal use only authentication is redundant and ultimately an unnecessary performance hit.

When I figure out a proper way of dealing with this while keeping security enabled I will add it here as an alternative as soon as possible.

Force JSF 1.2 on the jbpm-manager

By default JbossAS6 enables JSF 2.0 for the jbpm-manager. That may or may not work properly; my opinion is that the JBPM manager was developed for JSF 1.2 and should therefor run using JSF 1.2.

To ensure that this happens, open up deploy/jbpm/jsf-console.war/WEB-INF/web.xml and add the following content:

<context-param>
    <param-name>org.jboss.jbossfaces.JSF_CONFIG_NAME</param-name>
    <param-value>Mojarra-1.2</param-value>
</context-param>

That will trigger JBoss 6 to use Mojarra 1.2 for the jbpm-manager. It is not necessary for the gpd-deployer, since it doesn't use JSF.

JBPM manager and classpath isolation

This section will very soon contain a detailed explanation about how to get the JBPM manager (and more to the point: jbpm-enterprise) to function reliably in an environment where classpath isolation is switched on, which is by default the case in JBoss 6 and should remain that way. I am at the moment gathering all the example code and configuration files I need to properly explain it. It will be a nice trip into the wonderful world of JBoss classloader domains.

Coping with JBoss Tools 3.2

If you want to use JBoss 6 from Eclipse, you will probably have JBoss Tools 3.2 or higher installed. You will find that some things have changed since JBoss Tools 3.1 when it comes to JBPM 3 processes; for the worst in my opinion. Lets name a few key points.

Properties view does not update (Helios SR2, JBoss Tools 3.2)
When selecting nodes you'll find that the properties view does not update, making it so you cannot input properties for that node. This bug has been reported (by me to be precise) and fixed for the next release. Use the nightly build if you want to have the fix; a workaround is to use the outline view of Eclipse to make selections.

Change in file naming
When you create a new process definition, not only is the name of the file changed (in stead of processdefinition.xml it is processname.gpd.xml), it is also no longer stored in a subdirectory by default. This change has apparently been done so you can have multiple process definitions in the same folder. Who was asking for that I wonder?

To create new process instances using the old style, do the following.

- create a subdirectory in your project manually with the proper name
- use Eclipse to create a process definition there
- rename the file outside of Eclipse to processdefinition.xml
- refresh project view in Eclipse


Crippled class bundling
The JBoss Tools 3.1 deployment tab for deploying processes from Eclipse was in my opinion near perfection - it just worked. If something becomes perfect you have to break it, and this has been done by doing it completely different in JBoss Tools 3.2. Thanks a lot.

One of the biggest changes that made the deployment tab unusable for me is the fact that you now have to select handler classes *individually* that you want to deploy with your process; in the old version you could just select an entire package. I know in JBPM 5 you don't add Java code anymore, but it is silly to enforce such rules back onto JBPM 3 by making it unnecessarily difficult.

The only way I can deploy now is to build my project using Maven; as part of the build process we have some antrunner tasks that generate the par files, which I can then upload using the jsf-console. Here is an example:

<tasks name="create pars">
  <zip destfile="${project.build.directory}/PROCESSNAME-${project.version}.par">
    <fileset dir="${project.build.directory}" includes="**/HANDLER_PACKAGE/*" />
    <fileset dir="${basedir}/src/main/process/PROCESSNAME" includes="*.*" />
  </zip>
</tasks>

This will create a par file in the target directory of the module; it includes two things:

- all classes in a certain package; filter to only include the node handlers (so replace HANDLER_PACKAGE with the appropriate sub package name)
- the process definition files, which I store in the src/main/process directory of the module project (replace PROCESSNAME with the correct subdirectory name)

If you use the new style process definition creation (a single directory with a PROCESSNAME.gpd.xml file) then you would replace the second fileset with a single file inclusion; check out the ANT zip task for more information on how to configure such things.


In closing

Thats it! You should now be able to use the JBPM 3.2.9 manager on JBoss 6!