Eric D. Schabell: Quick Guide: Dissecting JBoss BPM Cross Process Communication

Thursday, December 4, 2014

Quick Guide: Dissecting JBoss BPM Cross Process Communication

(Article guest authored together with Jey Paulraj, Senior Solution Architect at Red Hat in North America)

The weeks tips & tricks article will dive in JBoss BPM Suite and specifically a question around how to communicate between two processes. Before we get into the solution details, let us first constrain the use case we will be talking about.

There could be many interpretations around what communication is between two processes, but we will start here with a simple way for one process to call another process. We will also show this simple usage through the provided RestAPI, which we will leverage to provide a deployable artifact that you can leverage as a custom work handler in any BPM process.

The artifact is a class we labeled RestApi.java, it contains the setup and details that make it possible for you to start another process from your existing process.

We provide the class in it's entirety at the end of this article but first we look closer at the various moving parts.

The top of every class includes the various imported objects or classes that will be used, we are most interested in the Knowledge Is Everything (KIE) API components and you will find them listed there along with some objects that represent our healthcare examples domain model.

package org.jboss.demo.heathcare;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// JBoss BPM Suite API 
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.services.client.api.RemoteRestRuntimeEngineFactory;

// Domain model.
import com.redhat.healthcare.CaseContext;
import com.redhat.healthcare.Doctor;
import com.redhat.healthcare.PatientInfo;
import com.redhat.healthcare.Prescription;
import com.redhat.healthcare.Rxdetail;

Next we will find the actual start of our RestAPI class, where we setup some of the attributes needed to work with the API along with a constructor that will make sure our JBoss BPM Suite server is running. Please note the process deployment ID along with the user and password are fictitious, so any resemblance to actual process data is by chance only.

String deploymentId = "com.redhat.healthcare:patients:1.0";
String bpmUrl = "http://localhost:8080/business-central";
String userId = "admin";
String password = "bpmsuite1!";
URL deploymentUrl;

// Constructor to check for availability of BPM server.
//
public RestApi()  {
   super();
   try {
      this.deploymentUrl = new URL();
   } catch (MalformedURLException e) {
      e.printStackTrace();
   }
}

The URL tested is assuming a basic default local installation, so if your installation is in a different setup you will need to adjust for that.

The next code snippet highlights a core helper method, the one that gets us a reference to the runtime engine. This is the engine that ties us through a RestAPI to a specific deployment, com.redhat.healthcare:patients:1.0 giving us access to start a process in that deployment.

// Get a runtime engine based on RestAPI and our deployment.
//
public RuntimeEngine getRuntimeEngine() {
   RemoteRestRuntimeEngineFactory restSessionFactory 
     = new RemoteRestRuntimeEngineFactory(deploymentId, deploymentUrl, userId, password);

   // create REST request
   RuntimeEngine engine = restSessionFactory.newRuntimeEngine();
   return engine;
}

With a runtime engine we can now access and create our sessions, where we will then be able to start our process instances.

The following method is called to start a process instance and contains for the sake of clarity only, the creation of a collection of data for submission into our process. It should be easy for you to see that this can be abstracted out as needed, for the use of process variables being mapped into your class.

// Setup our session, fill the data needed for process 
// instances and starting our process.
//
public void startProcess() {

   String taskUserId = userId;

   // create REST request.
   RuntimeEngine engine = getRuntimeEngine();
   KieSession ksession = engine.getKieSession();

   // setup data for submission to process instance.
   Doctor doctor = new Doctor();
   doctor.setAddress("3018 winter");
   doctor.setCity("madison");
   doctor.setGender("M");
   doctor.setGroupId("UW1001");
   doctor.setHospital("1001");
   doctor.setName("jey");
   doctor.setState("WI");

   PatientInfo pat = new PatientInfo();
   pat.setAge(12);
   pat.setName("jey");
   pat.setSymbtom("Diabetes Insipidus");
   pat.setType("Diabetes");

   Rxdetail rxdetail = new Rxdetail();
   List<rxdetail> details = new ArrayList<rxdetail>();
   rxdetail.setDrugName("xx");
   rxdetail.setOther("red");
   rxdetail.setQty(11);
   rxdetail.setRxNum(11);
   details.add(rxdetail);

   CaseContext cont = new CaseContext();
   cont.setApprovalReq("N");
   cont.setApprovalReq("Supervisor");
   
   Prescription prescription = new Prescription();
   prescription.setDoctor(doctor);
   prescription.setPatientInfo(pat);
   prescription.setRxdetails(details);

   // collect all data in our map.
   Map<string object=""> params = new HashMap<string object="">();
   params.put("prescription", prescription);
   params.put("caseContext", cont);
   
   // start process.
   ProcessInstance processInstance 
      = ksession.startProcess("healthcare.patientCaseProcess", params);

   // verify process started.
   System.out.println("process id " + processInstance.getProcessId());
   System.out.println("process id " + processInstance.getId());
}

