JBoss.orgCommunity Documentation
Read this chapter to learn about the facilities offered by the jBPM to that can be used to leverage the Java EE infrastructure.
The CommandServiceBean is a
stateless session bean that runs Business
Process Manager commands by calling its
execute method within a separate jBPM
context. The available environment entries and customizable
resources are summarized in the following table:
Table 8.1. Command Service Bean Environment
| Name | Type | Description |
|---|---|---|
JbpmCfgResource | Environment Entry | This the classpath resource from which the jBPM configuration is read.
Optional, defaults to jbpm.cfg.xml.
|
ejb/TimerEntityBean | EJB Reference | This is a link to the local entity bean that implements the scheduler service. Required for processes that contain timers. |
jdbc/JbpmDataSource | Resource Manager Reference | This is the logical name of the data source that provides JDBC connections to the jBPM persistence service. Must match the hibernate.connection.datasource property in the Hibernate configuration file. |
jms/JbpmConnectionFactory | Resource Manager Reference | This is the logical name of the factory that provides JMS connections to the jBPM message service. Required for processes that contain asynchronous continuations. |
jms/JobQueue | Message Destination Reference | The jBPM message service sends job messages to this queue.
To ensure this is the same queue from which the job listener bean receives
messages, the message-destination-link points to a common
logical destination, JobQueue.
|
jms/CommandQueue | Message Destination Reference | The command listener bean receives messages from this queue.
To ensure this is the same queue to which command messages can be sent,
the message-destination-link element points to a common
logical destination, CommandQueue.
|
The CommandListenerBean is a message-driven
bean that listens to the CommandQueue for
command messages. It delegates command execution to the
CommandServiceBean.
The body of the message must be a Java object that can implement the
org.jbpm.Command interface. (The
message properties, if any, are ignored.) If the message is not of
the expected format, it is forwarded to the
DeadLetterQueue and will not be processed any further.
The message will also be rejected if the destination reference is
absent.
If a received message specifies a replyTo
destination, the command execution result will be wrapped in an
object message and sent there.
The command connection factory environment
reference points to the resource manager being used
to supply Java Message Service connections.
Conversely, JobListenerBean is a
message-driven bean that listens to the
JbpmJobQueue for job messages, in order to
support asynchronous continuations.
Be aware that the message must have a property called
jobId of type long. This
property must contain references to a pending
Job in the database. The message body, if
it exists, is ignored.
This bean extends the CommandListenerBean. It
inherits the latter's environmental entries and those resource
references that can be customized.
Table 8.2. Command/Job listener bean environment
| Name | Type | Description |
|---|---|---|
ejb/LocalCommandServiceBean | EJB Reference | This is a link to the local session bean that executes commands on a separate jBPM context. |
jms/JbpmConnectionFactory | Resource Manager Reference | This is the logical name of the factory that provides Java Message Service connections for producing result messages. Required for command messages that indicate a reply destination. |
jms/DeadLetterQueue | Message Destination Reference | Messages which do not contain a command are sent to the queue referenced here. It is optional. If it is absent, such messages are rejected, which may cause the container to redeliver. |
The TimerEntityBean is used by the
Enterprise Java Bean timer service for
scheduling. When the bean expires, timer execution is delegated to
the command service bean.
The TimerEntityBean requires access to the
Business Process Manager's data source. The Enterprise Java Bean
deployment descriptor does not define how an entity bean is to map
to a database. (This is left to the container provider.) In the
JBoss Application Server, the
jbosscmp-jdbc.xml descriptor defines the data
source's JNDI name and relational mapping data (such as the table
and column names.)
The JBoss CMP (container-managed
persistence) descriptor uses a global
JNDI name (java:JbpmDS), as opposed to a
resource manager reference
(java:comp/env/jdbc/JbpmDataSource).
Earlier versions of the Business Process Manager used a stateless
session bean called TimerServiceBean to
interact with the Enterprise Java Bean timer service. The session
approach had to be abandoned because it caused an unavoidable
bottleneck for the cancellation methods.
Because session beans have no identity, the timer service was forced
to iterate through all the timers to find the
ones it had to cancel.
The bean is still available for backwards
compatibility purposes. It works in the same environment as the
TimerEntityBean, so migration is easy.
Table 8.3. Timer Entity/Service Bean Environment
| Name | Type | Description |
|---|---|---|
ejb/LocalCommandServiceBean | EJB Reference | This is a link to the local session bean that executes timers on a separate jBPM context. |
The following configuration items are included in
jbpm.cfg.xml:
<jbpm-context>
<service name="persistence"
factory="org.jbpm.persistence.jta.JtaDbPersistenceServiceFactory" />
<service name="message"
factory="org.jbpm.msg.jms.JmsMessageServiceFactory" />
<service name="scheduler"
factory="org.jbpm.scheduler.ejbtimer.EntitySchedulerServiceFactory" />
</jbpm-context>
The JtaDbPersistenceServiceFactory allows the
Business Process Manager to participate in JTA transactions. If an
existing transaction is underway, the JTA persistence service
"clings" to it; otherwise it starts a new transaction. The Business
Process Manager's enterprise beans are configured to delegate
transaction management to the container. However, a new one will be
started automatically if one creates a JbpmContext in an environment
in which no transaction is active (such as a web application.) The
JTA persistence service factory contains
the configurable fields described below.
When this is set to true, the Business Process
Manager will use the "current"
Hibernate session associated with
the ongoing JTA transaction. This is the default setting.
(See http://www.hibernate.org/hib_docs/v3/reference/en/html/architecture.html#architecture-current-session for more information.)
Use the same session as by jBPM in other parts of the
application by taking advantage of the contextual
session mechanism. Do so through a call to
SessionFactory.getCurrentSession().
Alternatively, supply a
Hibernate session to jBPM by
setting isCurrentSessionEnabled to
false and injecting the session via the
JbpmContext.setSession(session)
method. This also ensures that jBPM uses the same
Hibernate session as other
parts of the application.
The Hibernate session can be injected into a stateless session bean (via a persistence context, for example.)
When this is set to true, jBPM will begin a
transaction through
Hibernate's
transaction API, using the
JbpmConfiguration.createJbpmContext()
method to commit it. (The
Hibernate session is closed
when JbpmContext.close() is
called.)
This is not the desired behavior when the Business
Process Manager is deployed as an EAR and hence
isTransactionEnabled is set to
false by default. (See http://www.hibernate.org/hib_docs/v3/reference/en/html/transactions.html#transactions-demarcation for more details.)
JmsMessageServiceFactory delivers
asynchronous continuation messages to the
JobListenerBean by leveraging the reliable
communication infrastructure exposed through the Java Message Service
interfaces. The JmsMessageServiceFactory
exposes the following configurable fields:
This is the name of the JMS connection factory in the
JNDI initial context. It defaults to
java:comp/env/jms/JbpmConnectionFactory.
This is the name of the JMS destination to which job
messages will be sent. It must match the destination
from which JobListenerBean
receives messages. It defaults to
java:comp/env/jms/JobQueue.
This specifies whether the Business Process Manager
should commit the Java Message Service session upon
JbpmContext.close(). Messages
produced by the JMS message service are never meant to
be received before the current transaction commits;
hence the sessions created by the service are always
transacted. The default value is false,
which is appropriate when the connection
factory in use is XA-capable, as the
messages produced by the Java Message Service session
will be controlled by the overall JTA transaction. This
field should be set to true if the JMS
connection factory is not XA-capable so that the
Business Process Manager explicitly commits the JMS
session's local transaction.
The EntitySchedulerServiceFactory is used
to schedule business process timers. It does so by building upon on
the transactional notification service for timed events provided by
the Enterprise Java Bean container. The EJB
scheduler service factory has the
configurable field described
below.
This is the name of the
TimerEntityBean's local home
interface in the JNDI initial context. The default value
is
java:comp/env/ejb/TimerEntityBean.
The hibernate.cfg.xml file includes the
following configuration items. Modify them to support other
databases or application servers.
<!-- sql dialect -->
<property name="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
<!-- DataSource properties (begin) -->
<property name="hibernate.connection.datasource">
java:comp/env/jdbc/JbpmDataSource
</property>
<!-- DataSource properties (end) -->
<!-- JTA transaction properties (begin) -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<property name="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JBossTransactionManagerLookup
</property>
<!-- JTA transaction properties (end) -->
<!-- CMT transaction properties (begin) ===
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</property>
<property name="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JBossTransactionManagerLookup
</property>
==== CMT transaction properties (end) -->
Replace the hibernate.dialect setting with that which
is appropriate for one's database management system. (For more
information, read http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html#configuration-optional-dialects.)
The HashtableCacheProvider can be replaced
with other supported cache providers. (Refer to http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache for more information.)
Out of the box, jBPM is configured to use the
JTATransactionFactory. If an existing
transaction is underway, the JTA transaction factory uses it;
otherwise it creates a new transaction. The jBPM enterprise beans
are configured to delegate transaction management to the container.
However, if the jBPM APIs are being used in a context in which no
transaction is active (such as a web application), one will be
started automatically.
To prevent unintended transaction creations when using
container-managed transactions, switch to the
CMTTransactionFactory. This setting ensures
that Hibernate will always look for an
existing transaction and will report a problem if none is found.
Ensure that the appropriate environmental references are in place for deployment descriptors for client components written directly against those Business Process Manager APIs that can leverage the enterprise services. The descriptor below can be regarded as typical for a client session bean:
<session>
<ejb-name>MyClientBean</ejb-name>
<home>org.example.RemoteClientHome</home>
<remote>org.example.RemoteClient</remote>
<local-home>org.example.LocalClientHome</local-home>
<local>org.example.LocalClient</local>
<ejb-class>org.example.ClientBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<ejb-ref-name>ejb/TimerEntityBean</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>org.jbpm.ejb.LocalTimerEntityHome</local-home>
<local>org.jbpm.ejb.LocalTimerEntity</local>
</ejb-local-ref>
<resource-ref>
<res-ref-name>jdbc/JbpmDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<res-ref-name>jms/JbpmConnectionFactory</res-ref-name>
<res-type>javax.jms.ConnnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>
jms/JobQueue
</message-destination-ref-name>
<message-destination-type>javax.jms.Queue</message-destination-type>
<message-destination-usage>Produces</message-destination-usage>
</message-destination-ref>
</session>
The environmental references above can be bound to resources in the target operational environment as follows. Note that the JNDI names match the values used by the Business Process Manager enterprise beans.
<session>
<ejb-name>MyClientBean</ejb-name>
<jndi-name>ejb/MyClientBean</jndi-name>
<local-jndi-name>java:ejb/MyClientBean</local-jndi-name>
<ejb-local-ref>
<ejb-ref-name>ejb/TimerEntityBean</ejb-ref-name>
<local-jndi-name>java:ejb/TimerEntityBean</local-jndi-name>
</ejb-local-ref>
<resource-ref>
<res-ref-name>jdbc/JbpmDataSource</res-ref-name>
<jndi-name>java:JbpmDS</jndi-name>
</resource-ref>
<resource-ref>
<res-ref-name>jms/JbpmConnectionFactory</res-ref-name>
<jndi-name>java:JmsXA</jndi-name>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>
jms/JobQueue
</message-destination-ref-name>
<jndi-name>queue/JbpmJobQueue</jndi-name>
</message-destination-ref>
</session>
If the client component is a web application, as opposed to an enterprise bean, the deployment descriptor shall look like this:
<web-app>
<servlet>
<servlet-name>MyClientServlet</servlet-name>
<servlet-class>org.example.ClientServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyClientServlet</servlet-name>
<url-pattern>/client/servlet</url-pattern>
</servlet-mapping>
<ejb-local-ref>
<ejb-ref-name>ejb/TimerEntityBean</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>org.jbpm.ejb.LocalTimerEntityHome</local-home>
<local>org.jbpm.ejb.LocalTimerEntity</local>
<ejb-link>TimerEntityBean</ejb-link>
</ejb-local-ref>
<resource-ref>
<res-ref-name>jdbc/JbpmDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<res-ref-name>jms/JbpmConnectionFactory</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>
jms/JobQueue
</message-destination-ref-name>
<message-destination-type>javax.jms.Queue</message-destination-type>
<message-destination-usage>Produces</message-destination-usage>
<message-destination-link>JobQueue</message-destination-link>
</message-destination-ref>
</web-app>
The above environmental references can also be bound to resources in the target operational environment, as per this code sample:
<jboss-web>
<ejb-local-ref>
<ejb-ref-name>ejb/TimerEntityBean</ejb-ref-name>
<local-jndi-name>java:ejb/TimerEntityBean</local-jndi-name>
</ejb-local-ref>
<resource-ref>
<res-ref-name>jdbc/JbpmDataSource</res-ref-name>
<jndi-name>java:JbpmDS</jndi-name>
</resource-ref>
<resource-ref>
<res-ref-name>jms/JbpmConnectionFactory</res-ref-name>
<jndi-name>java:JmsXA</jndi-name>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>
jms/JobQueue
</message-destination-ref-name>
<jndi-name>queue/JbpmJobQueue</jndi-name>
</message-destination-ref>
</jboss-web>