Currently Being Moderated

Spring-Jbpm-JSF-Example

VERSION 10

Created on: Jul 1, 2008 12:52 AM by fernando.deleon@gmail.com - Last Modified:  Jul 4, 2008 7:13 PM by fernando.deleon@gmail.com

Spring  Jbpm  JSF Maven Project Example

-


This is a simple example of an app that runs a simple process and shows how to integrate Spring with Jbpm

 

The view technology chosen is JSF and the database chosen is MySql.

 

Requirements

The basic requirement is that you have running a MySql database that connects to your schema.

 

House Cleaning

The application described can be downloaded (maven project) and then you can mvn clean install to create

 

your simpleForms.war and deploy it on your Tomcat server (i am running on 6.0.9)

 

Your may need to manually install the jbpm lib files jbpm-3.1.2.jar and jbpm-identity-3.1.2.jar for your

 

maven to get them correctly.  Then modify the pom file accordingly that is,


<dependency>
            <groupId>jboss</groupId>
            <artifactId>jbpm</artifactId>
            <version>3.1.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>jboss</groupId>
            <artifactId>jbpm-identity</artifactId>
            <version>3.1.2</version>
            <scope>compile</scope>
        </dependency>

 

Setting your infrastructure

JBPM Tables

For starters we need to have the jbpm tables into your MySql database.

 

The easiest way I found is to let hibernate create them for you: (Using the attached project)

  1. grab a hold on WEB-INF/jdbc.properties file and modify the required fields, save the file.

    1. That is, make sure you modified username and password fields

  2. Open up WEB-INF/applicationWebContext.xml and uncomment <prop key="hibernate.hbm2ddl.auto">create</prop>

located under jbpmSessionFactory bean, save the file.

  1. On your terminal window run mvn clean install

  2. Fetch the simpleForms.war from the target directory created by maven

  3. Copy and paste the simpleForms.war into your tomcat webapps directory

  4. Start up your Tomcat server and make sure it starts up successfully.

  5. Check against your database (I use DBVisualizer or any other database viewer) and make

sure you can see a large array of tables created eg JBPM_PROCESSDEFINITION etc..

  1. Shut down your Tomcat Server, go back to your project and comment out the <prop key="hibernate.hbm2ddl.auto">create</prop> in your WEB-INF/applicationWebContext.xml file

 

Integrating Spring into the mix

This will give you an explanation on how Spring is wired into the application and allows for easier management

 

of your processes.

web.xml

Things to note for

  • We will currently use only one spring application context file

 

(look under <param-name>contextConfigLocation</param-name>).

 

 

  • We use JSF 1.1 and is configured in the web.xml file with only one faces-config file

  • The Faces Servlet uses the url pattern of .faces meaning our applyHolidayForm.jsp maps to

 

   applyHolidayForm.faces

 

applicationWebContext.xml

The way Spring knows of our process definition location is via the holidayProcessDefinition bean

 

<!-- holiday form process -->
    <bean id="holidayProcessDefinition" class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
        <property name="definitionLocation" value="classpath:/holidaydefinition.xml"></property>
    </bean>

 

jbpmTemplate is the main helper bean that you use to interface to your process

 

it has references to the holidayProcessDefinition bean and to the jbpmConfig bean

 

<bean id="jbpmTemplate" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
        <constructor-arg index="0" ref="jbpmConfig"></constructor-arg>
        <constructor-arg index="1" ref="holidayProcessDefinition"></constructor-arg>
        <property name="hibernateTemplate" ref="hibernateTemplate"></property>
    </bean>

 

jbpmConfig contains information of the jbpmSessionFactory and the jbpm.cfg.xml file

<bean id="jbpmConfig" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
        <property name="sessionFactory" ref="jbpmSessionFactory"></property>
        <property name="configuration" value="classpath:/jbpm.cfg.xml"></property>
        <property name="processDefinitions">
            <list>
                <ref local="holidayProcessDefinition"></ref>
            </list>
        </property>
        <property name="createSchema" value="false"></property>
    </bean>

 

jbpmSessionFactory manages the session note that its name MUST be sessionFactory otherwise it wont

 

be use by the openSessionInViewInterceptor

 

the sessionFactory also knows about the hibernate mapping tables via hibernate.cfg.xml file and knows

 

about database connectivity via dataSource bean

<bean id="jbpmSessionFactory" name="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation">
            <value>classpath:/hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <!-- <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> -->
                <!-- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> -->
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <!-- Create/update the database tables automatically when the JVM starts up -->
                <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->                
                <prop key="hibernate.cache.use_query_cache">false</prop> -->
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
                <!-- Turn batching off for better error messages under PostgreSQL 
                <prop key="hibernate.jdbc.batch_size">0</prop> -->
            </props>
        </property>
    </bean>

 

OpenSessionInViewInterceptor manages hibernate session  a la Spring, each request is intercepted via the

 

OpenSessionInViewFilter declared in web.xml note that is autowire by name

 

meaning that jbpmSessionFactory bean must have a name of sessionFactory

<bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" autowire="byName"></bean>

 

txManager manages the hibernate transactions and is used by our DAOs / Service beans it has

 

