(WID/WPS) Querying Human Tasks

This post shows how to query task related information from BPEDB .

To retrieve task instances of a particular task template :

String selectClause = "DISTINCT TASK.TKIID";
String whereClause = "TASK_TEMPL.NAME='RequestTask' AND TASK_TEMPL.NAMESPACE="http://ToDoTask/bpc/samples";
//Add "TASK.STATE = TASK.STATE.STATE_READY" to retrieve only those tasks which are in ready state.
QueryResultSet instances = taskManager.query(selectClause, whereClause, null, null, null, null);
boolean b = instances.first();
b = instances.next();
TKIID tkiid = (TKIID) instances.getOID(1);
Task task = taskManager.getTask(tkiid);


To retrieve all the participating task templates :


String whereClause = "TASK_TEMPL.KIND =  TASK_TEMPL.KIND.KIND_PARTICIPATING";
TaskTemplate[] templates = taskManager.queryTaskTemplates(whereClause, null, null, null);
System.out.println( " No of templates :" + templates.length);
System.out.println("***** Displaying TaskTemplateInfo ***** ");
for (int i = 0;i<templates.length;i++){
System.out.println(" Task Template Name :" + templates[i].getName());
System.out.println(" Task NameSpace :" + templates[i].getNamespace());
}


To retrieve all Escalation instances of ready tasks :


QueryResultSet escInstances = taskManager.query("DISTINCT ESCALATION.ESIID, ESCALATION.TKIID","TASK.STATE = TASK.STATE.STATE_READY ",(String)null, (Integer)null, (TimeZone)null );
System.out.println("No of Instances :"+escInstances.size());
boolean b2 = escInstances.first();
b2 = escInstances.next();
ESIID esiid = (ESIID) escInstances.getOID(1);
Escalation esc =  taskManager.getEscalation(esiid);
System.out.println("Escalation Name :"+esc.getName());
System.out.println("DurationUntilEscalated :"+esc.getDurationUntilEscalated());

To retrieve task instances with custom property name/value :

QueryResultSet instances = taskManager.query (" DISTINCT TASK.TKIID, TASK_CPROP.NAME, TASK_CPROP.STRING_VALUE",
"TASK_TEMPL.NAME = 'MyTask'",
String)null, (Integer)null, null );
while(instances.next()){ // looping thru all the rows
TKIID tkiid = (TKIID) instances.getOID(1);
System.out.println("TKIID "+tkiid);
System.out.println(instances.size()); // No of Rows
System.out.println(instances.getColumnDisplayName(1)); // TKIID
System.out.println(instances.getColumnDisplayName(2)); // NAME
System.out.println( instances .getColumnDisplayName(3)); // STRING_VALUE
System.out.println( instances .getString(2)); // Custom Property Name
System.out.println( instances .getString(3)); // Custom Property Value
}
Note : By executing escInstances.next()we shift to the next tuple(Row).

(WID/WPS) Ad-hoc Task Creation


This post shows the code for creating the ad-hoc task template & task on the fly:


To create the task template :


