Activiti BPM Tutorial – Web Services

Start Activiti REST Server in Main

package com.nuke.main;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.identity.User;
import org.activiti.rest.service.application.ActivitiRestServicesApplication;
import org.restlet.Component;
import org.restlet.data.Protocol;

import com.nuke.activiti.CustomProcessEngineConfig;

public class ExpenseProcessRESTMain {
	
	private static final String filename = "/Users/tmichels/Documents/workspace-sts-3.5.0.M21/nucleus-workflow/src/main/resources/diagrams/expense_process.bpmn";
	
	public static void main(String[] args) throws Exception {
		ProcessEngineConfiguration engineConfig = CustomProcessEngineConfig.createStandaloneInMemProcessEngineConfiguration();
	    ProcessEngine processEngine = engineConfig.buildProcessEngine();
	    
	    User newUser = processEngine.getIdentityService().newUser("kermit");
	    newUser.setPassword("kermit");
	    processEngine.getIdentityService().saveUser(newUser);

	    processEngine.getRepositoryService().createDeployment()
	    	.addInputStream("expense_process.bpmn",
				new FileInputStream(filename)).deploy();
	    
	    Map variableMap1 = new HashMap();
		variableMap1.put("employee", "Jack");
		variableMap1.put("amount", 111);
		
		processEngine.getRuntimeService().startProcessInstanceByKey("expenseProcess", variableMap1);
		
		Component component = new Component();
	    component.getServers().add(Protocol.HTTP, 8182);
	    ActivitiRestServicesApplication restApplication = new ActivitiRestServicesApplication();
	    // Attach the Activiti REST-application and start
	    component.getDefaultHost().attach("/activiti-rest",
	    		restApplication);
	    component.start();
	}
}

Create Activiti REST Server in web.xml