knowledge of the sessionFactory too.

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        <property name="sessionFactory" ref="jbpmSessionFactory"></property>
    </bean>

 

Setting up our DAOs beans

 

We first develop our DAO target bean which has autowire by name.  This means that our actual DAO needs to have

 

a reference to JbpmTemplate bean with a property name of jbpmTemplate.

 

Thus in code it will look

private JbpmTemplate jbpmTemplate;

with its corresponding getter and setters

 

Our DAO is called ProcessFormDAO so to create our target DAO bean we do :

<bean id="processFormDAOTarget" class="au.com.qtc.simpleForms.jbpm.dao.ProcessFormDAO" autowire="byName"></bean>

JSF managed beans or in a real live application our manager beans will have a reference not to

 

processFormDAOTarget but to processFormDAO and this bean is set up as follows:

<bean id="processFormDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager" ref="txManager"></property>
       <property name="target" ref="processFormDAOTarget"></property>
       <property name="proxyTargetClass" value="true" ></property>
       <property name="transactionAttributes">
         <props>
           <prop key="*">PROPAGATION_NESTED</prop>
         </props>
       </property>
     </bean>

Note that it has a reference to :

  • txManager bean

  • processFormDAOTarget bean

And we allow for propagation nested.

 

Setting up email notification

 

At the moment I havent caught up with how do you let Jbpm to send email notifications

 

So for the meantime you can use Spring Mail support service.

 

The basic idea is this.  I want an email notification to be triggered upon entering a decision node. 

 

In essence after doing my decision logic in the node I want to send a corresponding email that will inform the

 

originator of the outcome of the decision.

 

However I wired up my email using Spring and as such Spring needs to load the email manager bean on its

 

context loader.  So how to let my decision node know about my email manager in Spring?

 

Initially the process definition looked like this:

<decision name="evaluateLeave">
        <handler class="au.com.qtc.simpleForms.jbpm.decision.EvaluateLeaveDecisionHandler"></handler>
        <transition to="end" name="yes">
             <action class="au.com.qtc.simpleForms.jbpm.action.NotifyAboutLeaveActionHandler"></action>
        </transition>
        <transition to="giveDonuts" name="no">
            <action class="au.com.qtc.simpleForms.jbpm.action.NotifyAboutLeaveActionHandler"></action>
         </transition>
    </decision>  

I want my NotifyAboutLeaveActionHandler to know about my mail manager Spring bean.

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
               <property name="host" value="mail.optusnet.com.au"></property>
           </bean>
           
           <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
               <property name="from" value="simpleForms@nando.com"></property>
           </bean>
           
           <bean id="notifyEmailManager" class="au.com.qtc.simpleForms.mail.SimpleMailManager">
               <property name="mailSender" ref="mailSender"></property>
               <property name="templateMessage" ref="templateMessage"></property>
           </bean>

I want to inject notifyEmailManager into the NotifyAboutLeaveActionHanlder object.

 

 

This is the solution:

 

 <decision name="evaluateLeave">
        <handler class="au.com.qtc.simpleForms.jbpm.decision.EvaluateLeaveDecisionHandler"></handler>
        <transition to="end" name="yes">
            <action name="notificationAction" config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandlerProxy">
                <targetBean>notifyAboutLeaveActionHandler</targetBean>
            </action>
        </transition>
        <transition to="giveDonuts" name="no">
            <action name="notificationAction" config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandlerProxy">
                <targetBean>notifyAboutLeaveActionHandler</targetBean>
            </action>
         </transition>
    </decision>

Note the notificationAction nae refers to a spring module JbpmHandlerProxy bean.  which as the name suggest

 

acts as a proxy to my notifyAboutLeaveActionHandler bean.

 

So what is this notifyAboutLeaveActinoHandler bean coming from? you may ask!

 

This is where spring injection is made possible!

 

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
               <property name="host" value="mail.optusnet.com.au"></property>
           </bean>
           
           <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
               <property name="from" value="simpleForms@nando.com"></property>
           </bean>
           
           <bean id="notifyEmailManager" class="au.com.qtc.simpleForms.mail.SimpleMailManager">
               <property name="mailSender" ref="mailSender"></property>
               <property name="templateMessage" ref="templateMessage"></property>
           </bean>
           
           <bean id="notifyAboutLeaveActionHandler" class="au.com.qtc.simpleForms.jbpm.action.NotifyAboutLeaveActionHandler">
               <property name="mailManager" ref="notifyEmailManager"></property>
           </bean>

Notice now that my notifyAboutLeaveActionHandler is now a Spring bean loaded in the same Spring loader context

 

as such it can now inject any Spring declared beans.  As such I am now able to inject the appropriate

 

mailManager bean.

 

Thus in code the notifyAboutLeaveActionHandler has the following :


    private MailManager mailManager;

    public MailManager getMailManager() {
        return mailManager;
    }

    public void setMailManager(MailManager mailManager) {
        this.mailManager = mailManager;
    }
...

So it is now possible to have a preloaded instance of mailManager inside my NotifyAboutLeaveActionHandler.

 

 

 

 

 

 

 

 

 

Attachments:
Average User Rating
(0 ratings)




There are no comments on this article

More Like This

  • Retrieving data ...

More by fernando.deleon@gmail.com