try{
javax.naming.Context ctx = new javax.naming.InitialContext();
com.ibm.task.api.LocalHumanTaskManagerHome localHumanTaskManagerHome = (com.ibm.task.api.LocalHumanTaskManagerHome)ctx.lookup("local:ejb/com/ibm/task/api/HumanTaskManagerHome");


com.ibm.task.api.LocalHumanTaskManager taskManager = localHumanTaskManagerHome.create();


// Modelling of HumanTask at runtime
// ClientTaskfactory is used to create a resourceset that contains definition for a newly created Task Model


ClientTaskFactory factory = ClientTaskFactory.newInstance();
ResourceSet bundle = factory.createResourceSet();


// load the wsdl definition
Definition definition = factory.loadWSDLDefinition(bundle, "Customer.wsdl");
PortType portType = definition.getPortType(new QName(definition.getTargetNamespace(),"Customer"));
Operation operation = portType.getOperation("info", (String) null, (String) null);


TTask task = factory.createTTask(bundle, TTaskKinds.HTASK_LITERAL, "Ad-hoc-Sample", new UTCDate( "2012-02-28T00:00:00" ), "http://adhoctask", portType, operation);


//Task Name : Ad-hoc-Sample & namespace : http://adhoctask
TaskModel taskModel = ClientTaskFactory.createTaskModel( bundle );


ValidationProblem[] validationProblems = taskModel.validate();


if (validationProblems.length == 0) {
System.out.println("No Validation problems");
TKTID template = taskManager.createTaskTemplate(taskModel, "AccessHumanTask");
//APPLIC_NAME : AccessHumanTask (The Module name)


System.out.println(" Template created ");
}

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


Note :

  • Above code should run once as we can not create the same template more than once.
  • This template survives server bounce.
  • Customer.wsdl should be at runtime (Export as jar & keep in server-lib or put in shared lib)

To create the instance of the task :

TKIID tkiid = taskManager.createTask("Ad-hoc-Sample", "http://adhoctask");
ClientObjectWrapper cow = taskManager.createInputMessage(tkiid);
DataObject dataObject = (DataObject) cow.getObject();
dataObject.setString("input","<<Your Input>>");
taskManager.startTask(tkiid, cow, null);

(WID/WPS) Serialization & Deserialization


This post shows the sample Java code for Serialization & Deserialization.


//String to DataObject (Deserialization)
private DataObject deserialize(String serializedBO)
{
DataObject dataObject = null;
try {
if(serializedBO != null) {
ByteArrayInputStream bais = new ByteArrayInputStream(serializedBO.getBytes());
BufferedInputStream bis = new BufferedInputStream(bais);
BOXMLSerializer serializer = (BOXMLSerializer)ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOXMLSerializer");
dataObject = serializer.readXMLDocument(bis).getDataObject();
bis.close();
}
}
catch (IOException e) {
e.printStackTrace(System.out);
}
return dataObject;
}

//DataObject to String (Serialization)
private String serialize(DataObject dataObject)
{
String serializedBO = null;
if(dataObject != null)
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
BufferedOutputStream bos = new BufferedOutputStream(baos);
BOXMLSerializer serializer = (BOXMLSerializer)ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOXMLSerializer");
//InputData is the BusinessObject name.
serializer.writeDataObject(dataObject,"http://JMSSampleLibrary/bpc/samples","InputData",bos);
bos.flush();
bos.close();
serializedBO = baos.toString("UTF-8");
}
catch (IOException e) {
e.printStackTrace(System.out);
}
}
return serializedBO;
}

(WMQ) PCF commands Intro

The purpose of WebSphere® MQ programmable command format (PCF) commands is to allow administration tasks to be programmed into an administration program. In this way, from a program we can manipulate queue manager objects (queues, process definitions, namelists, channels, client connection channels, listeners, services, and authentication information objects), and even manipulate the queue managers themselves.
PCF commands cover the same range of functions provided by MQSC commands. We can write a program to issue PCF commands to any queue manager.
Each PCF command is a data structure that is embedded in the application data part of a WebSphere MQ message. Each command is sent to the target queue manager using the MQI function MQPUT in the same way as any other message. Providing the command server is running on the queue manager receiving the message, the command server interprets it as a command message and runs the command. To get the replies, the application issues an MQGET call and the reply data is returned in another data structure. The application can then process the reply and act accordingly.
Sample Java code for creating local queues :
Imports are :
import com.ibm.mq.MQC;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.headers.pcf.MQCFIN;
import com.ibm.mq.headers.pcf.MQCFST;
import com.ibm.mq.headers.pcf.PCFAgent;
import com.ibm.mq.headers.pcf.PCFParameter;
import com.ibm.mq.pcf.MQCFH;
import com.ibm.mq.pcf.MQCFSL;

private static void createQueues(String[] queues)throws Exception {
MQQueueManager qMgr;
qMgr = new MQQueueManager("QM");
PCFAgent   agent = new PCFAgent (qMgr);
MQMessage []   responses;
int queueCounter =0;
for(;queueCounter<queues.length;queueCounter++)
{
  PCFParameter [] parameters = 
    {
      new MQCFST (CMQC.MQCA_Q_NAME, queues[queueCounter]),
      new MQCFIN (CMQC.MQIA_Q_TYPE, MQC.MQQT_LOCAL)
    };
  MQCFH     cfh;
  responses = agent.send (CMQCFC.MQCMD_CREATE_Q, parameters);
  cfh = new MQCFH (responses [0]);
  if(cfh.reason==4001)
  System.out.println("Queue Name : "+queues[queueCounter] +" is already present");
  else if(cfh.reason==0)
  System.out.println("Queue Name : "+queues[queueCounter] +" is created");
 }
}

