Category Archives: BPM

JUnit testing Spring Security, Spring MVC and Activiti BPM

Spring Test MVC is a good framework for JUnit testing Spring MVC based application. In this sample, we demonstrated a simple LoanRequest application where in we test the Spring Security, Spring MVC and Activiti BPM Spring Support.

For people in hurry,

  • Get the latest Spring Test MVC code base
  • run “mvn clean install” on the above codebase
  • Get the loanrequest codebase latest code from @ Github
  • At the command prompt type “mvn test”, if the tests are successful, you are all set.

Details: JUnit testing Spring Security, Spring MVC and Activiti BPM

Spring Test MVC is an awesome framework to test the Spring MVC backend code. Spring Test MVC framework has a built in Spring MVC web container. You can point it to the webapp folder, and the spring application context and it will configure the buildin container to work with the JUnit test. You can also configure the Spring Security as below,

//You need to define a class as below,
class WebContextLoader extends GenericWebContextLoader {
public WebContextLoader() {
super("src/main/webapp", false);
}
}

//In your test case you need to configure the WebContexLoader as below with the Spring context files
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, value = {
"classpath:META-INF/spring/applicationContext-activiti.xml",
"classpath:META-INF/spring/applicationContext-security.xml",
"classpath:META-INF/spring/applicationContext.xml",
"classpath:META-INF/spring/test-datasource-config.xml"})
public class LoanRequestControllerTest {

//this FilterChainProxy configures the Spring Security feature
@Autowired
private FilterChainProxy springSecurityFilterChain;

@Autowired
private WebApplicationContext wac;

private MockMvc mockMvc;

@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webApplicationContextSetup(this.wac)
.addFilters(this.springSecurityFilterChain).build();
}

The API syntax is simple and expresses technical functionality closely, for example if the LoanRequest usecase is as below,

  • The accountant logged in and submitted the LoanRequest. The Server will return the HTTP Status as ok, and you can also assert if the Submitting went thru
  • Once the Accountant submitted the LoanRequest, the Management can review it and approve the Loan request

The above flow can be expressed by the below code using the TDD methodology,


@Test
public void testApprove() throws Exception {
mockMvc.perform(
post("/loanrequests/create").param("id", "4")
.param("customerName", "krishna").param("amount", "26")
.with(userDeatilsService("fozzie")))
.andExpect(status().isOk()).andExpect(redirectedUrl("/list"))
.andExpect(model().attribute("loanRequests", any(List.class)));

mockMvc.perform(
get("/loanrequestsapproval/approve/4").with(userDeatilsService("kermit")))
.andExpect(status().isOk());
}

If you notice, the http actions like Post and Get are demonstrated here. Also it has demonstrated how the user logging happens.

This container is configured to work with Spring Security, for example, if an accountant logs into to approval page, it will be forbidden. We write the test using TDD as below,


@Test
public void testApproveForbidden() throws Exception {
mockMvc.perform(
get("/loanrequestsapproval/approve/2").with(userDeatilsService("fozzie")))
.andExpect(status().isForbidden());
}

This sample also demonstrates the capability of Activiti BPM and how it can participate in JUnit testing.

You can configure the inmemory Activity Process Engine Configuration along with the deployed Bpmns as below,

<!-- <bean id="processEngineConfiguration"> -->
<bean id="processEngineConfiguration">
<property name="dataSource" ref="dataSource-activiti" />
<property name="databaseSchemaUpdate" value="true" />
<property name="transactionManager" ref="transactionManager" />
<property name="jpaHandleTransaction" value="false" />
<property name="jpaCloseEntityManager" value="false" />
<property name="jobExecutorActivate" value="false" />
<property name="deploymentResources" value="classpath*:/org/activiti/spring/test/usertask/LoanProcess.bpmn20.xml" />
</bean>

In the JUnit test TDD you can autowire this as below and populate some sample users,


@Autowired
SpringProcessEngineConfiguration processEngineConfiguration;

@Before
public void setup() {
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

IdentityService identityService = processEngine.getIdentityService();
User user = identityService.newUser("fozzie");
user.setPassword("fozzie");
identityService.saveUser(user);
user = identityService.newUser("kermit");
user.setPassword("kermit");
identityService.saveUser(user);

identityService.saveGroup(identityService.newGroup("accountancy"));
identityService.saveGroup(identityService.newGroup("management"));

identityService.createMembership("fozzie", "accountancy");
identityService.createMembership("kermit", "management");
}

In your controller, you can autowire the inmemory Activity Process Engine Configuration and start a process, approve a task and mark it as complete. For more details refer the LoanRequestController code.

Conclusion

In this example, I have demonstrated a Activiti BPM based workflow initiated from a Spring MVC container and goes thru a lifecycle. I also demonstrated how Spring Security is used to authorize the Activiti BPM users.

