Chapter 5. Configuration

Table of Contents

Customizing factories
Configuration properties
Other configuration files
Hibernate cfg xml file
Hibernate queries configuration file
Node types configuration file
Action types configuration file
Business calendar configuration file
Variable mapping configuration file
Converter configuration file
Default modules configuration file
Process archive parsers configuration file
Logging of optimistic concurrency exceptions
Object factory

The simplest way to configure jBPM is by putting the jbpm.cfg.xml configuration file in the root of the classpath. If that file is not found as a resource, the default minimal configuration will be used that is included in the jbpm library (org/jbpm/default.jbpm.cfg.xml). If a jbpm configuration file is provided, the values configured will be used as defaults. So you only need to specify the parts that are different from the default configuration file.

The jBPM configuration is represented by the java class org.jbpm.JbpmConfiguration. Most easy way to get a hold of the JbpmConfiguration is to make use of the singleton instance method JbpmConfiguration.getInstance().

If you want to load a configuration from another source, you can use the JbpmConfiguration.parseXxxx methods.

static JbpmConfinguration jbpmConfiguration = JbpmConfinguration.parseResource("my.jbpm.cfg.xml");

The JbpmConfiguration is threadsafe and hence can be kept in a static member. All threads can use the JbpmConfiguration as a factory for JbpmContext objects. A JbpmContext typically represents one transaction. The JbpmContext makes services available inside of a context block. A context block 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 a set of services and the configuration available to jBPM. These services are configured in the jbpm.cfg.xml configuration file and make it possible for jBPM to run in any Java environment and use whatever services are available in that environment.

Here's the default configuration 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='5000' /></field>
    <field name='maxIdleInterval'><int value='3600000' /></field> <!-- 1 hour -->
    <field name='historyMaxSize'><int value='20' /></field>
    <field name='maxLockTime'><int value='600000' /></field> <!-- 10 minutes -->
    <field name='lockMonitorInterval'><int value='60000' /></field> <!-- 1 minute -->
    <field name='lockBufferTime'><int value='5000' /></field> <!-- 5 seconds -->
  </bean>

</jbpm-configuration>

In this configuration file you can see 3 parts:

The default configured set of services is targetted at a simple webapp environment and minimal dependencies. The persistence service will obtain a jdbc connection and all the other services will use the same connection to perform their services. So all of your workflow operations are centralized into 1 transaction on a JDBC connection without the need for a transaction manager.

JbpmContext contains convenience methods for most of the common process operations:

  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() {...}

Note that the XxxForUpdate methods will register the loaded object for auto-save so that you don't have to call one of the save methods explicitely.

It's possible to specify multiple jbpm-contexts, but then you have to make sure that each jbpm-context is given a unique name attribute. Named contexts can be retrieved with JbpmConfiguration.createContext(String name);

A service element specifies the name of a service and the service factory for that service. The service will only be created in case it's asked for with JbpmContext.getServices().getService(String name).

The factories can also be specified as an element instead of an attribute. That might be necessary to inject some configuration information in the factory objects. The component responsible for parsing the XML, creating and wiring the objects is called the object factory.

Customizing factories

A common mistake when customizing factories is to mix the short and the long notation. Examples of the short notation can be seen in the default configuration file and above: E.g.

  ...
  <service name='persistence' factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />

If specific properties on a service need to be specified, the short notation can't be used, but instead, the long notation has to be used like this: E.g.

  <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>