Introduction
Note: This article is now basically obsolete. I refer you to my jbpm 3.2.9 installation guide. I let this article be to preserve the knowledge inside it.
JBPM is a 'Business Process Management' API. This API allows you to define program logic as a process, providing a vastly different and more visible approach to implementing application flow.
This document will describe setting up JBPM 3.2.6 on JBoss 5.1. The question you may ask yourself is: WHY do I document this? There is already a JBPM 4 out there!
Indeed there is and the JBPM4 API is very slick indeed. It deploys like a charm on JBoss 5.1, the API is very clean and in less than 5 minutes I had a database oriented test case running that was stepping through a process.
But there are a few things that I don't like about JBPM 4.
- the tools are only half finished and quite buggy
- the original 'brain' of JBPM has left Redhat and is now working on a competing open source API under the name of 'Activiti'.
Activiti press release.
This API is still heavily in development though, and thus not very useful yet. I am keeping my eye on it however.
And apparently Redhat also already has JBPM5 in development; my guess is that JBPM4.x is given up for lost for now and the focus for the tool development will be on JBPM5. A message on the main jbpm website called 'JBPM is still alive and kicking' seems to back this up.
All is fine and well, but I want a working JBPM API that DOES have functional tools. So I stick with my good old JBPM 3.2.X, which has served me well over the last year (with some help from me). The trouble is that this API is quite old already and developed with JBossAS 4 in mind. It just doesn't work out of the box on JBoss 5.1.
This document will tell you how you CAN make it work.
A note about JBPM 3 minor versions
If you look online, you'll find that there is actually also a JBPM 3.3.1. This version is *not* newer than JBPM 3.2.6! At one point in time JBPM 3 was forked into two paths; the JBPM 3.2.X path and the JBPM 3.3.X path. The 3.3.X path is binary compatible with the JBPM 3.2.X path, but also has an additional tool called the GWT-console, which is a flashier management interface built on top of google web toolkit.I don't know why, but the 3.3.X path was not maintained as far as the 3.2.X path. I recommend sticking with 3.2.6 as it contains a few bugfixes that are very much worth it.
JBPM 3.2.6 under the hood
The engine
When I talk about "JBPM", I actually talk about three different components;
- JBPM API; the api you can program against in your applications to be able to invoke and manage processes.
- JBPM MANAGER; a management application package that you deploy into JBossAS; the manager application holds the deployed processes and has a management interface in which you can see deployed process definitions and the state of process instances. It also allows you to deploy new process definitions.
- JBPM TOOLS; part of the "JBoss Tools" Eclipse plugin set, the JBPM tools give you a neat visual process designer application, also with the ability to directly deploy processes to a JBPM manager instance (requiring a running JBoss instance of course).
par files
JBPM 3 defines a binary type called a 'par' file. This is in fact nothing more than a zip file with the process classes and the process definition file inside it. The JBPM process designer can create these files for you if you want; You can also use the following ANT task, modifying it to your own taste/environment.
<zip destfile="${project.build.directory}/PROCESS_NAME-${project.version}.par"> <fileset dir="${project.build.directory}" includes="**/PROCESS_NAME/handlers/*" /> <fileset dir="${process.src.root}/PROCESS_NAME" includes="*.*" /> </zip>
This contains the following properties, as used in a maven pom file:
project.version = maven project version (1.0.0 for example)
process.src.root = PROJECT_BASE_DIR/src/main/process
project.build.directory = PROJECT_BASE_DIR/target/classes
I tend to put the node handler classes for a process in a package with the same name as the process and in a subpackage 'handlers'; this means that for example if I create a process 'myprocess', the package would be myapp.myprocess.handlers. Adjust according to your own taste.
Maven compile dependencies
To be able to compile code that uses JBPM, you need no more than the following maven dependency.
<dependency> <groupId>org.jbpm.jbpm3</groupId> <artifactId>jbpm-jpdl</artifactId> <version>3.2.6.SP1</version> <exclusions> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> </exclusion> <exclusion> <groupId>org.apache.jackrabbit</groupId> <artifactId>jackrabbit-core</artifactId> </exclusion> <exclusion> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> </exclusion> <exclusion> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> </exclusion> <exclusion> <groupId>org.apache.ant</groupId> <artifactId>ant-launcher</artifactId> </exclusion> <exclusion> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> </exclusion> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> <exclusion> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> </exclusion> <exclusion> <groupId>bsh</groupId> <artifactId>bsh</artifactId> </exclusion> </exclusions> </dependency>
I add all the exclusions to prevent polluting the classpath; most of these dependencies are absolutely not needed to just use JBPM. The exception to the rule is Hibernate: JBPM uses Hibernate internally for persistence actions. I exclude it anyway because you may be using your own, newer version of Hibernate already.
Installing JBPM 3.2.6
This part is quite easy actually; JBPM comes with an installer. Just download JBPM from the JBoss sourceforge download page. This download gives you an executable jar, so double click to execute it.The installer will ask you a few questions; where to install the JBPM runtime (choose any directory you want), which database do you use, which version of JBoss are you using (doesn't really matter, but choose Jboss 5), path to the JBoss server instance, etc. Unfortunately the JBPM 3 installer does not come with support for Oracle yet, but I'll show you how to set that up in a moment. If your database is not listed, simply choose Hypersonic SQL for now.
If everything is correct, you'll have an installed JBPM runtime folder and your JBoss instance's deploy directory now contains a subdirectory 'jbpm'.
Setting up the JBPM manager to work with Oracle
Of course, install an oracle driver into the instance's lib directory. To make JBPM talk with oracle, do the following steps.
1. delete the deploy\jbpm\jbpm-hsql-db.xml file
2. create your own JBoss oracle datasource with name 'JbpmDS' (case sensitive!)
3. Open file deploy\jbpm\jbpm-service.sar\hibernate.cfg.xml. Change the hibernate dialect to 'org.hibernate.dialect.Oracle9Dialect'.
That is all on the configuration side. Now we need to get some tables into the schema you point to in the datasource. 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);
All done! But when you now try to run the server instance, things will unfortunately break down with many deployment errors. We are not done yet, we need to hack some code!
Fixing the JMS queues
JBoss 5.1 has a new JMS provider. To be able to make JBPM work, we need to modify the file deploy\jbpm\jbpm-destinations-service.xml; replace the queue declarations with the following:<mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.messaging.destination:service=Queue,name=JbpmJobQueue" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.messaging.destination:service=Queue,name=JbpmCommandQueue" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean>
And that is all.
Fixing jbpm-enterprise.jar
The main problem we need to fix here is the way that the JNDI lookups are done - it tries to use the java:comp/env space, which is off-limits unfortunately. We need to patch some source files to use the real local JNDI names to get things working. Luckily we know these JNDI names; they are defined in the jboss.xml descriptor file.
First of all, locate the 'src' folder of your JBPM runtime installation folder. It holds a file 'jbpm-enterprise-sources.jar'. This is the source code you need, so unpack that so that you can modify and build the code into a jar - I created a simple maven Eclipse project for it.
you need to make modifications to the following files.
org/jbpm/msg/jms/JmsMessageServiceFactory.java
Change this:
String connectionFactoryJndiName = "java:comp/env/jms/JbpmConnectionFactory"; String destinationJndiName = "java:comp/env/jms/JobQueue"; String commandDestinationJndiName = "java:comp/env/jms/CommandQueue";
to this:
String connectionFactoryJndiName = "java:JmsXA"; String destinationJndiName = "queue/JbpmJobQueue"; String commandDestinationJndiName = "queue/JbpmCommandQueue";
org/jbpm/scheduler/ejbtimer/EntitySchedulerServiceFactory.java
Change this:
String timerEntityHomeJndiName = "java:comp/env/jbpm/TimerEntityBean";
to this:
String timerEntityHomeJndiName = "java:jbpm/TimerEntityBean";
org/jbpm/scheduler/ejbtimer/TimerServiceBean.java
In the ejbTimeout() method, change this:
String localCommandServiceJndiName = "java:comp/env/ejb/LocalCommandServiceBean";
To this:
String localCommandServiceJndiName = "java:jbpm/LocalCommandServiceBean";
org/jbpm/scheduler/ejbtimer/EjbSchedulerServiceFactory.java
Change this:
String timerServiceHomeJndiName = "java:comp/env/ejb/LocalTimerServiceBean";
To this:
String timerServiceHomeJndiName = "java:jbpm/LocalTimerServiceBean";
org/jbpm/ejb/impl/TimerEntityBean.java
In the ejbActivate() method change this:
LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) initial.lookup("java:comp/env/ejb/LocalCommandServiceBean");
To this:
LocalCommandServiceHome commandServiceHome = (LocalCommandServiceHome) initial.lookup("java:jbpm/CommandServiceBean");
Build the new jbpm-enterprise.jar. Remove the exploded jbpm-enterprise.jar directory from the deploy\jbpm directory in JBoss and put your own jbpm-enterprise.jar file in there to replace it (be sure to rename your own jar to jbpm-enterprise.jar if the name is different).
Now try to start the JBoss server instance; if you followed all my instructions to the letter, you should now be able to boot up your server instance without exceptions and be able to see http://localhost:8080/jbpm-console/ working!
One more thing to be done is to configure security in JBoss.
Configuring the user credentials
Open up JBOSS_HOME/server/instance/conf/login-config.xml. Add the following content somewhere at the end:
<application-policy name = "jbpm"> <authentication> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="dsJndiName">java:/JbpmDS</module-option> <module-option name="principalsQuery"> SELECT PASSWORD_ FROM JBPM_ID_USER WHERE NAME_=? </module-option> <module-option name="rolesQuery"> SELECT g.NAME_ ,'Roles' FROM JBPM_ID_USER u, JBPM_ID_MEMBERSHIP m, JBPM_ID_GROUP g WHERE g.TYPE_='security-role' AND m.GROUP_ = g.ID_ AND m.USER_ = u.ID_ AND u.NAME_=? </module-option> </login-module> </authentication> </application-policy>
Be sure to check the datasource JNDI name against your own environment - JbpmDS should connect to a schema/database with the JBPM tables in it. The above is for an Oracle environment, but is should work on other DBMS systems also.
Now you should be able to login in the JBPM manager webapp.
Installing JBoss-Tools into 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 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 http://download.jboss.org/jbosstools/updates/stable/galileo/. 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 = /jbpm-console/upload
Okay done! 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! To continue with your JBPM adventures, I can now safely leave you in the hands of the JBoss documentation. Perhaps I will create another article about process development and deployment and I'll certainly write one on unit testing them.
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.6.SP1)
- 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.
Hello,
ReplyDeleteI try to apply this articel.but i getting error when using processes that contain timers.
here is the error :
ERROR [GraphElement] action threw exception: $Proxy268 cannot be cast to org.jbpm.ejb.LocalTimerEntityHome
java.lang.ClassCastException: $Proxy268 cannot be cast to org.jbpm.ejb.LocalTimerEntityHome
at org.jbpm.scheduler.ejbtimer.EntitySchedulerServiceFactory.getTimerEntityHome(EntitySchedulerServiceFactory.java:46)
at org.jbpm.scheduler.ejbtimer.EntitySchedulerServiceFactory.openService(EntitySchedulerServiceFactory.java:65)
Any suggestion?
and here is the processdefinition.xml :
okay, thanks for reporting. I created a test setup myself and could reproduce this easily; turns out the patches that need to be done to enterprise.jar were not complete at all. I'm going to update the article right now.
ReplyDeleteOkay updated (and I took the chance to include syntax highlighting). I changed the existing patches also, so I would reapply them all if I were you.
ReplyDeletethanks gimby ...
ReplyDeletei already apply your suggestion.
the problem is solved.
good to know. And especially good to know I am not the only one playing around with this old technology ;)
ReplyDeletehai gimby...
ReplyDeletei will try jbpm-3.2.7 on JBoss-5.1 today.
do you have suggestion?
because i jbpm-3.2.6 still have a few problem such as jBPM console crashes when to many processes in process list
Weird that 3.2.7 has an official release now while 3.2.9 is the latest version. I would go for JBPM 3.2.9 directly. What you need is this jar:
ReplyDeletehttp://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/jbpm3/jbpm-distribution/3.2.9/
That should allow you to install the full JBPM 3.2.9 package, including manager. I believe some of the JNDI names are different in this version, so be sure to verify that in the jboss.xml file of the manager application.
Hi, I'm trying to get JBPM 3.2.2 running on JBoss 6. Do you know if there in relation to JBPM 3.x is a lot of difference between JBoss 5 and 6 - would I be able to use your guide as a basis for getting it to run. Would it be smarter to upgrade to 3.2.9?
ReplyDeleteSince JBoss6 builds on top of JBoss 5.1, it *should* "just work" if you incorporate my patches. But I cannot know for sure since I've not tested it myself yet.
ReplyDeleteJBPM 3.2.2 up to and including 3.2.6 contain many critical bugs that will create serious production issues; I know because I've had them myself. I would seriously consider going for 3.2.9 directly, or at least 3.2.7 that now has an official download package.
I'll try to upgrade the article this weekend to include the setup steps needed to install JBPM 3.2.9.
I just remembered: JBossAS6 comes with a new JMS engine (HornetQ). Probably you'll need to modify the JMS queue configuration file, but I'm not 100% sure about that either.
ReplyDeleteOk thanks a lot for the responses, I'll go ahead and try to migrate to 3.2.9.
ReplyDeleteHi again, still running 3.2.2. When trying to deploy processes i get this exeption:
ReplyDelete14:06:23,314 ERROR [org.jbpm.db.GraphSession] (http-127.0.0.1-8888-2) java.lang.ClassCastException: org.jbpm.graph.def.Node_$$_javassist_110 cannot be cast to javassist.util.proxy.ProxyObject
Any tips on this, could this be related to duplicate classes and if so how do you enable classpath isolation?
You turn on classpath isolation in the file deployers\ear-deployer-jboss-beans.xml; at the bottom of the file you will find a property "isolated", which will most likely have the value "false".
ReplyDeleteI'm not sure that classpath isolation will fix the issue, although it is preferable to configure the instance with isolation turned on as it can prevent many library conflicts when deploying several applications in the same instance (such as the JBPM manager and your own app).
If it doesn't fix it I'm going to safely assume it is a bug in that version of JBPM.
for those making the upgrade to jbpm 3.2.9 (a quick note because I didn't have the time yet to upgrade the article): one change I've noticed is that the deployer servlet is no longer part of the JBPM manager application. This means that out of the box you cannot deploy from the Eclipse / JBossTools plugin.
ReplyDeleteIt has been moved to a separate war that you need to install yourself in your dev environment. This has been done from a security perspective, you don't want this servlet in production environments.
Get it here:
http://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/jbpm3/gpd-deployer/3.2.9/
Of course, deploying a par through the manager works fine without this, you only need this when you want to deploy from Eclipse.
Glad to see this thread.
ReplyDeleteI have installed jBPM-3.2.7 using installer with Oracle and jBoss-5.1. jBoss started with no issues and http://localhost:8080/jbpm-console/ shows the login page. When I try to log-in using user, manager or any other users
from schema I am getting the following error. Do you have any suggestions?
13:18:58,672 ERROR [UsersRolesLoginModule] Failed to load users/passwords/role files
java.io.IOException: No properties file: users.properties or defaults: defaultUsers.properties found
at org.jboss.security.auth.spi.Util.loadProperties(Util.java:198)
.....
.....
Thanks.
please check jboss-web.xml in jsf-console.war.
ReplyDeleteand change security-domain to:
java:/jaas/jbpm-console
Part of the installation of JBPM is to create a JAAS security realm for it (I do believe the installer in the package should do this step...). It should at the least put some additional files in JBOSS_HOME\server\instance\conf\props.
ReplyDeleteIf it doesn't, you could try to do a JBPM 3.2.6 installation and see if it creates the security files; if it does, copy those over to your JBPM 3.2.7 environment.
When I do get around to updating this article, I will be sure to add that section.
Grr, now I'm mixing technologies. What I describes is true for Drools Guvnor...
ReplyDeleteI'll append a bit to the article now.
Priasa, your solution worked. Thanks.
ReplyDeleteI didn't need to modify the jsf-console.war to get it to work, not in 3.2.6 and not in 3.2.9... I wonder if this is something JBPM 3.2.7 specific.
ReplyDeletejboss-web.xml file had java:/jaas/soa and changing to java:/jaas/jbpm-console worked.
ReplyDeleteNow I have moved to eclipse and developed/junit tested the Hello example. Unable to deploy it to server and when I use Test Connection... button it is throwing an exception dialogue box saying An exception happened while testing the server connection... It seems it is unable to invoke An unexpected exception caused the test connection operation to fail
http://localhost:8080/jbpm-console/upload.
I am using eclipse-3.6 (Helios).
Any suggestions?
Thanks
perhaps you need to install the gpd deployer, like I suggested in an earlier comment?
ReplyDeleteYou can easily check if the servlet is available by simply navigating to it in a browser; if it exists it will give a simple proof of life message in your browser.
Also, I know that as of a certain version, you are forced to input a username/password (manager/manager) when deploying.
Found the servlet under classes folder but its url pattern in web.xml was /app/upload/*. Changing it to /upload/* make it work.
ReplyDeleteI should have known that; the JBPM 3.3.X branch has the same change in url. One thing is for certain: the devs at the time were good at making a mess out of things. Jeesh!
ReplyDeleteFunny how you changed the war in stead of changing the settings in Eclipse :p
Thank u so much for this post.
ReplyDeleteI tried deploying jbpm-3.2.7 on JBoss 5.1 and made the changes you said.
I'm able to login to jbpm-console but every page shows me an error.
Process page tells me "Error loading process list: An exception of type "org.jbpm.persistence.JbpmPersistenceException" was thrown. The message is: could not find all process definitions "
Identities page tells me "Error loading user list: An exception of type "org.hibernate.exception.GenericJDBCException" was thrown. The message is: Cannot open connection"
Can you help me figuring out what's left to configure?
Check the server logs; there you should find the stacktraces that come with these errors. Perhaps when you find the sourcefiles that are blowing up, you can have a hint what is wrong.
ReplyDeleteIt seems to be database oriented though; did you include a datasource called JbpmDS? Did you create the JBPM tables using the scripts specific to JBPM 3.2.7? What database are you using, and did you change the dialect in the hibernate.cfg.xml file to match it?
It's working now.
ReplyDeleteThe datasource property had a wrong value in the hibernate.cfg.xml and the mysql-ds created by the jbpm installer was using xa-datasource.
http://community.jboss.org/thread/155512?tstart=-1
I just modified the mysql-ds as per what is said in the link above and it's working now.
Thanks!!
Thanks a lot for this post, You doing a great job!
ReplyDeleteThanks, but also see my article on getting JBPM 3.2.9 working on JBoss 5.1. It has plenty of bugs squashed and is far more stable, so I really recommend going for that version. I've had zero problems with it so far.
ReplyDeletehttp://entjavastuff.blogspot.com/2010/11/jbpm-329-on-jboss-51.html