Activiti 5 with Spring Integration 2.0 Mail Adapter
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.

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.


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


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
@aparnachaudhary great post as always. Thanks for share
via Twitoaster
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
Hi Arun,
You can check Spring-Integration samples available at http://git.springsource.org/spring-integration/samples/trees/master
Aparna
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.
@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.
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 :
<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>
@Toolman, Nice to hear from you after a long time. Yes, the resources can be loaded directly in the configurations. Thanks for your comment.
Thanks a ton. this is exactly what I was looking for..
Thanks. This is was a good post unleasing the dual force of Activity and Spring Integration
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.
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