Monday, November 22, 2010

JBPM 3.2.9 on JBoss 5.1

introduction


Yet another article about JBPM on JBoss 5.1. The last time around I based the article on JBPM 3.2.6. Unfortunately I discovered after writing that article that this version still contains some blocking issues.

The latest and most stable installment in the JBPM 3 branch is version 3.2.9; unfortunately installing it is not the exact same process as older versions. I wanted to preserve the knowledge in the old article, hence I created this new one.

When installing JBPM 3, I highly recommend you to go for JBPM 3.2.9.

You may want to read through the old article (and its comments) before continuing with this one; it contains some additional information I am too lazy to include in this article :)

Note:
Even though I target JBoss 5.1, you can use the exact same steps to get JBPM to run on JBoss 4.2.3. The only difference is in the choices you make yourself during the installer phase (choose JBoss 4.2.3 in stead of JBoss 5.1 as the target server).


Downloading and installing

For some reason or another, JBPM 3.2.9 has no official package on the JBoss website. Most likely this is a support issue; Redhat still makes money on licensed support for JBoss products. Anyway, it isn't all that hard, it just requires a few steps to get things running.

First of all, you need to download the distribution. Since there is no official download package, we'll have to pull it from the Maven repository. You can find the distribution package here:

https://repository.jboss.org/nexus/content/groups/public/org/jbpm/jbpm3/jbpm-distribution/3.2.9/.

Download the file 'jbpm-distribution-3.2.9-installer.jar', which is an executable jar that will run the installer.

The installer will ask you three basic questions;

- where do you want to install the JBPM runtime; this can be any directory you want. The runtime contains all the libraries, documentation, configuration and sources.

- which components do you want to install (leave at default; only install JBPM runtime, not Eclipse or JBossAS).

- In which JBoss server and instance do you want to install the JBPM manager.

a difference in previous releases of JBPM is that the JBPM 3.2.9 installer also knows about JBoss 5.1 and Oracle, which is a very nice thing. When you choose JBoss 5.1 it will generate for example the correct JMS queue configuration file. When you choose Oracle it will generate a datasource and Hibernate cfg settings.

The configuration of the JBoss instance is in two parts; first you choose the version and the instance name ('default' for example), second you choose where the server is installed. Point to the root directory of your JBoss installation.

To verify the installation, you should end up with two things:

- the jbpm runtime directory
- in the JBoss instance you chose, there should now be a subdirectory 'jbpm' in the instance's deploy directory.


patching hibernate.cfg.xml

Unfortunately the generated hibernate.cfg.xml contains a flaw, lets fix that right away. Open it up (find it in the jbpm/jbpm-service.sar/hibernate.cfg.xml) and make the following change.

Change this:

java:comp/env/jdbc/JbpmDataSource

To this:

java:JbpmDS


Even more unfortunately is that even with this change in place, JBPM won't work at this point. Lets dive a little deeper.

Patching the enterprise.jar


Even with all the improvements in place, the code still doesn't work out of the box on JBoss 5.1 (or even JBoss 4.2.x). There are some JNDI lookups done in the enterprise.jar module that simply won't fly. So we have no choice but to patch the code ourselves.

The source itself can be found in the JBPM runtime installation directory (src/jbpm-enterprise-sources.jar). Create a project in your favorite IDE so you can build this code as a jar; you'll need the jbpm-jpdl 3.2.9 dependency at least (its in the lib directory of your JBPM runtime). Since the enterprise.jar builds against JEE technologies such as JMS, you'll also need to add the J2EE 1.5 dependency to your project. Most IDEs allow you to create a JEE based project that will do this automatically for you. Or you can do like me and use Maven.

Anyway, once you get the code to compile, you'll need to make the following changes to it. I'll list the line of code to change, and what to change it to.


ejb.impl.CommandListenerBean

From:

jmsConnectionFactory = (ConnectionFactory) jndiContext.lookup("java:comp/env/jms/JbpmConnectionFactory");

To:

jmsConnectionFactory = (ConnectionFactory) jndiContext.lookup("java:JmsXA");

From:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) jndiContext.lookup("java:comp/env/ejb/LocalCommandServiceBean");

To:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) jndiContext.lookup("java:ejb/CommandServiceBean");

From:

deadLetterQueue = (Destination) jndiContext.lookup("java:comp/env/jms/DeadLetterQueue");

To:

deadLetterQueue = (Destination) jndiContext.lookup("queue/DQL");


ejb.impl.TimerEntityBean

From:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) JndiUtil.lookup("java:comp/env/ejb/LocalCommandServiceBean", LocalCommandServiceHome.class);


To:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) JndiUtil.lookup("java:ejb/CommandServiceBean", LocalCommandServiceHome.class);

msg.jms.JmsMessageServiceFactory

From:

String connectionFactoryJndiName = "java:comp/env/jms/JbpmConnectionFactory";

To:

String connectionFactoryJndiName = "java:JmsXA";

From:

String destinationJndiName = "java:comp/env/jms/JobQueue";

To:

String destinationJndiName = "queue/JbpmJobQueue";

scheduler.ejbtimer.EjbSchedulerServiceFactory

From:

String timerServiceHomeJndiName = "java:comp/env/ejb/LocalTimerServiceBean";

To:

String timerServiceHomeJndiName = "java:jbpm/LocalTimerServiceBean";


scheduler.ejbtimer.TimerServiceBean

From:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) JndiUtil.lookup("java:comp/env/ejb/LocalCommandServiceBean", LocalCommandServiceHome.class);

To:

LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) JndiUtil.lookup("java:ejb/CommandServiceBean", LocalCommandServiceHome.class);

scheduler.ejbtimer.EntitySchedulerServiceFactory

From:

String timerEntityHomeJndiName = "java:comp/env/ejb/TimerEntityBean";

To:

String timerEntityHomeJndiName = "java:jbpm/TimerEntityBean";

As you can see, these are only changes to JNDI lookups. I discovered the correct names by checking the jboss.xml file and the jndiView through the jmx-console application.


Build the jbpm-enterprise.jar file (if you get a different filename, rename it). Remove the exploded enterprise.jar directory from the jbpm directory that was added to your JBoss instance, and replace it with the jar you just built.


Setting up the JBPM manager to work with Oracle


Note:
If you use a different DBMS the steps will be exactly the same, only you'll need to use/modify differently named files.


Of course, install an oracle driver into the instance's lib directory. The installer has already generated a datasource file, but you'll still need to modify it to point to the schema of your choice. You'll find the file in the jbpm subdirectory of the JBoss instance you configured during the installation process, under the name jbpm-oracle-ds.xml.

A note about the datasource:
The datasource defines an MBean jboss.jca:service=OracleXAExceptionFormatter; when you use Oracle you may already have this MBean declared in your own datasource file. If you do, remove it from the JBPM generated datasource, or you'll get a duplicate MBean error during startup.


To be able to work with JBPM, you need to create a set of tables in the oracle schema you configure. Luckily the runtime installation comes with the script you need; simply invoke the file RUNTIME_INSTALL_DIR/database/jbpm.jpdl.oracle.sql.

Finally to be able to work with the manager we need some users and roles. You can execute the following statements to get a few defaults:

INSERT INTO JBPM_ID_GROUP VALUES(1,'G','user','security-role',NULL);
INSERT INTO JBPM_ID_GROUP VALUES(2,'G','manager','security-role',NULL);
INSERT INTO JBPM_ID_GROUP VALUES(3,'G','admin','security-role',NULL);

INSERT INTO JBPM_ID_USER VALUES(1,'U','manager','','manager');
INSERT INTO JBPM_ID_USER VALUES(2,'U','user','','user');
INSERT INTO JBPM_ID_USER VALUES(3,'U','shipper','','shipper');
INSERT INTO JBPM_ID_USER VALUES(4,'U','admin','','admin'); 

INSERT INTO JBPM_ID_MEMBERSHIP VALUES(1,'M',NULL,NULL,1,1);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(2,'M',NULL,NULL,1,2);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(3,'M',NULL,NULL,1,3);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(4,'M',NULL,NULL,2,1);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(5,'M',NULL,NULL,3,1);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(6,'M',NULL,NULL,4,1);
INSERT INTO JBPM_ID_MEMBERSHIP VALUES(7,'M',NULL,NULL,4,3);


At this point you should be able to succesfully deploy the JBPM manager without any errors, open up the jbpm-console webapplication and login as manager/manager!


Deploying from Eclipse


Now that JBossAS is all setup, we need to do some work in Eclipse to be able to add a JBPM process to a project. Note that I am assuming you are using Eclipse 3.5.2 or higher. Also you need the JEE version of Eclipse.

The thing we need is our good friend, JBoss Tools. This wonderful set of Eclipse plugins can give you great joy, if you take the time to learn how to work with it. Jboss Tools contains far more tools beyond JBPM; in this document I'll limit it to the JBPM tools.

In order to install JBoss tools you just need to point the Eclipse software installer to the download site. Find the correct download site for your version of Eclipse on this page:

http://www.jboss.org/tools/download