Sample Java code for displaying all the local queues in queue manager:
private static void getQueueNames() throws Exception {
MQQueueManager qMgr;
qMgr = new MQQueueManager("QM");
PCFAgent   agent = new PCFAgent (qMgr);
MQMessage []   responses;
PCFParameter [] parameters = 
{
new MQCFST (CMQC.MQCA_Q_NAME, "*"), 
new MQCFIN (CMQC.MQIA_Q_TYPE, MQC.MQQT_LOCAL)
};
MQCFH cfh;
MQCFSL cfsl;
responses = agent.send (CMQCFC.MQCMD_INQUIRE_Q_NAMES, parameters);
cfh = new MQCFH (responses [0]);
if (cfh.reason == 0)
{
  cfsl = new MQCFSL (responses [0]);
  for (int i = 0; i < cfsl.strings.length; i++)
  {
    System.out.println ("Queue: " + cfsl.strings [i]);
  }
}
}


Jars required :

com.ibm.mq.headers.jar
com.ibm.mq.jar
com.ibm.mq.jmqi.jar
com.ibm.mq.pcf.jar


(WID/WPS) Group Work Items (Human Task)

In some scenarios it is necessary to assign a piece of work to a group of users, or to grant a particular privilege to a group of users. A well-known way to implement this behavior is to define appropriate groups in the staff repository and use appropriate people assignment criteria in the component which assigns tasks and authorizations to particular users.


The WPS offers 3 different people assignment criteria definitions which can be used to take advantage of groups predefined in the underlying staff repository. These verbs are:
  • Group Members
  • Group Search
  • Group
The Group Members verb implements a simple version of group resolution. As a parameter, the user of this verb must provide the group id of the group to be resolved, and a flag whether nested groups should be expanded recursively. At runtime, this verb triggers a lookup operation in the underlying staff repository and generates the explicit list of userids that are members of the specified group.




Scenario : Here the group name 'sellers' which has 2 users 'SellerA' & 'SellerB'. In real time when this task is created the Potential Owners in the Details tab of the task would be SellerA ,SellerB.


The Group Search verb offers a more advanced version of group resolution. Besides specifying the group id of the group to be resolved, the user of this verb may use other attributes of the group instead, like Manager of the group, Geographic Location, Business Category, etc. In addition, this verb allows to use wildcard symbols in parameters. For example, by using the pattern us012* as group id, this verb will create a query which, at runtime, will concatenate the users of all groups where the group id starts with "us012". Like the Group Members verb described above, at runtime the Group Search verb triggers a lookup operation in the underlying staff repository and generates the explicit list of userids that are members of the specified group.




The Group people assignment criteria definition uses a different approach to realize group resolution. This verb takes advantage of the WebSphere mechanism performed during login: Whenever a user authenticates against WebSphere, for example, by entering userid and password in a login dialog, all groups are automatically determined of which the user is a member, and this information is associated safely with the actual session.




In this case Potential Owners in the Details tab of the task would be cn=sellers,o=defaultWIMFileBasedRealm.


In contrast to the two verbs described above, no access to the underlying staff repository is performed at runtime for the Group verb, and no explicit list of userids is generated at any time. This allows to specify huge groups containing a large number of users without performance impact.

(WID/WPS) Human Task Overview

Task templates : Definition of a deployed task model, contains properties like name priority, escalation template, custom properties, people query templates etc.


Task instances : Runtime occurrence of a task template.


Subtask : Supports people when they need to delegate parts of their assigned work to other people, but want to keep control over the overall result.When the first subtask is started, the parent task enters the waiting-for-subtask substate. It remains in this substate until the last subtask reaches one of the end states finished, failed, expired, or terminated.
Read more : http://publib.boulder.ibm.com/infocenter/dmndhelp/v6r2mx/index.jsp?topic=/com.ibm.websphere.bpc.620.doc/doc/bpc/csubtasks.html


Follow-on tasks : Supports people when they want to delegate parts of their assigned work to other people, and the control over the completion of the work.When the follow-on task is started, the predecessor task enters the forwarded state.
Read more : http://publib.boulder.ibm.com/infocenter/dmndhelp/v6r2mx/index.jsp?topic=/com.ibm.websphere.bpc.620.doc/doc/bpc/cfollowon.html


