Home > Enterprise Integration, JEE, Open Source, Spring Framework > Activiti 5 with Spring Integration 2.0 Mail Adapter

Activiti 5 with Spring Integration 2.0 Mail Adapter

Print Friendly Print Get a PDF version of this webpage PDF

activiti_logo Activiti is an open source BPM and workflow system. The first GA release is expected to be out next month i.e. Dec 2010. The roadmap of activiti looks very promising and also involvement of companies like SpringSource and MuleSoft can make it even more interesting. There are couple of good articles and tutorials available on the wiki to help you get started with activiti. To get a feel of the framework, instead of developing a simple hello world app, I thought of integrating activiti with Spring Integration. SpringSource team is working on this integration module and once that is in place some of the boilerplate code from my prototype would be cleaned up. The following blog post demonstrates the use of spring integration mail module with activiti.

Business Process:

For the sake of prototype, I created a defect tracking application. Users can send their complaints to a specific email address e.g. helpdesk@xyz.com. The application polls on helpdesk’s mailbox using spring integration mail module. Once email is received, a defect is created and workflow is initiated to handle this defect.

activiti-demo

Running the Demo:

The source code for the prototype is available at google code. Checkout the sources. Modify the database and mail configurations in activiti.properties. Run the app using embedded jetty server with mvn jetty:run. Run data.sql to create test users. Send a mail to the address configured in activiti.properties {gmail.username}. All defects are assigned by default to manager user. Login to the app using manager/password. You would see the defect in your task list for review. You can click on the review link, see the details of the defect and assign it to a different user (e.g. developer). Once you assign the defect to a different user, your task list would be empty :-) . Now login as developer/password to resolve the defect.

reviewDefect

resolveDefect

Understanding the Code:

Maven Dependencies:

		<!-- ACTIVITI DEPENDENCIES -->
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-engine</artifactId>
			<version>${activiti.version}</version>
		</dependency>
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-spring</artifactId>
			<version>${activiti.version}</version>
		</dependency>

Wiring it up with Spring:

	<!-- Activiti Beans -->
	<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"
		p:databaseType="${database}" p:dataSource-ref="dataSource"
		p:transactionManager-ref="transactionManager" p:dbSchemaStrategy="${db.schema.strategy}"
		p:jpaEntityManagerFactory-ref="entityManagerFactory"
		p:jpaCloseEntityManager="true" p:jpaHandleTransaction="true" />

	<bean id="repositoryService" factory-bean="processEngine"
		factory-method="getRepositoryService" />
	<bean id="runtimeService" factory-bean="processEngine"
		factory-method="getRuntimeService" />
	<bean id="taskService" factory-bean="processEngine"
		factory-method="getTaskService" />
	<bean id="historyService" factory-bean="processEngine"
		factory-method="getHistoryService" />
	<bean id="managementService" factory-bean="processEngine"
		factory-method="getManagementService" />

If you take a look at my previous blog post about jBPM, you would clearly see the simplicity in configurations with activiti.

Spring Integration Configurations:

	<!-- ========================================================= -->
	<!-- ===== Spring Integration Setup for Receiving Email Messages ===== -->
	<!-- ========================================================= -->

	<util:properties id="javaMailProperties">
		<prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
		<prop key="mail.imap.socketFactory.fallback">false</prop>
		<prop key="mail.store.protocol">imaps</prop>
		<prop key="mail.debug">false</prop>
	</util:properties>

	<int-mail:imap-idle-channel-adapter
		id="gmailAdapter"
		store-uri="imaps://${gmail.username}:${gmail.password}@imap.gmail.com:993/inbox"
		channel="gmailChannel" auto-startup="true" should-delete-messages="false"
		java-mail-properties="javaMailProperties" />

	<int:channel id="gmailChannel" />

	<int:service-activator id="messageActivator"
		input-channel="gmailChannel" ref="gmailMessageActivator" method="process">
	</int:service-activator>

Understanding Service Activator and DefectService:

The GmailMessageActivator bean receives the mime message. It extracts the information from the message and calls the DefectService to create the defect. In the current prototype, the process kick off is done in the DefectService. DefectService uses the activiti query API for dealing with tasks and process instances.

@Component("gmailMessageActivator")
public class GmailMessageActivator {

    @Autowired
    DefectService defectService;

