Thursday, November 21, 2013

# 287 Adaptive Case Management - Subscribing to Case Events

I discussed the various types of Case events in a previous post.
Maybe you would like to review Here

I define my simple order approval case as follows -










Note I have checked Publish Case Events

I add a Mediator to my Case composite - this will subscribe to CaseEvents.
The edl is available here -


















oramds:/soa/shared/casemgmt/CaseEvent.edl

I create 7 file adapter (write) services for the different event types -

  • DOCUMENT_EVENT
  • USER_DEFINED_EVENT
  • DATA_UPLOAD_EVENT
  • COMMENT_EVENT
  • LIFECYCLE_EVENT
  • MILESTONE_EVENT
  • ACTIVITY_EVENT

I then filter on eventType in the mediator and call the appropriate service.



















































I then deploy and test my Case.
















I check for Lifecycle Events -








My case includes an automatic InitActivity.

Here are the start and end events for that -












Milestone Event - Once the Init is done we reach the milestone OrderApprovalStarted










Now I add a Comment to the case -











I now initiate the ApproveOrderProcessActivity - a BPM Process with Human Task
I then approve the order, I get 2 new activity events












I now raise a user Defined event - CustomerCancelledEvent via the Case UI








I now upload a doc to the case via the Case UI -










I now change a value of one of my order fields thru the Case UI -
this too is protocolled.








Tuesday, November 12, 2013

#285 Updating BPM task priority via Java API

Scenario:










I deploy this simple process

I then map the roles as follows -






Then I create a ws proxy to programmatically instantiate a BPM instance.
Essentially, what's covered in post #283.













I add the necessary code to the ...PortClient


















Test - check em to see that an instance has been created.






































Now we need to update this from priority 3 to 1.

First I use the API to query the current tasks for jcooper -

Method: getTaskDetails()

-----------------------------------------------------------------

    public String getTaskdetails(String user, String pwd) {
        System.out.println("getTaskdetails()");
        Map properties = new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,
                       "t3://localhost:7001");
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,
                       pwd);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,
                       user);

        try {
            //Create JAVA WorflowServiceClient
            IWorkflowServiceClient wfSvcClient =
                WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT,
                                                                      properties,
                                                                      null);

            //Get the task query service
            ITaskQueryService querySvc = wfSvcClient.getTaskQueryService();
            //Login as jcooper
            IWorkflowContext ctx =
                querySvc.authenticate(user, pwd.toCharArray(), null);
            //Set up list of columns to query
            List queryColumns = new ArrayList();
            queryColumns.add("TASKID");
            queryColumns.add("TASKNUMBER");
            queryColumns.add("TITLE");
            queryColumns.add("OUTCOME");
            //Query a list of tasks assigned to jcooper
            List tasks =
                querySvc.queryTasks(ctx, queryColumns, null, //Do not query additional info
                    ITaskQueryService.AssignmentFilter.MY_AND_GROUP, null, //No keywords
                    null, //No custom predicate
                    null, //No special ordering
                    0, //Do not page the query result
                    0);
            //Get the task service
            ITaskService taskSvc = wfSvcClient.getTaskService();
            //Loop over the tasks, outputting task information, and approving any
            //tasks whose outcome has not been set...
            System.out.println("getTaskdetails() nr of Tasks = " +
                               tasks.size());


            for (int i = 0; i < tasks.size(); i++) {
                System.out.println("In task loop...");
                Task task = (Task)tasks.get(i);
                int taskNumber = task.getSystemAttributes().getTaskNumber();
                String title = task.getTitle();
                String taskId = task.getSystemAttributes().getTaskId();
                String outcome = task.getSystemAttributes().getOutcome();
                int priority = task.getPriority();
                int taskNr = task.getSystemAttributes().getTaskNumber();
                String taskDefId =
                    task.getSystemAttributes().getTaskDefinitionId();
                System.out.println("In task loop... title/taskDefId = " +
                                   title + " / " + taskDefId);
                // Change priority from 3 to 1 for SimpleApprove

                System.out.println("Task #" + taskNumber + " (" + title +
                                   ") is " + outcome + " has priority " +
                                   priority + " Id = " + taskId + " taskNr= " +
                                   taskNr);
            }
        } catch (Exception e) {
            //Handle any exceptions raised here...
            System.out.println("Caught workflow exception: " + e.getMessage());
        }

        return "done";
    }

----------------------------------------------------------------------
This produces the following output -















Task 206277 is the one we just created.
TaskId is - 98f2fcc8-b3d1-4d65-a837-fb2e747763b4

Now I want to update this task to priority 1 -
So essentially I use the query service again, adding a predicate for the taskId -









I then use the updatePriority() method as shown below.




Test -














full method code -

    public String updateTaskPriority4Task(String myTaskId, int newPriority) {
        System.out.println("updateTaskPriority()");
        Map properties = new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,
                       "t3://localhost:7001");
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,
                       "welcome1");
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,
                       "weblogic");

        try {
            //Create JAVA WorkflowServiceClient
            IWorkflowServiceClient wfSvcClient =
                WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT,
                                                                      properties,
                                                                      null);

            //Get the task query service
            ITaskQueryService querySvc = wfSvcClient.getTaskQueryService();
            //Login as jcooper
            IWorkflowContext ctx =
                querySvc.authenticate("jcooper", "welcome1".toCharArray(),
                                      null);
            //Set up list of columns to query
            List queryColumns = new ArrayList();
            queryColumns.add("TASKID");
            queryColumns.add("TASKNUMBER");
            queryColumns.add("TITLE");
            queryColumns.add("OUTCOME");
            Predicate pred = new Predicate(TableConstants.WFTASK_TASKID_COLUMN,
            Predicate.OP_EQ, myTaskId);
            //Query a list of tasks assigned to jcooper
            List tasks =
                querySvc.queryTasks(ctx, queryColumns, null, //Do not query additional info
                    ITaskQueryService.AssignmentFilter.MY_AND_GROUP, null, //No keywords
                    pred, //No custom predicate
                    null, //No special ordering
                    0, //Do not page the query result
                    0);
            //Get the task service
            ITaskService taskSvc = wfSvcClient.getTaskService();
            taskSvc.updatePriority(ctx, myTaskId, ITaskService.UpdatePriorityType.UPDATE, newPriority);

        } catch (Exception e) {
            //Handle any exceptions raised here...
            System.out.println("Caught workflow exception: " + e.getMessage());
        }

        return "done";
    }