I hope this example helps.

Advertisements

Jumpstart Activiti BPM, Spring MVC and Maven

The source code for this can be found here.

Recently I had a opportunity to try Activiti, an opensource BPM. If you are from Java background, this is a good tool to help us learn concepts like BPM, Workflow, BPMN etc. It has very good Spring integration support. It support BPMN 2.0 standards. In this example, there are lots of JUnit testcases which runs out of the box with just maven, which can demo these concepts.

Just to give you some background, couple of years back, we had written a web application using Spring MVC for Supply Chain Automation, where the application flow was driven by the workflow rules defined outside of the application. While exploring this tool I also realized it is a perfect candidate for externalizing the user flows/rules similar to what we had written in Spring MVC. One of the other competing opensource tools is jBPM Drools.

BPM is a tool which can model a Business process to be used for 2 main purpose,

  • A BPM Business process that can be triggered by a web application to do a order process, which can touch multiple application (A2A) to complete the order
  • Another most important feature of a Business process modeling is in interacting with an user to complete a set of approval process, in the form of usertasks

In this article I will emphasize on 2nd point, I will demonstrate a Loan Processing Application using Activiti, BPMN 2.0, Spring ROO MVC and Maven. This code base has 2 projects,

  • Activiti Junit testcases ported to Maven: This helps you to learn the features of Activity. To quickstart go to this folder and run mvn test, if you see all the tests pass, import to STSIDE and run in debug mode and learn how it works. The prerequisites for this are maven and STS IDE, it does not need Activiti installation, it will work with Activiti in memory engine.
  • Loan Processing Application using Activiti, Spring ROO MVC, Maven: This example is built on top of Roo. In this example I demonstrate a process where loan is submitted by a user, the manager can claim the loan approval task and approve the loan. Activiti and most of other BPM tool does not need you to write external web application to control the flow, the tool themselves support basic UI flow. I will also demo how we can build basic UI for submitting a document and someone verify it and approving it. The prerequisites for this is maven, STS IDE, Activiti, ant, Spring Roo

Activiti BPM Details:

Let us download Activiti BPM and unzip the installation. Let us run ant demo.start from <activiti install>/setup folder.

In approach 1, open a browser and type http://localhost:8080/activiti-explorer, login as kermit/kermit. Deploy the bpmn.xml file located @ <svn location>/src/main/resources/org/activiti/spring/test/usertask1/LoanProcess1.bpmn20.xml . You will get user form in Activiti explorer where you can submit and approve the loan.

In approach 2, Deploy the bpmn.xml file located @ <svn location>/src/main/resources/org/activiti/spring/test/usertask/LoanProcess.bpmn20.xml . I have built a Roo based Spring MVC application where I did the “Push In” to generate the controller code LoanRequestController and added  the below code,

private String startProcess(LoanRequest loanRequest, HttpServletRequest request) {
  if (request.isUserInRole(submitterRole)) {
    logger.debug("in the startProcess ");
    // Get Activiti services
    // Create Activiti process engine
    ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().buildProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    taskService = processEngine.getTaskService();
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("loanProcess");
    logger.debug("startProcess processInstance Id=" + processInstance.getId());
    claimAndComplete(processInstance.getId());
  }
  return "";
}
private void approveProcess(LoanRequest loanRequest, HttpServletRequest request) {
  // TODO Auto-generated method stub
  logger.debug("in the approveProcess ");
  if (!loanRequest.getProcessId().isEmpty() &amp;&amp; request.isUserInRole(approverRole)) {
    claimAndComplete(loanRequest.getProcessId());
  }
}

Run the application by calling mvn -Dmaven.tomcat.port=8181 clean tomcat:run @/loanrequest folder. To test, login as kermit/kermit and create a loan request and submit. Now login as gonzo/gonzo and notice in activiti explorer the new process was started with new task “Verify loan request”. Now you go back to you application and login in as gonzo/gonzo and open the loan request and update it. It will get approved..

To learn more, run mvn test and understand how the process flow works. The spring configuration is as below,

 <bean id="dataSource-activiti">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:tcp://localhost/activiti" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="processEngineConfiguration">
<property name="dataSource" ref="dataSource-activiti" />
<property name="databaseSchemaUpdate" value="true" />
<property name="transactionManager" ref="transactionManager" />
<property name="jpaHandleTransaction" value="false" />
<property name="jpaCloseEntityManager" value="false" />
<property name="jobExecutorActivate" value="false" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource-activiti" />
</bean>
<bean id="processEngine"> <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" />

Quick look at the pom file will have below 3 additional dependencies,

<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.9</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.9</version>
</dependency> <dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.132</version>
</dependency>