Note that at the time of writing, there was no stable release yet for Eclipse Helios, so if that is still true when you read this, simply use the latest development milestone. I can assure you that the JBPM 3 part of the plugin is stable.

This will present you with quite an impressive list of available plugins; I suggest you install at least these ones:

  • JBossAS tools
  • JPBM3 tools SDK
  • Jboss BPEL editor SDK

This will give you tools for deploying to a JBoss server and the JBPM 3 visual process editor.

After installation (and restarting Eclipse) we still have one setup step to go. We should configure our JBPM runtime. Click:

window -> preferences -> JBoss JBPM -> runtime locations

Click Add and add the runtime by selecting the directory where you installed it. Also give it a descriptive name. After adding it make it the default runtime by checking the checkbox in front of the name and click the apply button.

To be sure, select jBPM 3 -> server deployment. Make sure that the following information is filled in here;

server name = localhost
server port = 8080
server deployer = /gpd-deployer/upload

Check use credentials, and for the username/password input manager/manager.


That's it for the configuration part. But we still need to install one last piece of software.

Installing the GPD-deployer

Starting from JBPM 3.2.8, the deployer servlet is no longer part of the jbpm-manager itself. This is done for security reasons; you don't want this servlet in a production environment (in stead you deploy processes through the jbpm-console web application).

If we want to deploy processes from Eclipse, we need to install the gpd-deployer web application.

Download it here: http://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/jbpm3/gpd-deployer/3.2.9/.

Get the file gpd-deployer-3.2.9.war and put this war in the jbpm subdirectory of your JBoss instance. Start the server and verify that everything still deploys fine.


You can now try it out if it all works; in any project click:

new -> other -> JBoss jBPM -> jBPM 3 Process Definition

Give your process definition a name and if all is correct, you'll be presented with the JBPM visual process editor! When deploying your created process, be sure to check the deployment configuration again (you can use the test connection button to verify everything is setup correctly).


JBPM and classpath isolation

Sometimes you have to work in an environment where classpath isolation is turned off. You'll find that when you have a JSF based application running next to the jbpm-manager in such situations, you get a strange 'jbpm configuration is null' error when you try to see a page. Opening the jbpm-console application will magically fix that issue.

If you are in this situation you have one of two options.

- turn on classpath isolation (really, you should do that!)
- patch your web module so that it can play nice with the jbpm-manager application.

To do this you need to add two dependencies to your war module:

- jsf-console-jbpm4jsf (maven groupId = org.jbpm.jbpm3, artifactId = jsf-console-jbpm4jsf, version = version 3.2.9)
- JBoss gravel (maven groupId = org.jboss.gravel, artifactId = gravel, version = 1.0.0.GA)

Then to magically fix the problem, add a file 'jbpm4jsf-config.xml' to the WEB-INF of your war, with the following default content:

<?xml version="1.0" encoding="UTF-8"?>
<jbpm4jsf-config xmlns="http://jbpm.org/jbpm4jsf/config">

    
    <authentication-service>
        <use-jsf-actor>true</use-jsf-actor>
    </authentication-service>

    <!-- This entry facilitates the usage of process image URLs -->
    <process-file-matcher>
        <pattern>^/app/pi/(\d+).jpg$</pattern>
        <file-name>processimage.jpg</file-name>
        <content-type>image/jpg</content-type>
    </process-file-matcher>

</jbpm4jsf-config>

Now boot JbossAS and open a webpage of your application: problem solved.


In closing

At some point in time I'll write a beginners guide to JBPM development. But perhaps it will be on JBPM 5 in stead, which is looking quite cool indeed. I hope this article will give you some benefit; I already know I'm not the only one out there that has to use this old technology!

4 comments:

  1. thank you for your great effort, it helped me a lot.

    note: I tried the 5.1.0 wizard and it works.

    ReplyDelete
  2. Hi,
    It's not imposilbe now to download jbpm-distribution-3.2.9-installer.jar, strange that other (jbpm 3.3.1) have not so good instalator like 3.2.8 and 3.2.9. Could you provide this file on you blog?

    ReplyDelete
  3. Ok, I found place where we can download 3.2.9 and also 3.2.10

    http://maven.antelink.com/content/repositories/public-jboss/org/jbpm/jbpm3/jbpm-distribution/

    ReplyDelete
  4. Sorry for the late reply, I was on vacation when you posted and just noticed it. I updated the link in the article.

    For now I don't really see a reason to upgrade to 3.2.10, I've been using 3.2.9 for over a year now in multiple projects and I've yet to find a single problem with it.

    ReplyDelete