jBPM executor for embedded applicatin in Eclipse

Version 1

    Requirements:

    - jBPM 6.1.0

    - Eclipse 4.4.1 with BPMN2 Modeler - Diagram Editor 1.0.2.201403061830 and - jBPM Runtime Extension Feature 1.0.2.201403061830

     

    This example was created based on method trials and errors.

    If you have any additional advice how to use jBPM executor in embedded application I'm waiting for your comments.

     

    Step 1:

    Create 'jbpm-executor' jBPM maven project in eclipse.

     

    Step 2:

    Create drools.rulebase.conf file in jbpm-executor\src\main\resources\META-INF

     

    drools.workDefinitions = WorkDefinitions.wid
    
    
    

     

    Step 3:

    Create WorkDefinitions.wid file in jbpm-executor\src\main\resources\META-INF

     

    import org.drools.core.process.core.datatype.impl.type.StringDataType;
    import org.drools.core.process.core.datatype.impl.type.ObjectDataType;
    import java.lang.Long;
    import java.lang.Integer;
    import java.lang.Boolean;
    import java.lang.String;
    
    
    [
      [
        "name" : "AsyncWIH",
        "parameters" : [
             "CommandClass" : new StringDataType()
        ],
        "results" : [
            "Result" : new ObjectDataType(),
        ],
        "displayName" : "AsyncWIH",
        "icon" : "async-16x15.png"
      ],
    ]
    
    
    
    

     

    Step 4:

    Create FileCommand class which will be executed as example by AsyncWIH work item.

    The example downloads file which will be set as parameter for work item.

     

    /**
    *
    */
    package com.sample.workitem;
    
    
    import java.lang.reflect.Array;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardCopyOption;
    
    
    import org.kie.api.runtime.process.WorkItem;
    import org.kie.internal.executor.api.Command;
    import org.kie.internal.executor.api.CommandContext;
    import org.kie.internal.executor.api.ExecutionResults;
    
    
    /**
    * Test command. Download file from url and save in temporary directory
    *
    * @author tgratkowski
    *
    */
    public class FileCommand implements Command {
    
    
      protected ExecutionResults executionResults;
    
    
      public ExecutionResults execute(CommandContext commandContext) {
    
    
      System.out.println("Command executed on executor with data " + commandContext.getData());
      WorkItem workItem = (WorkItem) commandContext.getData("workItem");
    
    
      // Do the heavy lifting here ...
      Object[] parameters = getParameters(workItem);
      String fileToDownload = (String) workItem.getParameter("fileToDownload");
    
    
      System.out.println(">>>>>>>>>>>>>>>>>> fileToDownload: " + fileToDownload);
      for (Object object : parameters) {
      System.out.println(">>>>>>>>>>>>>>>>>> parameters: " + object);
      }
    
    
      executionResults = new ExecutionResults();
    
    
      try {
      if (fileToDownload != null && !fileToDownload.isEmpty()) {
      URL website = new URL(fileToDownload);
      HttpURLConnection httpcon = (HttpURLConnection) website.openConnection();
      httpcon.addRequestProperty("User-Agent", "Mozilla/4.76");
      System.out.println(">>>>>>>>>>>>>>>>>> Save '" + website.getFile() + "' file to : " + System.getProperty("java.io.tmpdir"));
      Path destination = Paths.get(System.getProperty("java.io.tmpdir") + website.getFile());
      Files.copy(httpcon.getInputStream(), destination, StandardCopyOption.REPLACE_EXISTING);
    
    
      }
      } catch (Exception ex) {
      ex.printStackTrace();
      }
    
    
      return executionResults;
      }
    
    
      /**
      * Return table of parameter
      *
      * @param workItem
      * @return
      */
      public Object[] getParameters(WorkItem workItem) {
      Object[] parameters = null;
    
    
      if (workItem.getParameter("Parameter") instanceof Object[]) {
      parameters = (Object[]) workItem.getParameter("Parameter");
      } else if (workItem.getParameter("Parameter") != null && workItem.getParameter("Parameter").getClass().isArray()) {
      int length = Array.getLength(workItem.getParameter("Parameter"));
      parameters = new Object[length];
      for (int i = 0; i < length; i++) {
      parameters[i] = Array.get(workItem.getParameter("Parameter"), i);
      }
      } else {
      parameters = new Object[] { workItem.getParameter("Parameter") };
      }
    
    
      return parameters;
      }
    }
    
    
    
    
    
    

     

    In lines 43, 48 we can read parameters set in future when user will be drawn and parametrized BPM diagram.

     

    Step 5:

    Now we can update BPM model and we have ability to use own AsyncWIH work item.

    jbpm-executor_1.png

    Step 6:

    Parametrize AsyncWIH and set CommandClass which is our example com.sample.workitem.FileCommand

    and set additional parameter fileToDownload which is read by FileCommand in line 43

     

    jbpm-executor_2.png

     

    Step 7:

    Register our new work item in KieSession (line 45) and initialize engine for asynchronous tasks on BPM diagram (lines 44,46).

    package com.sample;
    
    
    import java.util.List;
    
    
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    
    
    import org.jbpm.executor.ExecutorServiceFactory;
    import org.jbpm.executor.impl.wih.AsyncWorkItemHandler;
    import org.jbpm.test.JBPMHelper;
    import org.kie.api.KieBase;
    import org.kie.api.KieServices;
    import org.kie.api.runtime.KieContainer;
    import org.kie.api.runtime.KieSession;
    import org.kie.api.runtime.manager.RuntimeEngine;
    import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder;
    import org.kie.api.runtime.manager.RuntimeManager;
    import org.kie.api.runtime.manager.RuntimeManagerFactory;
    import org.kie.api.task.TaskService;
    import org.kie.api.task.model.TaskSummary;
    import org.kie.internal.executor.api.ExecutorService;
    
    
    public class ProcessMain {
    
      static EntityManagerFactory emf;
    
    
      public static void main(String[] args) {
      KieServices ks = KieServices.Factory.get();
      KieContainer kContainer = ks.getKieClasspathContainer();
      KieBase kbase = kContainer.getKieBase("kbase");
    
    
      RuntimeManager manager = createRuntimeManager(kbase);
      RuntimeEngine engine = manager.getRuntimeEngine(null);
      KieSession ksession = engine.getKieSession();
      TaskService taskService = engine.getTaskService();
    
    
      ExecutorService executorService = ExecutorServiceFactory.newExecutorService(ProcessMain.emf);
      ksession.getWorkItemManager().registerWorkItemHandler("AsyncWIH", new AsyncWorkItemHandler(executorService));
      executorService.init();
    
    
      ksession.startProcess("com.sample.bpmn.hello");
    
    
      // let john execute Task 1
      List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
      TaskSummary task = list.get(0);
      System.out.println("John is executing task " + task.getName());
      taskService.start(task.getId(), "john");
      taskService.complete(task.getId(), "john", null);
    
    
      // let mary execute Task 2
      list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
      task = list.get(0);
      System.out.println("Mary is executing task " + task.getName());
      taskService.start(task.getId(), "mary");
      taskService.complete(task.getId(), "mary", null);
    
    
    // manager.disposeRuntimeEngine(engine);
    // System.exit(0);
      }
    
    
      private static RuntimeManager createRuntimeManager(KieBase kbase) {
      JBPMHelper.startH2Server();
      JBPMHelper.setupDataSource();
      ProcessMain.emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa");
      RuntimeEnvironmentBuilder builder = RuntimeEnvironmentBuilder.Factory.get()
      .newDefaultBuilder().entityManagerFactory(ProcessMain.emf)
      .knowledgeBase(kbase);
      return RuntimeManagerFactory.Factory.get()
      .newSingletonRuntimeManager(builder.get(), "com.sample:example:1.0");
      }
    
    
    }
    
    
    
    
    
    
    
    

     

    The result of our example:

    John is executing task Task 1
    Mary is executing task Task 2
    Command executed on executor with data {processInstanceId=1, deploymentId=com.sample:example:1.0, businessKey=1:2, callbacks=org.jbpm.executor.impl.wih.AsyncWorkItemHandlerCmdCallback, ClassLoader=sun.misc.Launcher$AppClassLoader@73d16e93, workItem=WorkItem 2 [name=AsyncWIH, state=0, processInstanceId=1, parameters{CommandClass=com.sample.workitem.FileCommand, fileToDownload=http://download.thinkbroadband.com/5MB.zip}]}
    >>>>>>>>>>>>>>>>>> fileToDownload: http://download.thinkbroadband.com/5MB.zip
    >>>>>>>>>>>>>>>>>> parameters: null
    >>>>>>>>>>>>>>>>>> Save '/5MB.zip' file to : D:\temp\os\
    END!!!
    
    
    

     

    I hope it helps somebody

     

    Best regards,

    Tom