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!

11 comments:

  1. Hello, thank you a lot to share all these tips, I know it is a lot of job.

    I am also under jboss 6 and would like not to update it right now.

    Using jbpm 3.2.8, I have followed all the instructions, recompilation of "enterprise" and "identity" libraries, HornetQ conf files etc...

    I configured my datasource which use MySql. You could also add method to fill jbpm database even it is provided in jdpm distributions..;)

    Few questions :

    - I do not find a way to change code for org.jbpm.identity.hibernate.IdentitySessionFactory, any special dependency needed to get getCache() method available.
    - Security for HornetQ : do not know where to place security options in conf file...

    Despite this, at the end, jbpm console seams to be working like a charm.

    - After I do not find a way do deploy gpd-deloyer, it say class not found with ProcessUploadServlet.class… do I need to compile it with my java version ?

    Sorry for all theses questions, but you help me a lot…it takes hours and hours to make this ;)

    Thanks,

    Jul

    ReplyDelete
  2. Did you also follow the instructions in the JBoss 5.1 article linked to at the top?

    I highly suggest you use JBPM 3.2.9 (download from the URL specified in the JBoss 5.1 article) as that is the one I use myself; with all the steps documented you should end up in the same situation as me.

    > After I do not find a way do deploy gpd-deloyer, it say class not found with ProcessUploadServlet.class… do I need to compile it with my java version ?

    You shouldn't need to compile anything. If you use a release of Java that is too low you'll get the 'unsupported class version' error. I suggest first trying JBPM 3.2.9 to see if that fixes it.

    ReplyDelete
  3. Thanks for you fast reply.

    I downloaded 3.2.9 version and not get previous ClassNotFound exception anymore.

    But one issue with configuration of datasource in web.xml of gpd-deployer jboss-web.xml.

    What do I need I do not understand ;)

    Extract from my hibernate.cfg.xml :

    ...

    java:comp/env/jdbc/JbpmDataSource
    ...

    Extract from my jbpm-mysql-ds.xml
    ...
    JbpmDS
    ...


    And then the 2 gpd conf files :

    jboss-web.xml

    ...

    jdbc/JbpmDataSource
    java:/JbpmDS

    ...

    web.xml

    ...

    Logical name of the data source that provides connections to
    the persistence service. Must match the hibernate.connection.datasource
    property in the Hibernate configuration file.
    jdbc/JbpmDataSource
    javax.sql.DataSource
    Container

    ...

    Is something wrong in this last 2 files, jim-console is working well, I would like use gpd servlet for deployment.

    Thanks

    ReplyDelete
  4. sorry, xml is not displayed well here

    ReplyDelete
  5. > java:comp/env/jdbc/JbpmDataSource

    Check the 'patching hibernate.cfg.xml' section of the JBoss 5.1 patch guide.

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

    ReplyDelete
  6. I remove <> so you can see xml...:

    I have the entry in hibernate conf file :

    !-- DataSource properties (begin) --
    property name="hibernate.connection.datasource" java:JbpmDS property
    !-- DataSource properties (end) --

    web.xml :

    resource-ref
    description
    Logical name of the data source that provides connections to
    the persistence service. Must match the hibernate.connection.datasource
    property in the Hibernate configuration file.
    description
    res-ref-name jdbc/JbpmDS res-ref-name
    res-type javax.sql.DataSource res-type
    res-auth Container res-auth
    resource-ref

    jboss-web.xml :

    jboss-web

    security-domain java:/jaas/jbpm-console security-domain

    resource-ref
    res-ref-name jdbc/JbpmDS res-ref-name
    jndi-name java:/JbpmDS jndi-name
    resource-ref

    jboss-web

    ReplyDelete
  7. Looks good to me (I never made any changes to web.xml and jboss-web.xml by the way). But I'm a bit lost now. Are you still having an actual problem here?

    BTW you can post XML in blogspot by replacing all < with &lt;. A bit annoying, but whatever.

    ReplyDelete
  8. If I can suggest it would be awesome if you could try to migrate jbpm 3 to jboss7.1 as it's quite stable now.

    I think it could be very helpful for many people.

    btw. Very good blog, thanks for sharing your knowledge with others!

    ReplyDelete
  9. Sorry, but I don't think I'm going to even attempt it; I don't have a need for it in my work environment. If you want to use a legacy technology like JBPM 3, you'll also have to use a legacy server. JBoss 6 (or 6.1) can hardly be called legacy though.

    ReplyDelete
  10. I have implemented your solutions and messages are queued by hornetq but it is not consuming by jbpm,what else shuld we do to consume the message.

    ReplyDelete
    Replies
    1. Sorry but this is just too old, I don't use the tech anymore so I can't really comment on anything anymore. I suggest you read the very extensive hornetq documentation in stead.

      Delete