<?xml version="1.0" encoding="UTF-8"?>  
<web-app id="WebApp_ID" version="2.4"  
            xmlns="http://java.sun.com/xml/ns/j2ee"  
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  
                 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  
  <display-name>Activiti REST</display-name>
   
  <listener>
    <listener-class>org.activiti.rest.common.servlet.ActivitiServletContextListener</listener-class>
  </listener> 
  
  <!-- Restlet adapter -->  
  <servlet>  
    <servlet-name>RestletServlet</servlet-name>  
    <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
    <init-param>
      <!-- Application class name -->
      <param-name>org.restlet.application</param-name>
      <param-value>org.activiti.rest.service.application.ActivitiRestServicesApplication</param-value>
    </init-param>
  </servlet>
  
  <!-- Catch all requests -->  
  <servlet-mapping>  
    <servlet-name>RestletServlet</servlet-name>  
    <url-pattern>/service/*</url-pattern>  
  </servlet-mapping>  
</web-app>

Activiti REST Client

package com.nuke.activiti.client;

import java.io.IOException;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ClientResource;

public class ActivitiRestClient {

	private static String REST_URI = "http://localhost:8081/activiti-rest-api/service";
	private static Logger logger = Logger.getLogger(ActivitiRestClient.class);

	private static ClientResource getClientResource(String uri) {
		ClientResource clientResource = new ClientResource(uri);
		clientResource.setChallengeResponse(ChallengeScheme.HTTP_BASIC,
				"kermit", "kermit");
		return clientResource;
	}

	public static String getUnderwritingQueueProcessId() throws IOException,
			JSONException {
		String uri = REST_URI + "/repository/process-definitions";
		System.out.println("URI: " + uri);
		Representation response = getClientResource(uri).get(
				MediaType.APPLICATION_JSON);
		JSONObject object = new JSONObject(response.getText());
		if (object != null) {
			JSONArray arr = (JSONArray) object.get("data");
			for (int i = 0; i < arr.length(); i++) {
				JSONObject jsonObject = (JSONObject) arr.get(i);
				if (jsonObject.get("key").equals("underwritingQueue")) {
					logger.info("Returning processDefinitionId "
							+ jsonObject.get("id"));
					return (String) jsonObject.get("id");
				}
			}
		}
		return null;
	}

	public static String addLoanToUnderwritingQueue(String processDefinitionId)
			throws Exception {
		String uri = REST_URI + "/runtime/process-instances";
		JSONStringer jsRequest = new JSONStringer();
		jsRequest.object().key("processDefinitionId")
				.value(processDefinitionId).key("variables").array().object()
				.key("name").value("LoanId").key("value").value("132312")
				.endObject().endArray();
		jsRequest.endObject();
		Representation rep = new StringRepresentation(jsRequest.toString(),
				MediaType.APPLICATION_JSON);
		System.out.println("REP: " + rep.toString());
		JSONObject jsObj = new JSONObject(getClientResource(uri).post(rep)
				.getText());
		logger.info("Returning processId " + jsObj.getString("id"));
		return jsObj.getString("id");
	}

	public static String getQueueTask(String processInstanceId)
			throws Exception {
		String uri = REST_URI + "/tasks?candidate=kermit";
		Representation response = getClientResource(uri).get(
				MediaType.APPLICATION_JSON);
		JSONObject object = new JSONObject(response.getText());
		if (object != null) {
			JSONArray arr = (JSONArray) object.get("data");
			for (int i = 0; i < arr.length(); i++) {
				JSONObject ob = (JSONObject) arr.get(i);
				if (ob.get("processInstanceId").equals(processInstanceId)) {
					logger.info("Returning taskId " + ob.get("id"));
					return (String) ob.get("id");
				}
			}
		}
		return null;
	}

	public static String claimQueueTask(String taskId) throws Exception {
		String uri = REST_URI + "/task/" + taskId + "/claim";
		Representation response = getClientResource(uri).put("{}",
				MediaType.APPLICATION_JSON);
		JSONObject object = new JSONObject(response.getText());
		System.out.println("OBJECT: " + object.toString());
		logger.info("Claimed task " + taskId + " " + object.get("success"));
		return object.get("success").toString();
	}
	
	public static String completeTask(String taskId)
			throws Exception {
		String uri = REST_URI + "/task/" + taskId + "/complete";
		Representation response = getClientResource(uri).put(
				"{disposition:complete}", MediaType.APPLICATION_JSON);
		JSONObject object = new JSONObject(response.getText());
		logger.info("Completed task " + taskId + " " + object.getString("success"));
		return object.getString("success");
	}
	
	@SuppressWarnings("unused")
	public static int getTasks(String status, String candidate)
			throws Exception {
		String uri = REST_URI + "/tasks?" + status + "=" + candidate;
		Representation response = getClientResource(uri).get(
				MediaType.APPLICATION_JSON);
		JSONObject object = new JSONObject(response.getText());
		if (object != null) {
			JSONArray arr = (JSONArray) object.get("data");
			logger.info("Tasklist " + candidate + " " + status + " size " + arr.length());
			return arr.length();
		}
		return -1;
	}
}

Activiti REST Client Test

package com.nuke.activiti.client;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.junit.Test;

import com.nuke.activiti.common.AbstractTest;


public class ActivitiRestClientTest extends AbstractTest {
	
	@Test
	public void restAPITest() throws Exception {
		String underwritingLoanDefinitionId = ActivitiRestClient.getUnderwritingQueueProcessId();
		assertNotNull(underwritingLoanDefinitionId);
		String processInstanceId = ActivitiRestClient.addLoanToUnderwritingQueue(underwritingLoanDefinitionId);
		assertNotNull(processInstanceId);
		String taskId = ActivitiRestClient.getQueueTask(processInstanceId);
		assertNotNull(taskId);
		assertEquals("true", ActivitiRestClient.claimQueueTask(taskId));
		assertEquals(4, ActivitiRestClient.getTasks("candidate","kermit"));
		assertEquals(6, ActivitiRestClient.getTasks("assignee","kermit"));
		assertEquals("true", ActivitiRestClient.completeTask(taskId));
		assertEquals(0, ActivitiRestClient.getTasks("assignee","kermit"));
	}
}

Activiti BPM Tutorial – LDAP

1.1 LDAP Configuration using XML
1.2 LDAP Configuration XML User Test
1.3 LDAP Configuration XML Group Test
2.1 LDAP Configuration using Annotations
2.2 LDAP Configuration Annotations User Test
2.3 LDAP Configuration Annotations Group Test

1.1 LDAP Configuration using XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.springframework.org/schema/beans
				http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  
    <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />
    <property name="history" value="full" />
    <property name="databaseSchemaUpdate" value="true" />
    
    <property name="jobExecutorActivate" value="true" />
    
    <property name="configurators">
          <list>
              <bean class="org.activiti.ldap.LDAPConfigurator">
              
                <!-- Server connection params -->
                <property name="server" value="ldap://localhost" />
                <property name="port" value="10389" />
                <property name="user" value="uid=admin,ou=system" />
                <property name="password" value="secret" />
                
                <!-- Query params -->
                <property name="baseDn" value="" /> 
                <property name="queryUserByUserId" value="(&amp;(objectClass=inetOrgPerson)(uid={0}))" />
                <property name="queryUserByFullNameLike" value="(&amp;(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))" />
                <property name="queryGroupsForUser" value="(&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />
                
                <!-- Attribute config -->
                <property name="userIdAttribute" value="uid" />
                <property name="userFirstNameAttribute" value="cn" />
                <property name="userLastNameAttribute" value="sn" />
                
                <property name="groupIdAttribute" value="cn" />
                <property name="groupNameAttribute" value="cn" />
                
              </bean>
          </list>
      </property>
  </bean>
  
</beans>

1.2 LDAP Configuration XML Test

package com.nuke.activiti.ldap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.activiti.engine.identity.User;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;

import com.nuke.activiti.common.AbstractTest;

public class LDAPUserTest extends AbstractTest {

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule("activiti.cfg.xml");

	@Test
	public void testCheckLogin() {
		boolean validated = activitiRule.getIdentityService().checkPassword("kermit", "kermit");
		assertTrue(validated);
	}
	
	@Test
	public void testCheckLoginFailure() {
		boolean validated = activitiRule.getIdentityService().checkPassword("kermit", "kermit2");
		assertFalse(validated);
	}
	
	@Test
	public void findUserById() throws Exception {
		User user = activitiRule.getIdentityService().createUserQuery().userId("kermit").singleResult();
		assertNotNull(user);
		assertEquals("kermit", user.getId());
		assertEquals("kermit", user.getLastName());
	}
}

1.3 LDAP Configuration XML Group Test

package com.nuke.activiti.ldap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.List;

import org.activiti.engine.identity.Group;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;

import com.nuke.activiti.common.AbstractTest;

public class LDAPGroupTest extends AbstractTest {

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule("activiti.cfg.xml");
		
	@Test
	public void findGroupByMember() throws Exception {
		List<Group> groupList = activitiRule.getIdentityService().createGroupQuery().groupMember("kermit").list();
		for (Group group : groupList){
			System.out.println(group.getName());
		}
		assertNotNull(groupList);
		assertEquals(3, groupList.size());
	}

}

2.1 LDAP Configuration using Annotations

package com.nuke.ldap;

import org.activiti.ldap.LDAPConfigurator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
public class LDAPConfiguration {

	@Bean
	public LDAPConfigurator LDAPConfig(){
		LDAPConfigurator ldapConfig = new LDAPConfigurator();
		
		ldapConfig.setServer("localhost");
		ldapConfig.setPort(10389);
		ldapConfig.setUser("uid=admin,ou=system");
		ldapConfig.setPassword("secret");
		
		ldapConfig.setBaseDn("");
		ldapConfig.setQueryUserByUserId("(&(objectClass=inetOrgPerson)(uid={0}))");
		ldapConfig.setQueryUserByFullNameLike("(&(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))");
		ldapConfig.setQueryGroupsForUser("(&(objectClass=groupOfUniqueNames)(uniqueMember={0}))");
		
		ldapConfig.setUserIdAttribute("uid");
		ldapConfig.setUserFirstNameAttribute("cn");
		ldapConfig.setUserLastNameAttribute("sn");
		
		ldapConfig.setGroupIdAttribute("cn");
		ldapConfig.setGroupNameAttribute("cn");
		
		return ldapConfig;
	}
}
package com.nuke.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.cfg.ProcessEngineConfigurator;
import org.activiti.engine.impl.HistoryServiceImpl;
import org.activiti.engine.impl.IdentityServiceImpl;
import org.activiti.engine.impl.ManagementServiceImpl;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.TaskServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.ldap.LDAPConfigurator;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.annotations.AbstractActivitiConfigurer;
import org.activiti.spring.annotations.EnableActiviti;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.nuke.ldap.LDAPConfiguration;

@Configuration
@EnableActiviti
@EnableTransactionManagement(proxyTargetClass = true)
@Import({LDAPConfiguration.class})
//@PropertySource("file:conf/lc-merged.properties")
public class ActivitConfiguration {
 
	@Autowired
	LDAPConfigurator ldapConfigurator;
	
    @Bean
    public DataSource inMemoryDataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setUsername("sa");
        basicDataSource.setUrl("jdbc:h2:mem:activiti");
        basicDataSource.setDefaultAutoCommit(false);
        basicDataSource.setDriverClassName(org.h2.Driver.class.getName());
        basicDataSource.setPassword("");
        return basicDataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource inMemoryDataSource) {
	  LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
      localContainerEntityManagerFactoryBean.setDataSource(inMemoryDataSource);
      localContainerEntityManagerFactoryBean.setPackagesToScan(new String[]{"com.nuke.model"});
      localContainerEntityManagerFactoryBean.setPersistenceUnitName("nuke");
      HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
      
      jpaVendorAdapter.setGenerateDdl(false);
      jpaVendorAdapter.setShowSql(false);
      jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
      localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
      return localContainerEntityManagerFactoryBean;
    }

    @Bean
    public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean);
    } 
    
       
	@Value("${LC_NUKE_MAIL_HOST}")
	private String mailHost;
	@Value("${LC_NUKE_MAIL_USERNAME}")
	private String mailUsername;
	@Value("${LC_NUKE_MAIL_PASSWORD}")
	private String mailServerPassword;
	
    @Bean
    public AbstractActivitiConfigurer abstractActivitiConfigurer(final EntityManagerFactory entityManagerFactoryBean, final PlatformTransactionManager jpaTransactionManager) {
        return new AbstractActivitiConfigurer() {
            @Override
            public void postProcessSpringProcessEngineConfiguration(SpringProcessEngineConfiguration engine) {
            	engine.setDatabaseType("h2");
            	engine.setDataSource(inMemoryDataSource());
                engine.setTransactionManager(jpaTransactionManager);
                engine.setJpaEntityManagerFactory(entityManagerFactoryBean);
                engine.setJpaHandleTransaction(true);
                engine.setJobExecutorActivate(true);
                engine.setJpaCloseEntityManager(false);
                engine.setMailServerDefaultFrom("nucleus@lc.com");
                engine.setMailServerHost(mailHost);
                engine.setMailServerPort(587);
                engine.setMailServerUsername(mailUsername);
                engine.setMailServerPassword(mailServerPassword);
                engine.setMailServerUseSSL(true);
                engine.setMailServerUseTLS(true);
                engine.setRepositoryService(repositoryService());
                engine.setTaskService(taskService());
                engine.setManagementService(managementService());
                engine.setRuntimeService(runtimeService());
                engine.setIdentityService(identityService());
                engine.setHistoryService(historyService());
                engine.setHistoryLevel(HistoryLevel.AUDIT);
                Resource[] processResources = new Resource[1] ;
                Resource underwritingQueueProcess = new ClassPathResource("diagrams/underwriting_queue.bpmn");
                processResources[0]=underwritingQueueProcess;
                engine.setDeploymentResources(processResources);
                engine.setConfigurators(new ArrayList<ProcessEngineConfigurator>(Arrays.asList(ldapConfigurator)));
                engine.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            }
        };
    }
    
    @Bean
    public RepositoryServiceImpl repositoryService(){
    	RepositoryServiceImpl repositoryService = new RepositoryServiceImpl();
    	return repositoryService;
    }
    
    @Bean
    public TaskServiceImpl taskService(){
    	TaskServiceImpl taskService = new TaskServiceImpl();
    	return taskService;
    }
    
    @Bean
    public ManagementServiceImpl managementService(){
    	ManagementServiceImpl managementService = new ManagementServiceImpl();
    	return managementService;
    }
    
    @Bean
    public RuntimeServiceImpl runtimeService(){
    	RuntimeServiceImpl runtimeService = new RuntimeServiceImpl();
    	return runtimeService;
    }
    
    @Bean
    public HistoryServiceImpl historyService(){
    	HistoryServiceImpl historyService = new HistoryServiceImpl();
    	return historyService;
    }
    
    @Bean
    public IdentityServiceImpl identityService(){
    	IdentityServiceImpl identityService = new IdentityServiceImpl();
    	return identityService;
    }
    
    @Bean
    public ActivitiRule activityRule(ProcessEngineConfigurationImpl abstractActivitiConfigurer){
    	ActivitiRule activityRule = new ActivitiRule();
    	activityRule.setProcessEngineConfiguration(abstractActivitiConfigurer);
    	return activityRule;
    }
}

2.2 LDAP Configuration Annotations User Test

package com.nuke.activiti.ldap;

import static org.junit.Assert.*;

import org.activiti.engine.identity.User;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.nuke.config.ActivitConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=ActivitConfiguration.class)
public class SpringLDAPUserTest {

	@Autowired
	@Rule
	public ActivitiRule activitiSpringRule;
	
	@Test
	public void testCheckLogin() {
		boolean validated = activitiSpringRule.getIdentityService().checkPassword("kermit", "kermit");
		assertTrue(validated);
	}
	
	@Test
	public void testCheckLoginFailure() {
		boolean validated = activitiSpringRule.getIdentityService().checkPassword("kermit", "kermit2");
		assertFalse(validated);
	}
	
	@Test
	public void findUserById() throws Exception {
		User user = activitiSpringRule.getIdentityService().createUserQuery().userId("kermit").singleResult();
		assertNotNull(user);
		assertEquals("kermit", user.getId());
		assertEquals("kermit", user.getLastName());
	}

}

2.3 LDAP Configuration Annotations Group Test

package com.nuke.activiti.ldap;

import static org.junit.Assert.*;

import java.util.List;

import org.activiti.engine.identity.Group;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.nuke.config.ActivitConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=ActivitConfiguration.class)
public class SpringLDAPGroupTest {

	@Autowired
	@Rule
	public ActivitiRule activitiSpringRule;
	
	@Test
	public void findGroupByMember() throws Exception {
		List<Group> groupList = activitiSpringRule.getIdentityService().createGroupQuery().groupMember("kermit").list();
		for (Group group : groupList){
			System.out.println(group.getName());
		}
		assertNotNull(groupList);
		assertEquals(3, groupList.size());
	}
}

Activiti BPM Tutorial – Spring Configuration

Activiti Spring Configuration
1. Activiti Configuration using XML
1.1 Activiti Configuration XML Test
2. Activiti Configuration using Annotations
2.1 Activiti Configuration Annotation Test

1. Activiti Configuration using XML

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans    
                           http://www.springframework.org/schema/beans/spring-beans.xsd 
                           http://www.springframework.org/schema/context  
                           http://www.springframework.org/schema/context/spring-context-2.5.xsd 
                           http://www.springframework.org/schema/tx       
                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
			<property name="driverClass" value="org.h2.Driver" />
			<property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
			<property name="username" value="sa" />
			<property name="password" value="" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
		<property name="databaseType" value="h2" />
		<property name="dataSource" ref="dataSource" />
		<property name="transactionManager" ref="transactionManager" />
		<property name="databaseSchemaUpdate" value="true" />
		<property name="deploymentResources"
			value="classpath*:diagrams/underwriting_queue.bpmn" />
		<property name="history" value="audit" />
		<property name="jobExecutorActivate" value="false" />
	</bean>

	<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
		<property name="processEngineConfiguration" ref="processEngineConfiguration" />
	</bean>

	<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" />
</beans>

1.1 Activiti Configuration XML Test

package com.nuke.activiti.spring;

import static org.junit.Assert.assertEquals;

import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.nuke.activiti.common.AbstractTest;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-test-application-context.xml")
public class SpringTest extends AbstractTest {

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	private TaskService taskService;

	@Test
	public void simpleProcessTest() {
		Map<String, Object> variableMap = new HashMap<String, Object>();
		variableMap.put("LoanId", 123456789);
		runtimeService.startProcessInstanceByKey("underwritingQueue", variableMap);
		Task task = taskService.createTaskQuery().singleResult();
		assertEquals("Unassigned Loan", task.getName());
		taskService.complete(task.getId());
		assertEquals(1, runtimeService.createProcessInstanceQuery().count());
	}
}

2. Activiti Configuration using Annotations

package com.nuke.config;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.HistoryServiceImpl;
import org.activiti.engine.impl.ManagementServiceImpl;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.TaskServiceImpl;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.annotations.AbstractActivitiConfigurer;
import org.activiti.spring.annotations.EnableActiviti;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.nuke.ldap.LDAPConnectionParams;
import com.nuke.ldap.LDAPGroupManagerFactory;
import com.nuke.ldap.LDAPUserManagerFactory;

@Configuration
@EnableActiviti
@EnableTransactionManagement(proxyTargetClass = true)
//@PropertySource("file:conf/lc-merged.properties")
public class ActivitConfiguration {
 
    @Bean
    public DataSource inMemoryDataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setUsername("sa");
        basicDataSource.setUrl("jdbc:h2:mem:activiti");
        basicDataSource.setDefaultAutoCommit(false);
        basicDataSource.setDriverClassName(org.h2.Driver.class.getName());
        basicDataSource.setPassword("");
        return basicDataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource inMemoryDataSource) {
	  LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
      localContainerEntityManagerFactoryBean.setDataSource(inMemoryDataSource);
      localContainerEntityManagerFactoryBean.setPackagesToScan(new String[]{"com.nuke.model"});
      localContainerEntityManagerFactoryBean.setPersistenceUnitName("nuke");
      HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
      
      jpaVendorAdapter.setGenerateDdl(false);
      jpaVendorAdapter.setShowSql(false);
      jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
      localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
      return localContainerEntityManagerFactoryBean;
    }

    @Bean
    public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean);
    } 
    
    @Value("${LC_NUKE_LDAP_URL:localhost}")
	private String ldapServer;
	@Value("${LC_NUKE_LDAP_PORT}")
	private String ldapPort;
	@Value("${LC_NUKE_LDAP_USERNAME:uid=admin,ou=system}")
	private String ldapUser;
	@Value("${LC_NUKE_LDAP_PASSWORD:secret}")
	private String ldapPassword;
	
	@Bean
	public LDAPConnectionParams ldapConnection(){
		LDAPConnectionParams ldapConnection = new LDAPConnectionParams();
		ldapConnection.setLdapServer(ldapServer);
		ldapConnection.setLdapPort(10389);
		ldapConnection.setLdapUser(ldapUser);
		ldapConnection.setLdapPassword(ldapPassword);
		return ldapConnection;
	}
    
    
	@Value("${LC_NUKE_MAIL_HOST}")
	private String mailHost;
	@Value("${LC_NUKE_MAIL_USERNAME}")
	private String mailUsername;
	@Value("${LC_NUKE_MAIL_PASSWORD}")
	private String mailServerPassword;
	
    @Bean
    public AbstractActivitiConfigurer abstractActivitiConfigurer(final EntityManagerFactory entityManagerFactoryBean, final PlatformTransactionManager jpaTransactionManager) {
        return new AbstractActivitiConfigurer() {
            @Override
            public void postProcessSpringProcessEngineConfiguration(SpringProcessEngineConfiguration engine) {
            	engine.setDatabaseType("h2");
            	engine.setDataSource(inMemoryDataSource());
                engine.setTransactionManager(jpaTransactionManager);
                engine.setJpaEntityManagerFactory(entityManagerFactoryBean);
                engine.setJpaHandleTransaction(true);
                engine.setJobExecutorActivate(true);
                engine.setJpaCloseEntityManager(false);
                engine.setMailServerDefaultFrom("nucleus@lc.com");
                engine.setMailServerHost(mailHost);
                engine.setMailServerPort(587);
                engine.setMailServerUsername(mailUsername);
                engine.setMailServerPassword(mailServerPassword);
                engine.setMailServerUseSSL(true);
                engine.setMailServerUseTLS(true);
                engine.setRepositoryService(repositoryService());
                engine.setTaskService(taskService());
                engine.setManagementService(managementService());
                engine.setRuntimeService(runtimeService());
                engine.setHistoryService(historyService());
                engine.setHistoryLevel(HistoryLevel.AUDIT);
                Resource[] processResources = new Resource[1] ;
                Resource underwritingQueueProcess = new ClassPathResource("diagrams/underwriting_queue.bpmn");
                processResources[0]=underwritingQueueProcess;
                engine.setDeploymentResources(processResources);
                List<SessionFactory> customSessionFactories = new ArrayList<SessionFactory>();
                customSessionFactories.add(new LDAPGroupManagerFactory(ldapConnection()));
                customSessionFactories.add(new LDAPUserManagerFactory(ldapConnection()));
        		engine.setCustomSessionFactories(customSessionFactories);
                
                engine.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            }
        };
    }
    
    @Bean
    public RepositoryServiceImpl repositoryService(){
    	RepositoryServiceImpl repositoryService = new RepositoryServiceImpl();
    	return repositoryService;
    }
    
    @Bean
    public TaskServiceImpl taskService(){
    	TaskServiceImpl taskService = new TaskServiceImpl();
    	return taskService;
    }
    
    @Bean
    public ManagementServiceImpl managementService(){
    	ManagementServiceImpl managementService = new ManagementServiceImpl();
    	return managementService;
    }
    
    @Bean
    public RuntimeServiceImpl runtimeService(){
    	RuntimeServiceImpl runtimeService = new RuntimeServiceImpl();
    	return runtimeService;
    }
    
    @Bean
    public HistoryServiceImpl historyService(){
    	HistoryServiceImpl historyService = new HistoryServiceImpl();
    	return historyService;
    }    
}

2.1 Activiti Configuration Annotation Test

package com.nuke.activiti.spring;

import static org.junit.Assert.assertEquals;

import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.nuke.config.ActivitConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=ActivitConfiguration.class)
public class SpringWithAnnotations {

	@Autowired
	private RuntimeService runtimeService;
	
	@Autowired
	private TaskService taskService;

	@Test
	public void simpleProcessTest() {
		Map<String, Object> variableMap = new HashMap<String, Object>();
		variableMap.put("LoanId", 123456789);
		runtimeService.startProcessInstanceByKey("underwritingQueue", variableMap);
		Task task = taskService.createTaskQuery().singleResult();
		assertEquals("Unassigned Loan", task.getName());
		taskService.complete(task.getId());
		assertEquals(1, runtimeService.createProcessInstanceQuery().count());
	}
}

Activiti BPM Tutorial – Process Engine

Expense Process Diagram

expense_process

Expense Process BPMN20

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="expenseProcess" name="The new and shiny expense process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="Request Refund" activiti:assignee="kermit">
      <documentation>[Employee:${employee}, 
Amount: ${amount}]</documentation>
    </userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="Handle Request" activiti:candidateGroups="accountancy">
      <documentation>${employee} has requested a refund amount ${amount}</documentation>
    </userTask>
    <userTask id="usertask3" name="Handle Request" activiti:candidateGroups="management">
      <documentation>${employee} has requested a refund of ${amount}</documentation>
    </userTask>
    <serviceTask id="mailtask1" name="Mail Task" activiti:type="mail">
      <extensionElements>
        <activiti:field name="to">
          <activiti:string><![CDATA[thysmichels@gmail.com]]></activiti:string>
        </activiti:field>
        <activiti:field name="from">
          <activiti:string><![CDATA[lc@lc.com]]></activiti:string>
        </activiti:field>
        <activiti:field name="subject">
          <activiti:string><![CDATA[Activity Mail]]></activiti:string>
        </activiti:field>
        <activiti:field name="html">
          <activiti:expression>${employee} has requested refund</activiti:expression>
        </activiti:field>
      </extensionElements>
    </serviceTask>
    <sequenceFlow id="flow6" sourceRef="mailtask1" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
    <exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow7" sourceRef="usertask3" targetRef="exclusivegateway2"></sequenceFlow>
    <sequenceFlow id="flow8" sourceRef="usertask2" targetRef="exclusivegateway2"></sequenceFlow>
    <sequenceFlow id="flow9" sourceRef="exclusivegateway2" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow10" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>
    <sequenceFlow id="flow11" name="${employeeVerification==&quot;true&quot;}" sourceRef="exclusivegateway1" targetRef="mailtask1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${employeeVerification=="true"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow12" name="${employeeVerification==&quot;false&quot;}" sourceRef="exclusivegateway1" targetRef="usertask2">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${employeeVerification=="false"}]]></conditionExpression>
    </sequenceFlow>
    <boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="usertask2" cancelActivity="true">
      <timerEventDefinition>
        <timeDuration>PT1S</timeDuration>
      </timerEventDefinition>
    </boundaryEvent>
    <sequenceFlow id="flow15" sourceRef="boundarytimer1" targetRef="startevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_expenseProcess">
    <bpmndi:BPMNPlane bpmnElement="expenseProcess" id="BPMNPlane_expenseProcess">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="132.0" y="290.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="240.0" y="280.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="462.0" y="390.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="boundarytimer1" id="BPMNShape_boundarytimer1">
        <omgdc:Bounds height="30.0" width="30.0" x="500.0" y="430.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="640.0" y="180.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="mailtask1" id="BPMNShape_mailtask1">
        <omgdc:Bounds height="55.0" width="105.0" x="450.0" y="180.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="890.0" y="297.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="413.0" y="287.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2">
        <omgdc:Bounds height="40.0" width="40.0" x="810.0" y="294.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="167.0" y="307.0"></omgdi:waypoint>
        <omgdi:waypoint x="240.0" y="307.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="555.0" y="207.0"></omgdi:waypoint>
        <omgdi:waypoint x="640.0" y="207.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="745.0" y="207.0"></omgdi:waypoint>
        <omgdi:waypoint x="830.0" y="207.0"></omgdi:waypoint>
        <omgdi:waypoint x="830.0" y="294.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="567.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="830.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="830.0" y="334.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
        <omgdi:waypoint x="850.0" y="314.0"></omgdi:waypoint>
        <omgdi:waypoint x="890.0" y="314.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
        <omgdi:waypoint x="345.0" y="307.0"></omgdi:waypoint>
        <omgdi:waypoint x="413.0" y="307.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
        <omgdi:waypoint x="433.0" y="287.0"></omgdi:waypoint>
        <omgdi:waypoint x="432.0" y="225.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="207.0"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="36.0" width="100.0" x="443.0" y="287.0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
        <omgdi:waypoint x="433.0" y="327.0"></omgdi:waypoint>
        <omgdi:waypoint x="433.0" y="417.0"></omgdi:waypoint>
        <omgdi:waypoint x="462.0" y="417.0"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="36.0" width="100.0" x="443.0" y="327.0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow15" id="BPMNEdge_flow15">
        <omgdi:waypoint x="500.0" y="445.0"></omgdi:waypoint>
        <omgdi:waypoint x="149.0" y="444.0"></omgdi:waypoint>
        <omgdi:waypoint x="149.0" y="325.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

Expense Process Test

package org.activiti.designer.test;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.FileInputStream;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;

public class ProcessTestExpenseProcess {

	private String filename = "/Users/tmichels/Documents/workspace-sts-3.5.0.M21/nucleus-business-process/src/main/resources/diagrams/expense_process.bpmn";

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule();
	
	@Test
	public void startProcess() throws Exception {
		ProcessEngine processEngine = ProcessEngineConfiguration
			.createStandaloneInMemProcessEngineConfiguration()
			.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
			.setMailServerHost("smtp.gmail.com")
			.setMailServerPort(587)
			.setMailServerUsername("youremail@gmail.com")
			.setMailServerPassword("password")
			.setMailServerUseSSL(true)
			.setMailServerUseTLS(true)
		    .buildProcessEngine();
		
		RuntimeService runtimeService = activitiRule.getRuntimeService();
		
		RepositoryService repositoryService = activitiRule.getRepositoryService();
		repositoryService.createDeployment().addInputStream("expense_process.bpmn",
				new FileInputStream(filename)).deploy();
		
		Map<String, Object> variableMap1 = new HashMap<String, Object>();
		variableMap1.put("employee", "Jack");
		variableMap1.put("amount", 111);
		Map<String, Object> variableMap2 = new HashMap<String, Object>();
		variableMap2.put("employee", "Jonny");
		variableMap2.put("amount", 222);
		Map<String, Object> variableMap3 = new HashMap<String, Object>();
		variableMap3.put("employee", "Pete");
		variableMap3.put("amount", 333);
		
		ProcessInstance processInstance1 = runtimeService.startProcessInstanceByKey("expenseProcess", variableMap1);
		ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("expenseProcess", variableMap2);
		ProcessInstance processInstance3 = runtimeService.startProcessInstanceByKey("expenseProcess", variableMap3);
		System.out.println("**** ProcessInstance1 ID *** " + processInstance1.getId());
		
		assertNotNull(processInstance1.getId());
		assertNotNull(processInstance2.getId());
		assertNotNull(processInstance3.getId());
		

		Map<String, Object> processVariables = runtimeService.getVariables(processInstance1.getId());
		for (String processVariable : processVariables.keySet()){
			System.out.println("PROCESS KEY : " + processVariable + " VALUE: " + processVariables.get(processVariable));
		}
		
		TaskService taskService = processEngine.getTaskService();
		
		//Query Task Available for Kermit
		 List<Task> availableTasksForKermit = taskService.createTaskQuery().taskAssignee("kermit").list();
		 for (Task task : availableTasksForKermit) {
		      System.out.println(" *******AVAILABLE TASK**********" + "\n" 
		      		+ 	" Task Name: " + task.getName() + "\n Owner: " + task.getOwner() + "\n" +
		    		  	" Assignee: " + task.getAssignee() +"\n "+ "Description: " + task.getDescription());
		 }
		
		List<Task> tasks = activitiRule.getTaskService().createTaskQuery().list();
		for (Task task : tasks){
			System.out.println("*******LIST TASKS************" + "\n" +
					"Get Task:" + task.getAssignee());
		}

		List<Task> kermitTasks = taskService.createTaskQuery()
		         .taskAssignee("kermit")
		         .processVariableValueEquals("amount", 111)
		         .orderByDueDate().asc()
		         .list();
		
		for (Task kermitTask: kermitTasks){
			System.out.println("*******QUERY FOR ASSIGNEE TASKS************" + "\n" + kermitTask.getAssignee());
		}
		
		 //Can't Claim Task as this task already has an assignee
		 if (availableTasksForKermit.get(0).getAssignee()==null)
			 taskService.claim(availableTasksForKermit.get(0).getId(), "rocky");
	     
	     //Verify Task - No Tasks for Rocky cause Kermit has it
	     tasks = taskService.createTaskQuery().taskAssignee("rocky").list();
	     for (Task task : tasks) {
	       System.out.println("Task for rocky: " + task.getName());
	     }
	     
	     //Ok kermit claims a tasks
	     taskService.claim(availableTasksForKermit.get(0).getId(), "kermit");
	     
	     List<Task> claimedTasks = taskService.createTaskQuery().taskCandidateOrAssigned("kermit").list();
	     for (Task claimedTask : claimedTasks){
	    	 System.out.println("Task claimed by Kermit: " + claimedTask.getDescription());
	     }
	     
	     Map<String, Object> taskCompleteVariables = new HashMap<String, Object>();
	     taskCompleteVariables.put("employeeVerification", false);
	     taskCompleteVariables.put("amountVerificaion", true);
	     taskService.complete(availableTasksForKermit.get(0).getId(),taskCompleteVariables);
	     
	     System.out.println("Number of tasks for kermit: " 
	             + taskService.createTaskQuery().taskAssignee("kermit").count());
	     
	     List<Task> accountancyTasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
	     for (Task accountancyTask : accountancyTasks){
	    	 System.out.println("Accountancy Task: " +accountancyTask.getDescription());
	     }
	     
	     taskService.claim(accountancyTasks.get(0).getId(), "sandy");
	     
	     System.out.println("Number of tasks for Sandy: " 
	             + taskService.createTaskQuery().taskAssignee("sandy").count());
	     
	     System.out.println("BreakPoint Timeout");
	     
	     System.out.println("Number of tasks for Sandy: " 
	             + taskService.createTaskQuery().taskAssignee("sandy").count());
	     
	   //Query Task Available for Kermit
		 List<Task> availableTasksForKermit2 = taskService.createTaskQuery().taskAssignee("kermit").list();
		 for (Task task : availableTasksForKermit2) {
		      System.out.println(" *******AVAILABLE TASK**********" + "\n" 
		      		+ 	" Task Name: " + task.getName() + "\n Owner: " + task.getOwner() + "\n" +
		    		  	" Assignee: " + task.getAssignee() +"\n "+ "Description: " + task.getDescription());
		 }
		 
		 taskService.claim(accountancyTasks.get(0).getId(), "sandy");
		 taskService.complete(accountancyTasks.get(0).getId());
	      
	     HistoryService historyService = processEngine.getHistoryService();
	     HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstance1.getId()).singleResult();
	     System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
	}
}

Output

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/tmichels/.m2/repository/org/slf4j/slf4j-log4j12/1.7.7/slf4j-log4j12-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/tmichels/.m2/repository/org/slf4j/slf4j-jdk14/1.7.2/slf4j-jdk14-1.7.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
23 May 2014 09:08:57,461 [main]  INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [activiti.cfg.xml]
23 May 2014 09:08:59,874 [main]  INFO org.activiti.engine.impl.db.DbSqlSession:975 - performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
23 May 2014 09:08:59,955 [main]  INFO org.activiti.engine.impl.db.DbSqlSession:975 - performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
23 May 2014 09:08:59,973 [main]  INFO org.activiti.engine.impl.db.DbSqlSession:975 - performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
23 May 2014 09:08:59,986 [main]  INFO org.activiti.engine.impl.ProcessEngineImpl:79 - ProcessEngine default created
23 May 2014 09:08:59,989 [main]  INFO org.activiti.engine.impl.jobexecutor.JobExecutor:76 - Starting up the JobExecutor[org.activiti.engine.impl.jobexecutor.DefaultJobExecutor].
23 May 2014 09:08:59,994 [Thread-1]  INFO org.activiti.engine.impl.jobexecutor.AcquireJobsRunnable:51 - JobExecutor[org.activiti.engine.impl.jobexecutor.DefaultJobExecutor] starting to acquire jobs
23 May 2014 09:09:00,847 [main]  INFO org.activiti.engine.impl.ProcessEngineImpl:79 - ProcessEngine default created
23 May 2014 09:09:00,853 [main]  INFO org.activiti.engine.impl.bpmn.deployer.BpmnDeployer:81 - Processing resource expense_process.bpmn
**** ProcessInstance1 ID *** 5
PROCESS KEY : amount VALUE: 111
PROCESS KEY : employee VALUE: Jack
 *******AVAILABLE TASK**********
 Task Name: Request Refund
 Owner: null
 Assignee: kermit
 Description: [Employee:Jack, 
Amount: 111]
 *******AVAILABLE TASK**********
 Task Name: Request Refund
 Owner: null
 Assignee: kermit
 Description: [Employee:Jonny, 
Amount: 222]
 *******AVAILABLE TASK**********
 Task Name: Request Refund
 Owner: null
 Assignee: kermit
 Description: [Employee:Pete, 
Amount: 333]
*******LIST TASKS************
Get Task:kermit
*******LIST TASKS************
Get Task:kermit
*******LIST TASKS************
Get Task:kermit
*******QUERY FOR ASSIGNEE TASKS************
kermit
23 May 2014 09:09:02,320 [main]  INFO org.activiti.engine.impl.bpmn.deployer.BpmnDeployer:81 - Processing resource expense_process.bpmn
23 May 2014 09:09:02,442 [main]  INFO org.activiti.engine.impl.bpmn.deployer.BpmnDeployer:81 - Processing resource expense_process.expenseProcess.png
Number of tasks for kermit: 2
Accountancy Task: Jack has requested a refund amount 111
Number of tasks for Sandy: 1
BreakPoint Timeout
Number of tasks for Sandy: 1
 *******AVAILABLE TASK**********
 Task Name: Request Refund
 Owner: null
 Assignee: kermit
 Description: [Employee:Jonny, 
Amount: 222]
 *******AVAILABLE TASK**********
 Task Name: Request Refund
 Owner: null
 Assignee: kermit
 Description: [Employee:Pete, 
Amount: 333]
Process instance end time: Fri May 23 09:09:02 PDT 2014

Develop custom widgets for Business Space with Rational Application Developer or WebSphere Integration Develope

Learn how to add value to your Business Process Management scenarios by developing custom widgets for your Business Space experience. Using the enhanced Web Tools features of Rational Application Developer V7.5.5 or WebSphere Integration Developer V7, you can create the specific widgets you need and “mash them up” with the widgets provided with the WebSphere BPM products. This article walks you through a step-by-step example for developing a widget and installing it to your Business Space palette for use in your spaces and pages.

http://www.ibm.com/developerworks/websphere/library/techarticles/1004_wayne/1004_wayne.html