JBoss.org Community Documentation

- Prev

## Chapter 19. Integration with Maven, OSGi, Spring, etc.

jBPM can be integrated with a lot of other technologies. This chapter gives an overview of a few of those that are supported out-of-the-box. Most of these modules are developed as part of the droolsjbpm-integration module, so they work not only for your business processes but also for business rules and complex event processing.

## 19.1. Maven

By using a Maven pom.xml to define your project dependencies, you can let maven get your dependencies for you. The following pom.xml is an example that could for example be used to create a new Maven project that is capable of executing a BPMN2 process:

    <?xml version="1.0" encoding="utf-8"?>

    <project xmlns="http://maven.apache.org/POM/4.0.0"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>org.jbpm</groupId>

      <artifactId>jbpm-maven-example</artifactId>

      <name>jBPM Maven Project</name>

      <version>1.0-SNAPSHOT</version>

      <repositories>

        <!--  use this repository for stable releases -->

        <repository>

          <id>jboss-public-repository-group</id>

          <name>JBoss Public Maven Repository Group</name>

          <url>https://repository.jboss.org/nexus/content/groups/public/</url>

          <layout>default</layout>

          <releases>

            <enabled>true</enabled>

            <updatePolicy>never</updatePolicy>

          </releases>

          <snapshots>

            <enabled>false</enabled>

          </snapshots>

        </repository>

        <!-- use this repository for snapshot releases -->

        <repository>

          <id>jboss-snapshot-repository-group</id>

          <name>JBoss SNAPSHOT Maven Repository Group</name>

          <url>https://repository.jboss.org/nexus/content/repositories/snapshots/</url>

          <layout>default</layout>

          <releases>

            <enabled>false</enabled>

          </releases>

          <snapshots>

            <enabled>true</enabled>

            <updatePolicy>never</updatePolicy>

          </snapshots>

        </repository>

      </repositories>

      <dependencies>

        <dependency>

          <groupId>org.jbpm</groupId>

          <artifactId>jbpm-bpmn2</artifactId>

          <version>5.0.0</version>

        </dependency>

      </dependencies>

    </project>

To use this as the basis for your project in Eclipse, either use M2Eclipse or use "mvn eclipse:eclipse" to generate eclipse .project and .classpath files based on this pom.

## 19.2. OSGi

All core jbpm jars (and core dependencies) are OSGi-enabled. That means that they contain MANIFEST.MF files (in the META-INF directory) that describe their dependencies etc. These manifest files are automatically generated by the build. You can plug these jars directly into an OSGi environment.

OSGi is a dynamic module system for declarative services. So what does that mean? Each jar in OSGi is called a bundle and has it's own Classloader. Each bundle specifies the packages it exports (makes publicly available) and which packages it imports (external dependencies). OSGi will use this information to wire the classloaders of different bundles together; the key distinction is you don't specify what bundle you depend on, or have a single monolithic classpath, instead you specify your package import and version and OSGi attempts to satisfy this from available bundles.

It also supports side by side versioning, so you can have multiple versions of a bundle installed and it'll wire up the correct one. Further to this Bundles can register services for other bundles to use. These services need initialisation, which can cause ordering problems - how do you make sure you don't consume a service before its registered? OSGi has a number of features to help with service composition and ordering. The two main ones are the programmatic ServiceTracker and the xml based Declarative Services. There are also other projects that help with this; Spring DM, iPOJO, Gravity.

The following jBPM jars are OGSi-enabled:

- jbpm-flow
- jbpm-flow-builder
- jbpm-bpmn2

For example, the following code example shows how you can look up the necessary services in an OSGi environment using the service registry and create a session that can then be used to start processes, signal events, etc.

    ServiceReference serviceRef = bundleContext.getServiceReference( ServiceRegistry.class.getName() );
    ServiceRegistry registry = (ServiceRegistry) bundleContext.getService( serviceRef );

    KnowledgeBuilderFactoryService knowledgeBuilderFactoryService = registry.get( KnowledgeBuilderFactoryService.class );
    KnowledgeBaseFactoryService knowledgeBaseFactoryService = registry.get( KnowledgeBaseFactoryService.class );
    ResourceFactoryService resourceFactoryService = registry.get( ResourceFactoryService.class );

    KnowledgeBaseConfiguration kbaseConf = knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null, getClass().getClassLoader() );

    KnowledgeBuilderConfiguration kbConf = knowledgeBuilderFactoryService.newKnowledgeBuilderConfiguration( null, getClass().getClassLoader() );
    KnowledgeBuilder kbuilder = knowledgeBuilderFactoryService.newKnowledgeBuilder( kbConf );
    kbuilder.add( resourceFactoryService.newClassPathResource( "MyProcess.bpmn", Dummy.class ), ResourceType.BPMN2 );

    kbaseConf = knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null, getClass().getClassLoader() );
    KnowledgeBase kbase = knowledgeBaseFactoryService.newKnowledgeBase( kbaseConf );
    kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );

    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

