jBPM 6 Web application example

User Rating: 4 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Inactive
 

In this tutorial I'll describe how I have set up my first jBPM 6 application using Eclipse and the jBPM 6 plugin installed on it. The prerequisite to it is that you have correctly installed jBPM 6 using the jbpm-installer. I have described the steps in this tutorial which shows how to shorten the full installation procedure. 


Before starting, let's see at first what's new with jBPM 6. jBPM6 introduces several enhancements: one of the most interesting ones is the introduction of the module Runtime Manager which greatly simplify the management of:

  • KnowledgeBase (KieBase)
  • KnowledgeSession (KieSession)

jbpm 6 tutorial example jbpm 6 tutorial example

The Knowledge is a key element of jBPM 6 (KIE = Knowledge is everything) and you can use any of three built-in strategies for handling knowledge sessions and its relation to process instance.

  • Singleton - single knowledge session that will execute all process instances
  • Per Request - every request (which is in fact call to getRuntimeEngine) will get new knowledge session
  • Per Process Instance - every process instance will have its dedicated knowledge session for the entire life time

To make use of the strategy it's enough to create proper type of RuntimeManager. This can be obtained by means of Context and Dependency Injection which brings the power of jBPM 6 to the next level.

@Inject
@Singleton
private RuntimeManager singletonManager;


So let's see how I've built my example. This example is intended as an upgrade of my jBPM 5 tutorial with the introduction of a Task Service in it. I've found lots of useful hints on this article (http://jsvitak.wordpress.com/2014/01/09/jbpm-6-web-application-examples/) where you can find some useful stuff for building JSP/JSF applications and jBPM 6. In particular I've borrowed the "util" package which contains some CDI producer and Alternative Beans needed for proper deployment of the application.

So here's our simple process. This project is engineered as jBPM 6 Maven project. Once that you have created the project, add a jBPM 6 process to it. Here's a view of the process:
jbpm 6 tutorial example jbpm 6 tutorial example
The main process contains a variable named "money" which will be used to direct the flow in one direction or in another.
jbpm 6 tutorial example jbpm 6 tutorial example
The only Task (buy ticket) is assigned to user "john".

jbpm 6 tutorial example jbpm 6 tutorial example

We have included in the resources of our project the userinfo.properties which contains a ":" separated list of values for each actor including Name=email:Group:Display Name:
This email address is being protected from spambots. You need JavaScript enabled to view it.">john=This email address is being protected from spambots. You need JavaScript enabled to view it.:en-UK:john

Moving next, within the Exclusive Gateway, we have set as Mvel condition
Money < 1000  Economy class
Money >= 1000 First class

jbpm 6 tutorial example jbpm 6 tutorial example

The last part of the process is an Inclusive Gateway which is Converging towards the end
jbpm 6 tutorial example jbpm 6 tutorial example

The project is composed of two EJBs and a Servlet Controller. This is the first Singleton EJB named ProcessBean which, as the name suggests, handles the Startup of processes:

@Startup
@javax.ejb.Singleton
public class ProcessBean    {

    @Inject
    @Singleton
    private RuntimeManager singletonManager;

    @PostConstruct
    public void configure() {
        singletonManager.toString();
    }

    public long startProcess(String processName, Map<String, Object> params) throws Exception {

        RuntimeEngine runtime = singletonManager.getRuntimeEngine(EmptyContext.get());
        KieSession ksession = runtime.getKieSession();

        long processInstanceId = -1;

  
        try {
             
            ProcessInstance processInstance = ksession.startProcess(processName,params);
                   
            processInstanceId = processInstance.getId();

            System.out.println("Process started ... : processInstanceId = " + processInstanceId);

    
        } catch (Exception e) {
            e.printStackTrace();
 
            throw e;
        }

        return processInstanceId;
    }

}


What is most interesting to note is that this EJB gets injected the RuntimeManager that will be used to collect the KieSession; The other EJB named TaskManager handles the Tasks approval and retrieval, getting the TaskService injected as follows:

@Stateless
public class TaskBean  {

    @Inject
    TaskService taskService;
    
    public List<TaskSummary> retrieveTaskList(String actorId) throws Exception {

        List<TaskSummary> list;
        
        try {
            list = taskService.getTasksAssignedAsPotentialOwner(actorId, "en-UK");
  
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        System.out.println("retrieveTaskList by " + actorId);
        for (TaskSummary task : list) {
            System.out.println(" task.getId() = " + task.getId());
        }

        return list;
    }

    public void approveTask(String actorId, long taskId) throws Exception {

        try {
            System.out.println("approveTask (taskId = " + taskId + ") by " + actorId);
            taskService.start(taskId, actorId);
        
            taskService.complete(taskId, actorId, null);
 
        } catch (Exception e) {
            e.printStackTrace();
            Throwable cause = e.getCause();
            
            throw new RuntimeException(e);
        }  
    }

}


Among the utility classes of this project, you will find the CustomApplicationScopedProducer which contains a RuntimeEnvironment producer in all three possible variants (Singleton, PerProcess, PerRequest) loading one asset, the travel.bpmn:

    @Produces
    @Singleton
    @PerProcessInstance
    @PerRequest
    public RuntimeEnvironment produceEnvironment(EntityManagerFactory emf) {
        RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
                .newDefaultBuilder()
                .entityManagerFactory(emf)
                .userGroupCallback(usergroupCallback)
                .registerableItemsFactory(factory)
                .addAsset(
                        ResourceFactory
                                .newClassPathResource("travel.bpmn"),
                        ResourceType.BPMN2).get();
        return environment;
    }

    
Finally, the TaskServlet is a simple Controller which takes care to contect the EJBs for starting the process and for approving the Task. The Servlet is really styled using year's 2000's coding :-) however it's done on purpose to keep the web application as simplest as possible and just concentrate on the jBPM 6 stuff.

@WebServlet(name = "task", urlPatterns = { "/task" })
public class TaskServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @EJB
    private ProcessBean processService;
    @EJB
    private TaskBean taskService;

    protected void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        doGet(req, res);
    }

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {

        PrintWriter out = res.getWriter();
        res.setContentType("text/html");
        long processInstanceId = -1;
        try {
            String action = req.getParameter("action");

            if (action.equals("create")) {
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("money", 2000);

                processInstanceId = processService.startProcess(
                        "com.sample.bpmn", params);
                out.println("Process started with Id " + processInstanceId);
                out.println("<a href=\"task?action=submit\">Complete Task</a> <br/>");
            } else if (action.equals("submit")) {
                List<TaskSummary> taskListJohn = taskService
                        .retrieveTaskList("john");
                approveAllTasks(taskListJohn, "john");

                out.println("John Appoved ");
                out.println("<a href=\"index.jsp\">Home</a> <br/>");

            }

        } catch (Exception e) {
            throw new ServletException(e);
        }

    }

    private void approveAllTasks(List<TaskSummary> taskList, String actor) {

        try {

            System.out.println("======== TASK LIST ========");
            for (TaskSummary task : taskList) {

                System.out.println(task.getName());
                System.out.println(task.getId());
                System.out.println(task.getProcessInstanceId());

                taskService.approveTask(actor, task.getId());

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

The pom.xml of this Maven project contains the JBoss plugin:

  <build>
    <plugins>
      <plugin>
        <groupId>org.jboss.as.plugins</groupId>
        <artifactId>jboss-as-maven-plugin</artifactId>
        <version>7.3.Final</version>
      </plugin>
    </plugins>
  </build>


Therefore in order to compile and deploy simply execute:

mvn clean install jboss-as:deploy


Download the Maven project from here


Advertisement