---------------------------------------------------

Project Libraries -






























Monday, November 11, 2013

#284 - BPM 11g EJB Service Clients

Scenario: Essentially the same as previous post, except we now have the BPM process exposed as an EJB Service. This is a sync BPM process -you probably won't be having many of these - so this is more applicable to BPEL based composites.



















Notice the SyncOrderService.

I deploy the BPM app and check out the ejb in the JNDI tree -











There it is, last in the list.

I now create an ejb jar to package up the EJB from the BPM App -


















The jar will include the SyncBPMProcessPortType which we will leverage in the EJB client.



















I then created a new project and added the jar to it -
















I created a class with the following code -

package niallcsimpleordersejbserviceclient;


import com.example.loanaudit.Order;

import com.oracle.xmlns.bpmn.bpmnprocess.syncbpmprocess.Start;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import java.math.BigDecimal;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import syncbpmprocess.bpmnprocess.bpmn.com.oracle.xmlns.SyncBPMProcessPortType;


public class SimpleOrdersEJBClient {
    public SimpleOrdersEJBClient() {
        super();
    }

       public String initiateProcessByEJB() throws NamingException,
                                                NoSuchMethodException,
                                                Throwable {
        System.out.println("initiateProcessByEJB()");
        Hashtable ht = new Hashtable();
        ht.put(Context.INITIAL_CONTEXT_FACTORY,
               "weblogic.jndi.WLInitialContextFactory");
        ht.put(Context.PROVIDER_URL, "t3://localhost:7001");
        Context ctx;

        ctx = new InitialContext(ht);
           
        Proxy proxy;

        // preparing the method to be called on the remote EJB

        proxy = (Proxy)ctx.lookup("ejb/SyncOrderProcess");
 
        Method method;

        method =
                SyncBPMProcessPortType.class.getDeclaredMethod("start", new Class[] { Start.class });
     
        Start myStart = new Start();
        Order myOrder = new Order();
        myOrder.setCustCountry("IE");
        myOrder.setCustEmail("n@c.com");
        myOrder.setCustFirstName("Niall");
        myOrder.setCustLastName("C");
        myOrder.setExportRestriction("N");
        myOrder.setOrderNr("123");
        myOrder.setProduct("i");
        myOrder.setQuantity(12);
        myOrder.setSupplier("ORCL");
        myOrder.setUnitPrice(new BigDecimal("199.99"));
        myStart.setOrder(myOrder);
     
     
        //
        InvocationHandler handler = Proxy.getInvocationHandler(proxy);
     
     
        handler.invoke(proxy, method, new Object[] { myStart });
   
     
        return "ok";
    }
}

As you can see instantiate a proxy for our EJB, create the required payload(Order) and then
invoke the start method - which is the EJB service exposure of the BPM process start activity. 

I then create a Servlet that will call this client -

package niallcsimpleordersejbserviceclient;

import java.io.IOException;
import java.io.PrintWriter;

import javax.naming.NamingException;

import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends HttpServlet {
    private static final String CONTENT_TYPE = "text/html; charset=windows-1252";

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response) throws IOException {
        response.setContentType(CONTENT_TYPE);
        PrintWriter out;
        String str = "INIT";
        out = response.getWriter();
        
        try{
        SimpleOrdersEJBClient client = new SimpleOrdersEJBClient();
        str = client.initiateProcessByEJB();
        }
        catch (Throwable e) {
            }
        out.println("");
        out.println("TestServlet");
        out.println("");
        out.println("The servlet has received a GET. This is the reply .
");
        out.println("
");
        out.close();
        } 
}

I deploy the Servlet to my AdminServer and test - I then check em to see that a new instance has been created.



#283 - BPM 11g Web Service Clients

Scenario:

I have the following simple process -









Payload is as follows -






















I deploy the composite and then pick up the WSDL from EM
Click on the icon -

















I then create a new "Generic" project in JDev and add a Web Service Proxy based on the above WSDL.

JDev does its magic and all I need to do is add the following code to the auto-generated client

public class NiallCSimpleOrdersProcessPortClient
{
  @WebServiceRef
  private static NiallCSimpleOrdersProcessService niallCSimpleOrdersProcessService;

  public static void main(String [] args)
  {
    niallCSimpleOrdersProcessService = new NiallCSimpleOrdersProcessService();
    NiallCSimpleOrdersProcessPortType niallCSimpleOrdersProcessPortType =
        niallCSimpleOrdersProcessService.getNiallCSimpleOrdersProcessPort();
 
    // MY CODE HERE
    Order order = new Order();
    order.setCustCountry("IE");
    order.setUnitPrice(new BigDecimal("199.99") );
    order.setCustEmail("n@c.com");
    order.setCustFirstName("Niall");
    order.setCustLastName("Commiskey");
    order.setExportRestriction("N");
    order.setOrderNr("123");
    order.setProduct("iToaster");
    order.setQuantity(10);
    niallCSimpleOrdersProcessService.getNiallCSimpleOrdersProcessPort().start(order);
  }
}

I run the client and check for the instance in EM -
















Simple stuff!