Adhoc Task : Creating task dynamically at runtime.
  • The idea is to specify and use task templates dynamically, without a tooling application like WID, and without an explicit deployment step.
  • A task which is not part of the modeled process flow, but is created "on the fly" in the runtime environment to address work to be done. 
  • This task can be based on a predefined task template, or a free-form task that is created using a form editor.
Ex : A Document review process where the main reviewer assigns the review of certain chapters of the document to other reviewers, based on their expertise.
Note : Only the Collaborating(TTaskKinds.HTASK_LITERAL) & To-Do(TTaskKinds.PTASK_LITERAL) task can be created on the fly.

Running Example : http://publib.boulder.ibm.com/bpcsamp/v6r2/humanTaskFeatures/adHoc.html
Read more : http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/index.jsp?topic=%2Fcom.ibm.websphere.bpc.doc%2Fdoc%2Fbpc%2Ft6task_adhoc.html

For all Samples : http://publib.boulder.ibm.com/bpcsamp/index.html
For more info : http://publib.boulder.ibm.com/infocenter/dmndhelp/v6r2mx/index.jsp?topic=/com.ibm.websphere.bpc.620.doc/doc/bpc/ctasks.html

(WID/WPS) Why Inline Task ?

An inline task is defined in the BPEL process implementation. It can be implemented as a staff activity modeled on the business process level, and as task on various activities (invoke, pick, receive, event handler, on message).


Following reason why one should go for Inline Human Tasks :
  • Inline tasks offer the advantage that they have access to the context of the business process they belong to.
  • We need information from the process logic to execute human interaction.
  • We want to execute administrative tasks.
  • We want to define authorization rights on specific activities.
  • This enables scenarios like the “4-eyes principle”, also known as “separation of duties”. A usage example for the 4-eyes principle is an approval flow with two approval steps, both assigned to the same group of people, but with the additional rule that the approvals need to be given by two different people. The second approval’s staff query is defined such that it explicitly excludes the actual starter of the first approval. This can be done because as inline tasks, both approval tasks know about the enclosing process and its context, and hence the second task can access information from the first task.
Setting for the second human task :
Potential owner : Group Members without Named Users
NamedUsers : %wf:activity(Ratecredit).potentialOwners%
Where Ratecredit is the name of the business process activity (The first human task)

  • Having the ability to access process context also allows assigning tasks directly to the process starter something very useful for example in employee self service applications.



(WID/WPS) HumanTask API (Create/Claim/CompleteTask)

This post gives the code for creating, claiming & completing the task.


LocalHumanTaskManager taskManager = null;
String name = null;
QueryResultSet instances = null;
try {
Context context = new javax.naming.InitialContext();
System.out.println("Lookup...started");


LocalHumanTaskManagerHome taskHome = (LocalHumanTaskManagerHome) context.lookup("java:comp/env/ejb/LocalHumanTaskManagerHome");


LocalHumanTaskManagerHome taskHome = (LocalHumanTaskManagerHome) context.lookup("local:ejb/com/ibm/task/api/HumanTaskManagerHome");


System.out.println("Lookup...success");
taskManager = taskHome.create();
System.out.println("Accessing local interface...success");
//String taskName = "MyHumanTask"; // Invocation Task
String taskName = "StandAloneHT"; // To-doTask
String taskNamespace = "http://HTModule";
TKIID tkiid = taskManager.createTask(taskName, taskNamespace);
Task task = taskManager.getTask(tkiid);
ClientObjectWrapper cow = taskManager.createInputMessage(tkiid);
DataObject dataObject = (DataObject) cow.getObject();

dataObject.setString("input1","<<Your Input>>");
taskManager.startTask(tkiid, cow, null);
//Signature of the startTask method :
//void startTask(TKIID tkiid, ClientObjectWrapper input, ReplyHandlerWrapper replyHandler) 
 //Asynchronously executes a previously created task using the task instance ID.
//Task can be of any type.


//Alternate way of calling a task :
//ClientObjectWrapper  cow2= taskManager.callTask(tkiid, cow);
// Signature of the callTask method :
//ClientObjectWrapper callTask(TKIID tkiid, ClientObjectWrapper input) 
//Synchronously executes a previously created invocation task instance using the task instance ID.
//Task should not be of To-Do type.
System.out.println("TKIID : "+tkiid);


//Claiming the task :
taskManager.claim(tkiid);
System.out.println("Claimed the task");


//Creating output for completing the task :
ClientObjectWrapper output =  taskManager.createOutputMessage(tkiid);
DataObject outDataObject = (DataObject) output.getObject();
outDataObject.setString("output1","909090");
taskManager.complete(tkiid,  output); 
System.out.println("Completed the task");

//System.out.println("OUTPUT : "+((DataObject)cow2.getObject()).getString("output1")); If called Synchronously.
}
catch (Exception e) {
e.printStackTrace();
System.out.println(e.getClass());
}


