Home JBpm JBPM web application example
12 | 03 | 2010
JBoss 5 AS Book
"JBoss AS 5 development" reviews
Please share your feedback/review with other readers!
Banner
Dashboard
Advertise with Us
Banner
RSS Feed
Login
Sign here for the NewsLetter.



Poll
What book could be in your wish list next XMas ?
 
JBoss admin resources
Banner
JBPM Books
JBoss howto

How can you solve deployment errors caused by large war/jar/ear files ?

jboss recipe of the day ...
Read More

How do you configure your .war to be deployed after your EJB ?

jboss recipe of the day ...
Read More

How do I configure a Queue/Topic to work in a cluster?

JBoss recipe of the day ...
Read More
JBPM web application example
Written by F.Marchioni   

An article about JBPM in a web application has been often requested in the forums and in this site too. Let's see how JBoss process engine fits in a web application.

Probably the thing which is most misunderstood by people approaching JBPM is -what is JBPM - ? a tool / framework / a server application ? when I approached a JBPM course in London 2 years ago our coach made this clear in the first 5 minutes of the course. JBPM is just a Java library wrapping -with Hibernate- a DB schema.

Of course in these classes there is the logic to interact with the DB schema (which contains all process data); however just being a set of Java classes you can deploy them  in every environment: EJB, web application. Even in another application server, which supports Hibernate.
 

Configuring JBPM in a web application

This said, let's see how to use JBPM in a web application. The only requirement is to make visible to the Web application the required files:
jbpm web application
As you can see at first you need to publish the hibernate configuration file: hibernate.cfg.xml. In the config folder of JBPM installation you can find hibernate configuration samples for every DB.

Then you need to add also the process definition file if you plan to deploy/redeploy your process from the web application.

Optionally you can add also jbpm.cfg.xml which contains additional configuration for JBPM (for example if you need to send mail from JBPM you should use this file to configure the mail server)

The second piece of information is the JBPM libraries which will be added in the "lib" folder of your application.
 

Dealing with the JBPM Context 

A JbpmContext separates jBPM from a sprecific environment. For each service that jBPM uses, there is an interface specified in the jBPM codebase.

A JbpmContext can also demarcate a transaction. When a PersistenceService is fetched from the JbpmContext, the default implementation for the persistence service will create a hibernate session and start a transaction. So that transactions can be configured in the hibernate configuration.

Last but not least, JbpmContext provides convenient access to the most common operations such as getTaskList(String), newProcessInstance(String) loadTaskInstanceForUpdate(long) and save(ProcessInstance). 

If you want to access the JBPM Context you must however follow the following paradigma:

jbpm web application
That is, you create the JBPM Context at every request, perform the necessary operation with JBPM, then close the JBPM Context when you have finished.
 

jbpm web applicationDon't worry: opening and closing the JBPM Context hasn't got any performance issue. What could a be an overkill is re-creating the JBPMConfiguration. Since this Object is Thread safe, you can create it once and store in a static field.





A sample JBPM web application

So here's a very simple web application made up of a Servlet Controller and a DAO component which interacts with JBPM. In this application the user is allowed to deploy a process, start new instances and see the process list.
 

package com.sample;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sample.dao.JBPMDao;

public class JBPMServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static String processName;

	 public void init() throws ServletException {
	       
	        // Get the value of an initialization parameter
	        processName = getServletConfig().getInitParameter("processName");    	        
	 }

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = new PrintWriter(response.getOutputStream());

		JBPMDao dao = new JBPMDao();
		String html = null;
		String action = request.getParameter("action");
		
		if (action.equals("deploy")) {
			html = dao.redeployProcess("processdefinition.xml");
		} else if (action.equals("start")) {
			html = dao.startNewProcessInstance(processName);
		} else if (action.equals("list")) {
			html = dao.readProcessInstances(processName);
		} else if (action.equals("signal")) {
			html = dao.signalProcess(processName, request.getParameter("id"));
		}

		out.println(html);
		out.println("<br />");
		out.println("<a href='index.jsp'>Back</a>");
		out.close();
	}

}

The process definition file can be any process definition file you like, just insert into web.xml the processName parameter so it's available to the Servlet.


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <display-name>JBPMWeb</display-name>
 <servlet>
  <servlet-name>JBPMServlet</servlet-name>
  <servlet-class>com.sample.JBPMServlet</servlet-class>
     <init-param>
        <param-name>processName</param-name>
        <param-value>simple</param-value>
     </init-param>
 </servlet>
 <servlet-mapping>
  <servlet-name>JBPMServlet</servlet-name>
  <url-pattern>/jbpmServlet</url-pattern>
 </servlet-mapping>

</web-app>