## 19.3. Spring

A Spring XML configuration file can be used to easily define and configure knowledge bases and sessions in a Spring environment. This allows you to simply access a session and invoke processes from within your Spring application.

For example, the following configuration file sets up a new session based on a knowledge base with one process definition (loaded from the classpath).

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xmlns:jbpm="http://drools.org/schema/drools-spring"

           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

                               http://drools.org/schema/drools-spring org/drools/container/spring/drools-spring-1.2.0.xsd>

      <jbpm:kbase id="kbase">

        <jbpm:resources>

          <jbpm:resource type="BPMN2" source="classpath:HelloWorld.bpmn2"/>

        </jbpm:resources>

      </jbpm:kbase>

      <jbpm:ksession id="ksession" type="stateful" kbase="kbase" />

    </beans>

The following piece of code can be used to load the above Spring configuration, retrieve the session and start the process.

    ClassPathXmlApplicationContext context =

        new ClassPathXmlApplicationContext("spring-conf.xml");

    StatefulKnowledgeSession ksession = (StatefulKnowledgeSession) context.getBean("ksession");

    ksession.startProcess("com.sample.HelloWorld");

Note that you can also inject the session in one of your domain objects, for example by adding the following fragment in the configuration file.

    <bean id="myObject" class="org.jbpm.sample.MyObject">

      <property name="session" ref="ksession" />

    </bean>

As a result, the session will be injected in your domain object can then be accessed directly. For example:

    public class MyObject {

      private StatefulKnowledgeSession ksession;

      public void setSession(StatefulKnowledgeSession ksession) {

        this.ksession = ksession;

      }

      public void doSomething() {

        ksession.startProcess("com.sample.HelloWorld");

      }

    }

The following example shows a slightly more complex example, where the session is configured to use persistence (JPA using an in-memory database) and transaction (using the Spring transaction manager).

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xmlns:drools="http://drools.org/schema/drools-spring"

           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

                               http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring-1.3.0.xsd">

        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

          <property name="driverClassName" value="org.h2.Driver"/>

          <property name="url" value="jdbc:h2:mem:jbpm"/>

          <property name="username" value="sa"/>

          <property name="password" value=""/>

        </bean>

        <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

          <property name="dataSource" ref="dataSource"/>

          <property name="persistenceUnitName" value="org.drools.persistence.jpa.local"/>

        </bean>

        <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">

          <property name="entityManagerFactory" ref="emf"/>

        </bean>

        <drools:grid-node id="node1"/>

        <drools:kbase id="kbase1" node="node1">

          <drools:resources>

            <drools:resource type="BPMN2" source="classpath:MyProcess.bpmn"/>

          </drools:resources>

        </drools:kbase>

        <drools:ksession id="ksession1" type="stateful" kbase="kbase1" node="node1">

          <drools:configuration>

            <drools:jpa-persistence>

              <drools:transaction-manager ref="txManager"/>

              <drools:entity-manager-factory ref="emf"/>

            </drools:jpa-persistence>

          </drools:configuration>

        </drools:ksession>

    </beans>

In order to execute the above example you must be sure that in your META-INF you have a persistent.xml file with the following content:

    <?xml version="1.0" encoding="UTF-8"?>

    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"

                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

      <persistence-unit name="org.drools.persistence.jpa.local">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <mapping-file>META-INF/JBPMorm.xml</mapping-file>

        <mapping-file>META-INF/ProcessInstanceInfo.hbm.xml</mapping-file>

        <class>org.drools.persistence.info.SessionInfo</class>

        <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>

        <class>org.drools.persistence.info.WorkItemInfo</class>

        <properties>

          <property name="hibernate.max_fetch_depth" value="3"/>

          <property name="hibernate.hbm2ddl.auto" value="update"/>

          <property name="hibernate.show_sql" value="false"/>

          <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

        </properties>

      </persistence-unit>

    </persistence>