Lookup in Green is used in a JSP while in Red is used in Java component.


Red Scenario :






In the above example "MyHumanTask" is an Invocation Task (Human----Service) & "StandAloneHT" is a To-Do Task.


 Assembly Diagram


Interface (Used as an interface for Todo Task & as a reference for Invocation Task)

(WID/WPS) Configuring EventHandler for an Escalation (WPS)

If an escalation occurs during the execution of a human task, you may want to notify an event handler within the application environment.
To configure an event and add it to your business application model, follow these instructions.

Declare a notification event handler for your task as described here:
  • In the human task editor click the Details tab. 
  • In the Event handler name field, enter a name for your notification event handler. {This name is not the name of the implementation class.}
  • Click Save. 
Add your plugin to your application:
  • Switch to the Resource perspective. 
  • In the Navigator, expand your business integration project. 
  • In the META-INF folder, create a new folder services
  • Right-click the services folder and select New > File . 
  • In the File name field of the New File wizard, , enter com.ibm.task.spi.EventHandlerNameNotificationEventHandlerPlugin Where EventHandlerName is the event handler name you have specified for your task. 
  • Click Finish. 
  • In the above file, write the fully qualified name of the event handler class.(For example : bpc.samples.plugin.EscalationNotificationPlugin)
Implementing the Event Handler Class:

EscalationNotificationPlugin.java

package bpc.samples.plugin;
import com.ibm.task.api.Escalation;
import com.ibm.task.api.TKIID;
import com.ibm.task.api.Task;
import com.ibm.task.spi.NotificationEventHandlerPlugin;

public class EscalationNotificationPlugin implements
NotificationEventHandlerPlugin {

public void escalationNotification(Task task, Escalation escalation) {
System.out.println("Entering method");
if(task != null && escalation != null)
{
System.out.println("Task template name: " + task.getTaskTemplateName());
System.out.println("Task name: " + task.getName());
System.out.println("Task state: " + task.getState());
System.out.println("Event handler name: " + task.getEventHandlerName());
System.out.println("Is escalated: " + task.isEscalated());
System.out.println("Escalation name: " + escalation.getName());
TKIID tkId = task.getID();
System.out.println("Task Id : " + tkId);
}

}

}

Specify an escalation with a notification type Event:
  • Switch to the Business Integration perspective and open your task in the human task editor. 
  • In the Escalation settings section, select the escalation. 
  • Click the Details tab. 
  • Configure the escalation as needed. For Notification type, choose Event from the list of available options. 
  • Save your work. 

(WID/WPS) Function Selector in WPS

I am expecting you might be knowing what it is & why to use it, if not then read this first :


Here is the sample code how to implement it :

import java.io.ByteArrayInputStream;
import java.io.IOException;
import com.ibm.jms.JMSBytesMessage;
import com.ibm.jms.JMSTextMessage;
import com.ibm.websphere.bo.BOXMLSerializer;
import com.ibm.ws.bo.service.BOXMLSerializerImpl;
import commonj.connector.runtime.FunctionSelector;
import commonj.connector.runtime.SelectorException;
import commonj.sdo.DataObject;