JBPMDao contains a set of methods to interact with JBPM and a Decorator Class to output the list of processes. ( This web application is much 90's programming style :-) however should give the idea how to work with JBPM in a web context)


package com.sample.dao;

import java.util.List;

import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;

import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.GraphSession;

public class JBPMDao {
	private static JbpmConfiguration jbpmConfiguration = JbpmConfiguration
			.getInstance();

	public String redeployProcess(String processName) {
		JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
		try {
			ProcessDefinition processDefinition = ProcessDefinition
					.parseXmlResource(processName);
			jbpmContext.deployProcessDefinition(processDefinition);

			return "Process " + processDefinition.getName() + " redeployed.";
		} finally {
			jbpmContext.close();
		}
	}

	public String startNewProcessInstance(String processDefinitionName) {

		JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
		try {
			GraphSession graphSession = jbpmContext.getGraphSession();
			ProcessDefinition definition = graphSession
					.findLatestProcessDefinition(processDefinitionName);
			ProcessInstance instance = definition.createProcessInstance();
			long id = instance.getId();
			jbpmContext.save(instance);

			return "Started process instance: " + id;
		} finally {
			jbpmContext.close();
		}
	}

	public String readProcessInstances(String processDefinitionName) {

		JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

		try {
			GraphSession graphSession = jbpmContext.getGraphSession();
			ProcessDefinition processDefinition = graphSession
					.findLatestProcessDefinition(processDefinitionName);

			List processInstances = jbpmContext.getGraphSession()
					.findProcessInstances(processDefinition.getId());

			String html = ProcessDecorator.drawList(processInstances);

			return html;
		} finally {
			jbpmContext.close();
		}
	}

	public String signalProcess(String processDefinitionName, String id) {

		JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
		try {

			long processId = Long.parseLong(id);

			ProcessInstance instance = jbpmContext
					.loadProcessInstance(processId);
			instance.signal();

			String node = instance.getRootToken().getNode().getName();
			StringBuffer sbHtml = new StringBuffer();
			sbHtml.append("Process ");
			sbHtml.append(processId);
			sbHtml.append(" just moved to Node " + node);
			jbpmContext.save(instance);
			return sbHtml.toString();
		} finally {
			jbpmContext.close();
		}
	}

	static class ProcessDecorator {
		private static final String SIGNAL = "jbpmServlet?action=signal";
		private static final String BR = "<br />";

		static String drawList(List processInstances) {
			StringBuffer sbHtml = new StringBuffer();
			sbHtml.append("Process instances");
			sbHtml.append("<hr>");

			for (int ii = 0; ii < processInstances.size(); ii++) {
				ProcessInstance processInstance = (ProcessInstance) processInstances
						.get(ii);
				// We don't display ended processes
				if (processInstance.hasEnded())
					continue;

				String nodeName = processInstance.getRootToken().getNode()
						.getName();
				String processId = String.valueOf(processInstance.getId());

				sbHtml.append("Id              : " + processId);
				sbHtml.append("  Current Node  : <b>" + nodeName + "</b>");
				sbHtml.append("  Start time    : "
								+ processInstance.getStart());
				sbHtml.append("  "
						+ createLink(SIGNAL, "id", processId, "Signal") + BR);

			}
			sbHtml.append("<HR>");
			return sbHtml.toString();
		}

		private static String createLink(String link, String param,
				String value, String description) {
			return "<a href="/ + link + "&" + param + "=" + value + ">"
					+ description + "</a>";
		}
	}
}


This is the bare bones index.jsp which acts as start menu for this application
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<h1>JBPM web example</h1>
<body>
<a href="/jbpmServlet?action=deploy">Deploy  Process</a><br />
<a href="/jbpmServlet?action=start">Start new Process</a><br />
<a href="/jbpmServlet?action=list">Process List</a>
</body>
</html>

Once launched simply deploy the processdefinition file and start creating new process instances which can be advanced with the Signal link.
 

Have you got some time ?


if you liked this article what about helping us to improve it ? It could be nice to spice it with JSF or Struts. If you would like to collaborate mail to mailto: This e-mail address is being protected from spambots. You need JavaScript enabled to view it
Download code for this article
JBoss.org Search
Custom Search
Comments
Search
p_san   |2009-04-28 08:01:00
Above exception has been removed after some changes in the hibernate config
file placed in jbpm-services.sar.
But i think this is not the correct
place for changes in hibernate cfg file. Please tell me which hibernate
file should be configured according to my web application.

Structure
for my web application is:
webapp.war :

.web-inf
- classes
. config
.gpd.xml
 .hibernate.cfg.xml

 .jbpm.cfg.xml
 .processdefinition.xml

. controller
. lib
. web.xml
. JSPs
admin   |2009-04-28 10:45:47
the jbpm-service.sar contains the web application console and gwt-console.
However you don't need to have them installed in order to use jbpm.
Try to
start with a clean JBoss installation (without installing any jbpm
application).
Just configure the WEB-INF/classes/hibernate.cfg.xml of your web
application.
See if the problem persists.
regards
p_san   |2009-04-30 11:48:23
After following your instruction my application starts reading hibernate config
file. But now its giving exception



org.hibernate.MappingException: An
association from the table JBPM_NODE refers to an unmapped class:
org.jbpm.graph.action.Script
org.hibernate.cfg.Co
nfiguration.secondPassCompileForeignKeys(Configura
tion.java:1252)
org.hibernate.cfg.Configuration.s
econdPassCompile(Configuration.java:1170)
org.hib
ernate.cfg.Configuration.buildSessionFactory(Confi
guration.java:1286)
org.jbpm.persistence.db.DbPer
sistenceServiceFactory.getSessionFactory(DbPersist
enceServiceFactory.java:91)
org.jbpm.persistence.
db.DbPersistenceService.getSessionFactory(DbPersis
tenceService.java:95)
org.jbpm.persistence.db.DbP
ersistenceService.getSession(DbPersistenceService.
java:99)
org.jbpm.persistence.db.DbPersistenceSer
vice.getGraphSession(DbPersistenceService.java:341
)
org.jbpm.JbpmContext.getGraphSe...
rohitrai  - NullPointerException   |2009-04-28 11:52:06
Hi!
while trying to run the sample code i am getting the following
exception.

ProcessInstance instance =
jbpmContext.loadProcessInstance(processId);
Sy
stem.out.println("Instance ->
"+instance);
instance.signal();


Stack Trace is as shown
below:
SEVERE: Servlet.service() for servlet JBPMServlet threw
exception
org.jbpm.graph.def.DelegationException

at
org.jbpm.graph.def.GraphElement.raiseException(Gra phElement.java:379)
at
org.jbpm.graph.def.GraphElement.raiseException(Gra phElement.java:370)
at
org.jbpm.graph.def.GraphElement.executeAction(Grap hElement.java:273)
at
org.jbpm.graph.def.GraphElement.executeActions(Gra phElement.java:212)
at
org.jbpm.graph.def.GraphElement.fireAndPropagateEv
ent(GraphElement.java:182)
at
org.jbpm.graph.def.GraphElement.fireEvent(GraphEle ment.java:166)
at
org.jbpm.graph.def.Node.leave(Node.java:377)
at
org.jbpm.graph.node.StartSt...
p_san  - Need help in jbpm   |2009-05-04 13:58:46
Can any body tell me why i am getting this exception

[JDBCExceptionReporter]
SQL Error: -22, SQLState: S0002
16:10:59,059 INFO [STDOUT] 16:10:59,059 ERROR
[JDBCExceptionReporter] Table not found in statement [select top ?
processdef0_.ID_ as ID1_4_, processdef0_.NAME_ as NAME3_4_,
processdef0_.DESCRIPTION_ as DESCRIPT4_4_, processdef0_.VERSION_ as VERSION5_4_,
processdef0_.ISTERMINATIONIMPLICIT_ as ISTERMIN6_4_, processdef0_.STARTSTATE_ as
STARTSTATE7_4_ from JBPM_PROCESSDEFINITION processdef0_ where
processdef0_.NAME_=? order by processdef0_.VERSION_ desc]
16:10:59,262 ERROR
[STDERR] org.hibernate.exception.SQLGrammarException: could not execute
query
at org.hibernate.exception.SQLStateConverter.convert(
SQLStateConverter.java:67)
at
org.hibernate.exception.JDBCExceptionHelper.conver
t(JDBCExceptionHelper.java:43)
at
org.hibernate.loader.Loader.doList(Loader.java:221 6)
at
org.hibernate.loader.Loader.listIg...
admin   |2009-05-04 15:31:54
I think that your JBPM schema hasn't been created correctly. Verify from jbpm
documentation the scripts necessary to create the initial schema for jbpm.
p_san  - Thanks   |2009-05-05 12:23:32
Thanks my web application is deployed and working now, but i did this using Sql
Server DataBase
rohitrai  - org.jbpm.graph.def.DelegationException   |2009-05-05 13:37:14
This is caused by :

Caused by: java.lang.NullPointerException
at
org.jbpm.graph.def.Action.execute(Action.java:129)
at
org.jbpm.graph.def.GraphElement.executeAction(Grap hElement.java:256)
... 42
more

The line of exception is coming at:
public String signalProcess(String
processDefinitionName, String id) {

JbpmContext jbpmContext =
jbpmConfiguration.createJbpmContext();
try {

long processId =
Long.parseLong(id);

ProcessInstance instance =
jbpmContext
.loadProcessInstance(processId);
instance.signal();//this
signal is giving an exception

String node =
instance.getRootToken().getNode().getName();
S tringBuffer sbHtml = new
StringBuffer();
sbHtml.append("Process
";
sbHtml.append(processId);
sbHtml.a ppend(" just moved to
Node " + node);
jbpmContext.save(instance);
return
sbHtml.toString();
admin   |2009-05-08 09:21:05
verify if your ProcessInstance field is null. If it's not null but you get a
NullPointerExcp it can be a problem with your graph.....
p_san   |2009-05-06 07:36:52
can any body tell me how a Xhtml form for a jbpm proces be converted in to a jsp
form
admin   |2009-05-08 09:13:48
Xhtml pages are powered by JSF so rather then converting you should re-write
from scratch in JSP. IMHO I'd suggest to take a look at Seam-JBPM integration
which makes easier to integrate JBPM with a web application.
p_san  - task form association with task node   |2009-05-08 13:32:04
Hi can any one tell me how to associate a task form to a task node in a web
application
p_san   |2009-05-12 06:57:25
Hi can any one tell me how the variables of a task form(View) which i want to
create using JSP are mapped with a process. I mean to say what kind of mapping
exists between a task form and a process.
p_san   |2009-05-12 13:41:58
hi,
How an already deployed jbpm process can be accessed from a web
application.
Is this possible ??
Please reply.... any jBPM expert..
admin   |2009-05-12 14:06:55
look at line 35
Code:
 ProcessDefinition definition = graphSession
 
 .findLatestProcessDefinition(processDefinitionName ;


there you load in the web application a process definition. Just make
it available in the web application's classpath (ex.
in web-inf/classes )
rohitrai  - Sample jBPM program - could anyone check if this i   |2009-06-03 06:07:05
Hello,

I have been looking to integrate the jBPM engine into a sample
web based application. For this after a process is deployed i
have written a method to signal that will signal a transistion. As i
am very new to JBPM and did not get a lot of references in the web
regarding how to go about it. Could anyone possibly comment on the
following piece of code.

This method will return a map that will have a
key value pair like: 
{WIP=PM,DM,GPM}

(Other posts since i am
not being able to paste the entire code here:
http://www.coderanch.com/t/447968/JBoss/JBoss-j...
)
Here key is : WIP (WorkInProgress) 
PM,DM,GPM : Roles who have access
to that state WIP

The method is as follows:
Code:

public Map signalProcess(String processDefinitionName, long
processInstanceId, String userRole) {
JbpmContext jbpmContext
= jbpmConfiguration.createJbpmCon...
vignesh  - Kind Request     |2009-07-02 08:00:31
Dear Admin,
I thank you very much for providing such an informative, impressive
content to our readers.
But the comments feature in our website makes
the content a bit confusing. I took me lot of time to figure out what actually
is posted first & what follows it.
Of course, there is a indentation
characteristic for differentiating replies but still the first post should come
first & others should follow it.

Please customize the design slightly so that
anyone can easily identify what's happening.
I hope someone else out there
thinks the same
thanks.
- MasterTheBoss Fan.
vignesh  - Requesting your Help     |2009-07-07 09:26:15
Hi i successfully run this application in Tomcat. But it is not working in jBoss. I am using jBPM 3.2.X with jBoss 4.2.X in MySQL 5 Database. I am facing some hibernate related problems.

What i did in Tomcat ?
In Tomcat, i added all the jBPM libraries to Tomcat common lib folder & in
the Hibernate file, i gave the Database details directly & removed
the Datasource (jbpmDS).

What's wrong with jBoss ?
If it works with Tomcat, it must work with jBoss too. I removed the
database details & enabled the Datasource.
Added the application to server/default/deploy and tried to execute it & ended up with this exception.

Code:
org.hibernate.HibernateException: No CurrentSessionContext configured!
org.hibernate.impl.SessionFactoryImpl.getCurrent Session(SessionFactoryIm
pl.java:542)
org.jbpm.per sistence.db.DbPersistenceService.getSession(DbPe
rs istenceService.java:90)
org.jbpm.persistence.db.D bPersi...
prajatna  - Mahunta   |2009-08-21 23:36:35
Hi,
Thanks for the nice document.

I am developing simple JBPM process, with
some java classes only..My doubt is when we are using a task node with two
transitions, how execution context decides, which transition has to follow.


How to customize the recquired transition the execution should follow..as if we
didn't control that it 'll always choose the default(1st) transition...

Can you
please explain how we can customize the transition and, where we need to write
that code...
Only registered users can write comments!

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."