    @Transactional(readOnly = false)
    public void process(MimeMessage mimeMessage) throws Exception {
        try {
            String[] fromHeaders = mimeMessage.getHeader("From");
            String from = "";
            if (fromHeaders != null && fromHeaders.length > 0) {
                from = fromHeaders[0];
            }
            Defect defect = new Defect();
            defect.setDescription(mimeMessage.getSubject());
            defect.setCreatedBy(from);
            defect.setAssignedTo("manager");
            defectService.createDefect(defect);
        }
        catch (MessagingException e) {
            throw new Exception("Exception occurred during message receiption ", e);
        }
    }
}

   //Note: checkout project for entire source

    @Autowired
    private DefectRepository defectRepository;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;

    @PostConstruct
    public void setupProcessDefinitions() {
        try {
            for (String processDefinition : processDefinitions) {
                repositoryService.createDeployment()
                        .addInputStream(processDefinition, new ClassPathResource(processDefinition).getInputStream())
                        .deploy();
            }
        }
        catch (Exception e) {
            throw new RuntimeException("An error occured while trying to deploy a process definition", e);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public Defect createDefect(Defect defect) {
        defect.setCreatedDate(new LocalDate());
        defect.setStatus(DefectStatus.NEW);
        Defect newDefect = defectRepository.save(defect);

        Map<String, Object> vars = new HashMap<String, Object>();
        vars.put("defectId", newDefect.getId());
        vars.put("assignee", defect.getAssignedTo());
        runtimeService.startProcessInstanceByKey(DEFECT_TRACKING_PROCESS_KEY, newDefect.getId().toString(), vars);
        return defect;
    }

Understanding BPMN2.0 constructs:

A user task is used to model work that is to be done by human. When process execution arrives at this point in the flow, a new task is created in the user’s task list.

		<userTask name="reviewDefect" id="reviewDefect">
			<documentation>
				The assignee will review the defect.
			</documentation>
			<humanPerformer>
				<resourceAssignmentExpression>
					<formalExpression>#{assignee}</formalExpression>
				</resourceAssignmentExpression>
			</humanPerformer>
		</userTask>

A service task is used to execute some business logic when process execution arrives at a particular point.

		<serviceTask id="findAssignee"
			activiti:class="net.arunoday.activiti.demo.handler.CheckAssignee" />

Conclusion:

In the above blog post, I demonstrated how to setup activiti and use it along with spring integration mail module. The configurations required to setup activiti are pretty simple. To get better understanding of the framework, its wise to quickly read the sources from activiti-engine module. Also, while you run the demo app, check the data in the activiti configuration tables and see how data flows from current tables to history tables after successful execution of the process. This data can be used to generate reports.

It would be interesting to see activiti getting feature rich and then answers to questions like “whether existing jBPM apps should continue with it or consider migrating to activiti?”, “whether new developments should be done with activiti or jBPM?” would come with ease :-) !!

  1. November 23rd, 2010 at 09:43 | #1

    Wrote a blog post #Activiti 5 with Spring Integration 2.0 Mail Adapter http://blog.aparnachaudhary.net/2010/11/... DZone Link: http://www.dzone.com/links/activiti_5_wi... #bpmn2
    via Twitoaster

  2. thejavadev
    thejavadev
    November 23rd, 2010 at 14:53 | #2

    @aparnachaudhary great post as always. Thanks for share :)
    via Twitoaster

  3. D.V.ArunKumar
    November 23rd, 2010 at 23:27 | #3

    hai
    this is arun. i want to integrate webservices in spring (jax-ws),jwsdp pack
    if u know pls send me a related example how to webservice integrate spring and how to access it.
    pls send as soon as possible

  4. Aparna Chaudhary
    November 25th, 2010 at 04:58 | #4

    Hi Arun,

    You can check Spring-Integration samples available at http://git.springsource.org/spring-integration/samples/trees/master

    Aparna

  5. Kris
    February 8th, 2011 at 21:02 | #5

    Nice blog, very helpful to get started on Activiti. Do we need to create all our application users in activiti database schema?
    Lets say we have 1000 users in existing application and we want to use activiti in one of the module to define a workflow. Is it good idea to run the Activiti database in seperate schema or do we need to create activiti schema also in the same application schema.

  6. Aparna Chaudhary
    February 11th, 2011 at 10:25 | #6

    @Kris

    No. Its not mandatory to create application users in activiti schema. That would be required if you use the IdentityService.

    About maintaining a different schema, well its a matter of taste. If your relational model is big, then I personally prefer maintaining a separate schema for application specific objects. But again, its not mandatory, you can also maintain a single schema for application objects and activiti related objects.

  7. thetoolman
    March 15th, 2011 at 08:38 | #7

    Hey Aparna all the way from NZ!

    Thought I’d note that you can also load BPMN XML with your context.xml, instead of programatically in the :

  8. thetoolman
    March 15th, 2011 at 08:39 | #8

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    <property name="dataSource" ref="dataSource"></property>
    <property name="transactionManager" ref="transactionManager" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="jobExecutorActivate" value="false" />

    <property name="deploymentResources" value="classpath*:/bpmn/*.bpmn20.xml" />

    </bean>

  9. Aparna Chaudhary
    March 15th, 2011 at 09:30 | #9

    @Toolman, Nice to hear from you after a long time. Yes, the resources can be loaded directly in the configurations. Thanks for your comment.

  10. Siva
    May 13th, 2011 at 21:56 | #10

    Thanks a ton. this is exactly what I was looking for..

  11. May 30th, 2011 at 21:08 | #11

    Thanks. This is was a good post unleasing the dual force of Activity and Spring Integration

  12. June 7th, 2011 at 09:26 | #12

    Wow! What a great post! I’m sorry I didn’t see this earlier :-) You’ve done a lot of great things here, and the combination of Spring Integration and Activiti is very formidable. If you have a second, perhaps you could look at the Spring Integration Activiti adapter (in the git.springsource.org/spring-integration sandbox) which is specifically meant to solve some of the problems you’ve solved here. This adapter will be in Spring Integration 2.1. Keep up the great work and be sure to feedback on JIRA or the forums if there’s anything you feel is not being addressed. ;-)

  13. Sanket
    October 19th, 2011 at 22:17 | #13

    Many thanks to Aparna for such a nice post. Josh, Any idea when will Activity adapter make it to 2.1? I dont find it in 2.1.M2. @Josh Long

  1. No trackbacks yet.
Get Adobe Flash playerPlugin by wpburn.com wordpress themes