With this method we have setup our doctor, patient and other medical details required by the process, collected them into a map and submitted them to the process instance to kick it all off.

Now we can tie this all together so that the main class that is run when this is called will just setup our RestAPI and start a new process instance each time it is called.

// Start our process by using RestAPI.
//
public static void main(String[] ar) {

   RestApi api = new RestApi();
   api.startProcess();
}

We hope this simple tour through this medical example gives you an idea of how to use the provided JBoss BPM Suite RestAPI to your advantage. In this case we use it for communicating to a specific process in a specific deployment from any other process deployed on our BPM server.

Here is the RestApi class:

package org.jboss.demo.heathcare;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// JBoss BPM Suite API 
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.services.client.api.RemoteRestRuntimeEngineFactory;

// Domain model.
import com.redhat.healthcare.CaseContext;
import com.redhat.healthcare.Doctor;
import com.redhat.healthcare.PatientInfo;
import com.redhat.healthcare.Prescription;
import com.redhat.healthcare.Rxdetail;

String deploymentId = "com.redhat.healthcare:patients:1.0";
String bpmUrl = "http://localhost:8080/business-central";
String userId = "admin";
String password = "bpmsuite1!";
URL deploymentUrl;

// Constructor to check for availability of BPM server.
//
public RestApi()  {
   super();
   try {
      this.deploymentUrl = new URL();
   } catch (MalformedURLException e) {
      e.printStackTrace();
   }
}

// Get a runtime engine based on RestAPI and our deployment.
//
public RuntimeEngine getRuntimeEngine() {
   RemoteRestRuntimeEngineFactory restSessionFactory 
     = new RemoteRestRuntimeEngineFactory(deploymentId, deploymentUrl, userId, password);

   // create REST request
   RuntimeEngine engine = restSessionFactory.newRuntimeEngine();
   return engine;
}

// Setup our session, fill the data needed for process 
// instances and starting our process.
//
public void startProcess() {

   String taskUserId = userId;

   // create REST request.
   RuntimeEngine engine = getRuntimeEngine();
   KieSession ksession = engine.getKieSession();

   // setup data for submission to process instance.
   Doctor doctor = new Doctor();
   doctor.setAddress("3018 winter");
   doctor.setCity("madison");
   doctor.setGender("M");
   doctor.setGroupId("UW1001");
   doctor.setHospital("1001");
   doctor.setName("jey");
   doctor.setState("WI");

   PatientInfo pat = new PatientInfo();
   pat.setAge(12);
   pat.setName("jey");
   pat.setSymbtom("Diabetes Insipidus");
   pat.setType("Diabetes");

   Rxdetail rxdetail = new Rxdetail();
   List<rxdetail> details = new ArrayList<rxdetail>();
   rxdetail.setDrugName("xx");
   rxdetail.setOther("red");
   rxdetail.setQty(11);
   rxdetail.setRxNum(11);
   details.add(rxdetail);

   CaseContext cont = new CaseContext();
   cont.setApprovalReq("N");
   cont.setApprovalReq("Supervisor");
   
   Prescription prescription = new Prescription();
   prescription.setDoctor(doctor);
   prescription.setPatientInfo(pat);
   prescription.setRxdetails(details);

   // collect all data in our map.
   Map<string object=""> params = new HashMap<string object="">();
   params.put("prescription", prescription);
   params.put("caseContext", cont);
   
   // start process.
   ProcessInstance processInstance 
      = ksession.startProcess("healthcare.patientCaseProcess", params);

   // verify process started.
   System.out.println("process id " + processInstance.getProcessId());
   System.out.println("process id " + processInstance.getId());
}

// Start our process by using RestAPI.
//
public static void main(String[] ar) {

   RestApi api = new RestApi();
   api.startProcess();
}


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.