public class SampleFunctionSelector implements FunctionSelector {

public String generateEISFunctionName(Object[] argObjects) throws SelectorException 
{
String rootElementName = null;
String strMsg =null;
try 
{
for (int i = 0; i < argObjects.length; i++) {
if (argObjects[i] instanceof JMSTextMessage){
JMSTextMessage message = (JMSTextMessage) argObjects[i];
String xmlString = message.getText();
System.out.println("MESSAGE is instanceof JMSTextMessage :");
DataObject dataObject =convertXMLToBO(xmlString);
rootElementName = dataObject.getType().getName();
System.out.println("rootElementName::"+rootElementName);
}

else if (argObjects[i] instanceof JMSBytesMessage)
{
System.out.println("MESSAGE is instanceof JMSBytesMessage ");
JMSBytesMessage bytesMsg = (JMSBytesMessage) argObjects[i];
int msgLength = 0;
int BUF_SIZE = 50000;
byte[] data = new byte[BUF_SIZE];
while (true)
{
int len = bytesMsg.readBytes(data);
if (len > 0)
{
msgLength += len;
}
else
{
break;
}
}
byte[] message = new byte[msgLength];
if (msgLength <= BUF_SIZE)
{
System.arraycopy(data, 0, message, 0, msgLength);
}

else
{
bytesMsg.reset(); //reset cursor to beginning
bytesMsg.readBytes(message);

strMsg = new String(message);
DataObject dataObject =convertXMLToBO(strMsg);
rootElementName = dataObject.getType().getName();
System.out.println("rootElementName::"+rootElementName);
}

if(rootElementName != null)
{

if(rootElementName.equalsIgnoreCase("Operation1"))
return "processItem";
else if(rootElementName.equalsIgnoreCase("Operation2"))
return "processEmp";
else
System.out.println("no match");
}
}
throw new SelectorException("No Method Identified to process this message");
} catch (Throwable e) {
e.printStackTrace();
throw new SelectorException(e);
}
}

private DataObject convertXMLToBO(String strMsg) throws IOException

{
BOXMLSerializer serializer = new BOXMLSerializerImpl();
ByteArrayInputStream bis = new ByteArrayInputStream(strMsg.getBytes("UTF-8"));  //UTF-8 Encoding 
DataObject dataObject = serializer.readXMLDocument(bis).getDataObject();
return dataObject;

}
}

Storing Logical Tree to a String Using ESQL



CREATE FUNCTION parseToString(IN root REFERENCE) RETURNS CHARACTER
BEGIN
DECLARE concatString character;
SET concatString = '';
CALL ComposeDetails(root,concatString);
return concatString;
END;


CREATE PROCEDURE ComposeDetails(IN root REFERENCE,INOUT concatString CHARACTER) BEGIN
DECLARE fieldName CHARACTER;
DECLARE fieldValue CHARACTER;
DECLARE cursor REFERENCE TO root;
MOVE cursor FIRSTCHILD;
WHILE LASTMOVE(cursor) Do
SET fieldName = FIELDNAME(cursor);
SET fieldValue = FIELDVALUE(cursor);
IF (fieldValue is not null) THEN
SET  concatString  =  concatString  ||'<'||fieldName||'>' ||fieldValue||'</'||fieldName||'>';
ELSE
SET  concatString  =  concatString  ||'<'||fieldName||'>';
CALL ComposeDetails(cursor, concatString  );
SET  concatString  =  concatString  ||'</'||fieldName||'>';
END IF;
MOVE cursor NEXTSIBLING;
END WHILE;
END;

(WID/WPS) HTTP Binding in WPS

HTTP is a widely-used protocol for transferring information on the Web. Though originally designed to publish and retrieve HTML pages, it has now become a standard request/response protocol between clients and server.

When working with an external application using the HTTP protocol, an HTTP binding is necessary. 
  • The HTTP binding handles the transformation of data passed in as a message in a native format to a business object in a SCA application.
  • The HTTP binding also can transform data passed out as a business object to the native format expected by the external application. 

Comparing the HTTP binding to the Web services binding :
  • The Web Services binding only supports the SOAP (and JMS) protocols. 
  • The Web Services binding assumes that it is working with Web Services-based applications and so exposes the same model. In contrast, the HTTP binding assumes that it is working with native HTTP applications and exposes a model more familiar to this audience. 
  • Therefore, the Web Services binding provides first class support within the SCA architecture for Web Services applications communicating with the HTTP protocol and other protocols; whereas the HTTP binding allows WPS & WESB to mediate between, and communicate with, any HTTP application thus bringing any HTTP application into the Service Oriented Architecture framework. 

Link for a working PI :
UI based application, involves Ajax call to the Http Export binding & display the response in the UI.

Web Project (Html page)------> AJAX HTTP CALL-----> HTTP Export---> Business Process----->Show AJAX HTTP Response

(WMB) Local & Global env in Java Compute node

Local Environment :