## 19.4. Apache Camel Integration

Camel provides a lightweight bus framework for geting information into and out of jBPM. Additionally Camel provides a way to expose your KnowledgeBases remotely for any sort of client application that can use HTTP, through a SOAP or REST interface.

The following example shows how to setup a remote accessible session:

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xmlns:cxf="http://camel.apache.org/schema/cxf"

           xmlns:jaxrs="http://cxf.apache.org/jaxrs"

           xmlns:kb="http://drools.org/schema/drools-spring"

           xsi:schemaLocation="

           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd

           http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd

           http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd

           http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

      <!-- jBPM Knowledge Related Config -->

      <kb:grid-node id="node1"/>

      <kb:kbase id="kbase1" node="node1">

        <kb:resources>

          <kb:resource type="BPMN2" source="classpath:MyProcess.bpmn"/>

        </kb:resources>

      </kb:kbase>

      <kb:ksession id="ksession1" type="stateless" kbase="kbase1" node="node1"/>

      <!-- Camel Config -->

      <import resource="classpath:META-INF/cxf/cxf.xml" />

      <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

      <cxf:rsServer id="rsServer"

                    address="/rest"

                    serviceClass="org.drools.jax.rs.CommandExecutorImpl">

           <cxf:providers>

               <bean class="org.drools.jax.rs.CommandMessageBodyReader"/>

           </cxf:providers>

      </cxf:rsServer>

      <cxf:cxfEndpoint id="soapServer"

                address="/soap"

                 serviceName="ns:CommandExecutor"

                 endpointName="ns:CommandExecutorPort"

              wsdlURL="soap.wsdl"

              xmlns:ns="http://soap.jax.drools.org/" >

        <cxf:properties>

          <entry key="dataFormat" value="MESSAGE"/>

          <entry key="defaultOperationName" value="execute"/>

        </cxf:properties>

      </cxf:cxfEndpoint>

      <!-- Must have bean - needed to make Camel "drools" aware -->

      <bean id="kbPolicy" class="org.drools.camel.component.DroolsPolicy" />

      <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">

        <route>

           <from uri="cxfrs://bean://rsServer"/>

           <policy ref="kbPolicy">

             <unmarshal ref="xstream" />

             <to uri="drools:node1/ksession1" />

             <marshal ref="xstream" />

           </policy>

        </route>

        <route>

          <from uri="cxf://bean://soapServer"/>

          <policy ref="kbPolicy">

            <unmarshal ref="xstream" />

            <to uri="drools:node1/ksession1" />

            <marshal ref="xstream" />

          </policy>

        </route>

      </camelContext>

    </beans>

To execute the above example you must be sure that you have the folliwing content in your web.xml file:

    <web-app>

      (...)

      <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>classpath:beans.xml</param-value>

      </context-param>

      <listener>

        <listener-class>

          org.springframework.web.context.ContextLoaderListener

        </listener-class>

      </listener>

      <servlet>

        <display-name>CXF Servlet</display-name>

        <servlet-name>CXFServlet</servlet-name>

        <servlet-class>

          org.apache.cxf.transport.servlet.CXFServlet

        </servlet-class>

        <load-on-startup>1</load-on-startup>

      </servlet>

      <servlet-mapping>

        <servlet-name>CXFServlet</servlet-name>

        <url-pattern>/kservice/*</url-pattern>

      </servlet-mapping>

      <session-config>

        <session-timeout>10</session-timeout>

      </session-config>

    </web-app>

After deploying the above example, you can test it using any http compatible tool like curl, directly from you command line

    $ curl -v \
      -H 'Content-Type: text/plain' \
      -d '<batch-execution lookup="ksession1"> \
      <start-process processId="org.jbpm.sample.my-process" out-identifier = "processId"/> \
      </batch-execution>' \
      http://localhost:8080/jbpm-camel/kservice/rest/execute

The above execution will result in something similar to the following code snippet:

    HTTP/1.1 200 OK
    Content-Length: 131
    Server: Apache-Coyote/1.1
    Date: Mon, 13 Apr 2012 17:02:42 GMT
    Content-Type: text/plain
    Connection: close

    <?xml version='1.0' encoding='UTF-8'?><execution-results><result identifier="processId"><long>1</long></result></execution-results>

- PrevChapter 18. Flexible Processes
- Top of page
- Front page