JBoss.orgCommunity Documentation
Read this chapter and studied the examples to learn how to configure the jBPM.
The simplest way to configure the Business Process Manager is by
putting the jbpm.cfg.xml configuration file into
the root of the classpath. If the file is not available for use as a
resource, the default minimal configuration will be used instead. This
minimal configuration is included in the jBPM library
(org/jbpm/default.jbpm.cfg.xml.) If a jBPM
configuration file is provided, the values it contains will be used as
the defaults. Hence, one only needs to specify the values that are to
be different from those in the default configuration file.
The jBPM configuration is represented by a Java class called
org.jbpm.JbpmConfiguration. Obtain it by
making use of the singleton instance method
(JbpmConfiguration.getInstance().)
Use the JbpmConfiguration.parseXxxx methods
to load a configuration from another source.
static JbpmConfinguration jbpmConfiguration = JbpmConfinguration.parseResource("my.jbpm.cfg.xml");
The JbpmConfiguration is "thread safe" and,
hence, can be kept in a static member.
Every thread can use a JbpmConfiguration as a
factory for JbpmContext
objects. A JbpmContext will usually represent
one transaction. They make services available inside
context blocks which looks like this:
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// This is what we call a context block.
// Here you can perform workflow operations
} finally {
jbpmContext.close();
}
The JbpmContext makes both a set of services
and the configuration settings available to the Business Process
Manager. The services are configured by the values in the
jbpm.cfg.xml file. They make it possible for the
jBPM to run in any Java environment, using whatever services are
available within said environment.
Here are the default configuration settings for the
JbpmContext:
<jbpm-configuration>
<jbpm-context>
<service name='persistence'
factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />
<service name='message'
factory='org.jbpm.msg.db.DbMessageServiceFactory' />
<service name='scheduler'
factory='org.jbpm.scheduler.db.DbSchedulerServiceFactory' />
<service name='logging'
factory='org.jbpm.logging.db.DbLoggingServiceFactory' />
<service name='authentication'
factory=
'org.jbpm.security.authentication.DefaultAuthenticationServiceFactory' />
</jbpm-context>
<!-- configuration resource files pointing to default
configuration files in jbpm-{version}.jar -->
<string name='resource.hibernate.cfg.xml' value='hibernate.cfg.xml' />
<!-- <string name='resource.hibernate.properties'
value='hibernate.properties' /> -->
<string name='resource.business.calendar'
value='org/jbpm/calendar/jbpm.business.calendar.properties' />
<string name='resource.default.modules'
value='org/jbpm/graph/def/jbpm.default.modules.properties' />
<string name='resource.converter'
value='org/jbpm/db/hibernate/jbpm.converter.properties' />
<string name='resource.action.types'
value='org/jbpm/graph/action/action.types.xml' />
<string name='resource.node.types'
value='org/jbpm/graph/node/node.types.xml' />
<string name='resource.parsers'
value='org/jbpm/jpdl/par/jbpm.parsers.xml' />
<string name='resource.varmapping'
value='org/jbpm/context/exe/jbpm.varmapping.xml' />
<string name='resource.mail.templates'
value='jbpm.mail.templates.xml' />
<int name='jbpm.byte.block.size' value="1024" singleton="true" />
<bean name='jbpm.task.instance.factory'
class='org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl'
singleton='true' />
<bean name='jbpm.variable.resolver'
class='org.jbpm.jpdl.el.impl.JbpmVariableResolver'
singleton='true' />
<string name='jbpm.mail.smtp.host' value='localhost' />
<bean name='jbpm.mail.address.resolver'
class='org.jbpm.identity.mail.IdentityAddressResolver'
singleton='true' />
<string name='jbpm.mail.from.address' value='jbpm@noreply' />
<bean name='jbpm.job.executor'
class='org.jbpm.job.executor.JobExecutor'>
<field name='jbpmConfiguration'><ref bean='jbpmConfiguration' />
</field>
<field name='name'><string value='JbpmJobExecutor' /></field>
<field name='nbrOfThreads'><int value='1' /></field>
<field name='idleInterval'><int value='60000' /></field>
<field name='retryInterval'><int value='4000' /></field>
<!-- 1 hour -->
<field name='maxIdleInterval'><int value='3600000' /></field>
<field name='historyMaxSize'><int value='20' /></field>
<!-- 10 minutes -->
<field name='maxLockTime'><int value='600000' /></field>
<!-- 1 minute -->
<field name='lockMonitorInterval'><int value='60000' /></field>
<!-- 5 seconds -->
<field name='lockBufferTime'><int value='5000' /></field>
</bean>
</jbpm-configuration>
The above file contains three parts:
a set of service implementations which
configure the JbpmContext. (The possible
configuration options are detailed in the chapters that cover
specific service implementations.)
all of the mappings linking references to configuration
resources. If one wishes to customize one of the configuration
files, update these mappings. To do so, always back up the
default configuration file (jbpm-3.x.jar)
to another location on the classpath first. Then, update the
reference in this file, pointing it to the customized version
that the jBPM is to use.
miscellaneous configurations for use by the jBPM. (These are described in the chapters that cover the specific topics in question.)
The default configuration has been optimized for a simple web application environment which has minimal dependencies. The persistence service obtains a JDBC connection which is used by all of the other services. Hence, all of the workflow operations are centralized as they are placed in a single transaction on a JDBC connection (without the need for a transaction manager.)
JbpmContext contains convenience
methods for most of the common process operations. They
are demonstrated in this code sample:
public void deployProcessDefinition(ProcessDefinition processDefinition)
public List getTaskList()
public List getTaskList(String actorId)
public List getGroupTaskList(List actorIds)
public TaskInstance loadTaskInstance(long taskInstanceId)
public TaskInstance loadTaskInstanceForUpdate(long taskInstanceId)
public Token loadToken(long tokenId)
public Token loadTokenForUpdate(long tokenId)
public ProcessInstance loadProcessInstance(long processInstanceId)
public ProcessInstance loadProcessInstanceForUpdate(long processInstanceId)
public ProcessInstance newProcessInstance(String processDefinitionName)
public void save(ProcessInstance processInstance)
public void save(Token token)
public void save(TaskInstance taskInstance)
public void setRollbackOnly()
There is no need to call any of the save methods explicitly
because the XxxForUpdate methods are
designed to register the loaded object for "auto-save."
It is possible to specify multiple
jbpm-contexts. To do so, make sure that each
of them is given a unique name attribute.
(Retrieve named contexts by using
JbpmConfiguration.createContext(String
name);.)
A service element specifies its own name and
associated service factory. The service
will only be created when requested to do so by
JbpmContext.getServices().getService(String
name).
One can also specfy the factories as
elements instead of attributes. This is
necessary when injecting some configuration information into factory
objects.
Note that the component responsible for creating and wiring the
objects and parsing the XML is called the object
factory.
A mistake commonly made by people when they are trying to customize factories is to mix long and short notation together. (Examples of the short notation can be seen in the default configuration file.)
Hibernate logs
StateObjectStateException exceptions
and generates a stack trace. In order to
remove the latter, set
org.hibernate.event.def.AbstractFlushingEventListener
to FATAL. (Alternatively, if using
log4j, set the following line in the
configuration: for that:
log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=FATAL
<service name='persistence'
factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />
If one needs to note specific properties on a service, only the long notation can be used.
<service name="persistence">
<factory>
<bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory">
<field name="dataSourceJndiName">
<string value="java:/myDataSource"/>
</field>
<field name="isCurrentSessionEnabled"><true /></field>
<field name="isTransactionEnabled"><false /></field>
</bean>
</factory>
</service>
File attachments and binary variables are stored in the database in the form of a list of fixed-sized, binary objects. (The aim of this is to improve portability amongst different databases. It also allows one to embed the jBPM more easily.) This parameter controls the size of those fixed-length chunks.
To customize the way in which task instances are
created, specify a fully-qualified classname against
this property. (This is often necessary when one intends
to customize, and add new properties to, the
TaskInstance bean.) Ensure that
the specified classname implements the
org.jbpm.taskmgmt.TaskInstanceFactory
interface. (Refer to Section 11.10, “
Customizing Task Instances
” for more
information.)
Use this to customize the way in which jBPM looks for the first term in "JSF"-like expressions.
There are a number of configuration files in the jBPM which can be customized:
hibernate.cfg.xmlThis contains references to, and configuration details for, the Hibernate mapping resource files.
To specify a different file, configure the
jbpm.hibernate.cfg.xml property in
jbpm.properties. (The
default Hibernate
configuration file is located in the
src/config.files/hibernate.cfg.xml
sub-directory.)
org/jbpm/db/hibernate.queries.hbm.xml
This file contains those Hibernate
queries to be used in the jBPM sessions
(org.jbpm.db.*Session.)
org/jbpm/graph/node/node.types.xml
This file is used to map XML node elements to
Node implementation classes.
org/jbpm/graph/action/action.types.xml
This file is used to map XML action elements to
Action implementation classes.
org/jbpm/calendar/jbpm.business.calendar.propertiesThis contains the definitions of "business hours" and "free time."
org/jbpm/context/exe/jbpm.varmapping.xmlThis specifies the way in which the process variables values (Java objects) are converted to variable instances for storage in the jBPM database.
org/jbpm/db/hibernate/jbpm.converter.properties
This specifies the id-to-classname mappings. The
ids are stored in the database. The
org.jbpm.db.hibernate.ConverterEnumType class
is used to map the identifiers to the
singleton objects.
org/jbpm/graph/def/jbpm.default.modules.properties
This specifies which modules are to be added to a new
ProcessDefinition by default.
org/jbpm/jpdl/par/jbpm.parsers.xmlThis specifies the phases of process archive parsing.
When it is run in a cluster configuration, the jBPM synchronizes with
the database by using optimistic locking.
This means that each operation is performed in a transaction and
if, at the end, a collision is detected, then the transaction in
question is rolled back and has to be handled with a retry. This
can cause
org.hibernate.StateObjectStateException
exceptions. If and when this happens,
Hibernate will log the exceptions
with a simple message,
optimistic locking
failed.
Hibernate can also log the
StateObjectStateException with a
stack trace. To remove these stack traces, set the
org.hibernate.event.def.AbstractFlushingEventListener
class to FATAL. Do so in
log4j by using the following
configuration:
log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=FATAL
In order to log jBPM stack traces, add the following line to the
jbpm.cfg.xml file:
<boolean name="jbpm.hide.stale.object.exceptions" value="false" />
The Object Factory can build objects to the specification contained in a "beans-like" XML configuration file. This file dictates how objects are to be created, configured and wired together to form a complete object graph. Also use the Object Factory to inject configurations and other beans into a single bean.
In its most elementary form, the Object Factory is able to create both basic types and Java beans from such a configuration, as shown in the following examples:
<beans>
<bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance"/>
<string name="greeting">hello world</string>
<int name="answer">42</int>
<boolean name="javaisold">true</boolean>
<float name="percentage">10.2</float>
<double name="salary">100000000.32</double>
<char name="java">j</char>
<null name="dusttodust" />
</beans>
ObjectFactory of = ObjectFactory.parseXmlFromAbove();
assertEquals(TaskInstance.class, of.getNewObject("task").getClass());
assertEquals("hello world", of.getNewObject("greeting"));
assertEquals(new Integer(42), of.getNewObject("answer"));
assertEquals(Boolean.TRUE, of.getNewObject("javaisold"));
assertEquals(new Float(10.2), of.getNewObject("percentage"));
assertEquals(new Double(100000000.32), of.getNewObject("salary"));
assertEquals(new Character('j'), of.getNewObject("java"));
assertNull(of.getNewObject("dusttodust"));]]>
This code shows how to configure lists:
<beans>
<list name="numbers">
<string>one</string>
<string>two</string>
<string>three</string>
</list>
</beans>
This code demonstrates how to configure maps:
<beans>
<map name="numbers">
<entry>
<key><int>1</int></key>
<value><string>one</string></value>
</entry>
<entry>
<key><int>2</int></key>
<value><string>two</string></value>
</entry>
<entry>
<key><int>3</int></key>
<value><string>three</string></value>
</entry>
</map>
</beans>
Use direct field injection and property
setter methods to configure beans:
<beans>
<bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
<field name="name"><string>do dishes</string></field>
<property name="actorId"><string>theotherguy</string></property>
</bean>
</beans>
Beans can be referenced. The referenced object doesn't have to be a bean; it can be a string, an integer or any other kind. Here is some code that demonstrates this capability:
<beans>
<bean name="a" class="org.jbpm.A" />
<ref name="b" bean="a" />
</beans>
Beans can be built with any constructor, as this code shows:
<beans>
<bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
<constructor>
<parameter class="java.lang.String">
<string>do dishes</string>
</parameter>
<parameter class="java.lang.String">
<string>theotherguy</string>
</parameter>
</constructor>
</bean>
</beans>
Beans can be constructed using a factory
method:
<beans>
<bean name="taskFactory"
class="org.jbpm.UnexistingTaskInstanceFactory"
singleton="true"/>
<bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
<constructor factory="taskFactory" method="createTask" >
<parameter class="java.lang.String">
<string>do dishes</string>
</parameter>
<parameter class="java.lang.String">
<string>theotherguy</string>
</parameter>
</constructor>
</bean>
</beans>
Beans can be constructed using a static
factory method on a class:
<beans>
<bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
<constructor
factory-class="org.jbpm.UnexistingTaskInstanceFactory"
method="createTask" >
<parameter class="java.lang.String">
<string>do dishes</string>
</parameter>
<parameter class="java.lang.String">
<string>theotherguy</string>
</parameter>
</constructor>
</bean>
</beans>
Use the attribute singleton="true" to mark each named
object as a singleton. Doing so will ensure that a
given object factory always returns the
same object for each request.
Singletons cannot be shared between
different object factories.
The singleton feature causes
differentiation between the methods named
getObject and
getNewObject. Normally, one should use
getNewObject as this clears the
object factory's object
cache before the new object graph is constructed.
During construction of the object graph, the
non-singleton objects are stored in the
object factory's cache. This allows
references to one object to be shared. Bear in mind that the
singleton object cache is different from
the plain object cache. The
singleton cache is never cleared, whilst
the plain one is cleared every time a
getNewObject method is started.
Having studied this chapter, one now has a thorough knowledge of the many ways in which the jBPM can be configured.