  • The local environment tree is part of the logical message tree in which we can store information while the message flow processes the message.
  • In order to update the local environment, make a new copy of the local environment.

Use the full version of the copy constructor to create a new MbMessageAssembly object, as shown in the following example:

MbMessage env = assembly.getLocalEnvironment();
MbMessage newEnv = new MbMessage(env);
newEnv.getRootElement().createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"Status","Success");
MbMessageAssembly outAssembly = new MbMessageAssembly(
assembly,newEnv,assembly.getExceptionList(),assembly.getMessage());
getOutputTerminal("out").propagate(outAssembly);

Global Environment :

  • The Global environment tree is a part of the message and it is created when input message is received. However message flow does not populates the tree or using the contents of the tree .
  • The Global Environment can be altered across the message flow, therefore do not make a copy of it to alter.

The following Java code shows how to alter the Global Environment:
MbMessage env = assembly.getGlobalEnvironment();
env.getRootElement().createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "Status", "Success");
getOutputTerminal("out").propagate(assembly); 

(WMB) DB Call in JavaCompute Node

This post shows how to connect to DB in Java compute node & how to construct output message from database result set.
Below diagram shows the database table :

Database (TEST) Schema ( ADMIN) Table (EMP)

Schema :
mxsd

Here is the evaluate method :

public void evaluate(MbMessageAssembly inAssembly) throws MbException {
MbOutputTerminal out = getOutputTerminal("out");
MbMessage inMessage = inAssembly.getMessage();
MbMessage outMessage = new MbMessage();
MbMessageAssembly outAssembly = new MbMessageAssembly(inAssembly,outMessage);
try {
copyMessageHeaders(inMessage, outMessage);
MbElement inRootElement = inMessage.getRootElement();
List<MbElement>  idList =  (List) inRootElement.getLastChild().evaluateXPath("/ID");
int id = (Integer)idList.get(0).getValue();

//Creating Output data
MbElement outRootElement = outMessage.getRootElement();
MbElement messageType = outRootElement.getFirstChild().getFirstElementByPath("MessageType");
messageType.setValue("Response");
MbElement parser = outRootElement.createElementAsLastChild("MRM");

// Conventional way of connecting to DB.
Class.forName("com.ibm.db2.jcc.DB2Driver");  //Driver for DB2
String url = "jdbc:db2://localhost:50000/TEST"; // Database name : TEST
 Connection conn = DriverManager.getConnection(url,"username","password"); 

//Connection conn = getJDBCType4Connection("MYDB",JDBC_TransactionType.MB_TRANSACTION_AUTO); 
   // For this need to configure the configurable service.
  Statement stmt = conn.createStatement
  (ResultSet.TYPE_SCROLL_INSENSITIVE,  
   ResultSet.CONCUR_READ_ONLY);                                                 

 ResultSet resultSet = stmt.executeQuery("SELECT COMPANY, SALARY FROM ADMIN.EMP WHERE ID ="+id);

while(resultSet.next())
{
parser.createElementAsLastChild(MbElement.TYPE_NAME_VALUE,"COMPANY",resultSet.getString("COMPANY"));
parser.createElementAsLastChild(MbElement.TYPE_NAME_VALUE,"SALARY",resultSet.getInt("SALARY"));
}

out.propagate(outAssembly);


catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
finally {


// clear the outMessage even if there's an exception
outMessage.clearMessage();
}
}


Input :
<Request><ID>834</ID></Request>


Output :
<?xml version="1.0"?>
<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<COMPANY>GALAXY</COMPANY>
<SALARY>900000</SALARY>
</Response>

(WMB) Printing XML in JavaCompute

Printing application data in xml format in Java compute node is bit tricky, If we simply print the body (payload) we will not have data in xml format. We have to make use of toBitstream method to convert the body into an array of bytes & then print.

Excerpt of evaluate method :

  MbMessage message = assembly.getMessage();
MbElement root = message.getRootElement();
MbElement body = root.getLastChild();
byte[] b = null;
b = body.toBitstream("", "", "", 0, 0, 0);
 // This example is taken with XMLNSC as parser for input so no need to specify messageType, messageSet & wire format. 
 //For MRM parser, these parameters has to be specified.

try {
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(b);
InputStreamReader inputStreamReader = new InputStreamReader(arrayInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
char[] c = new char[b.length];
bufferedReader.read(c, 0, c.length);
System.out.println(c);
} catch (Exception e) {
e.printStackTrace();
}

Signature of toBitstream method :
                  
public byte[] toBitstream(String messageType, String messageSet, String messageFormat,int encoding,int ccsid, int options) throws MbException