33 Building a Custom Worklist Client

This chapter describes how, starting with the sample Worklist Application, a developer can build clients for workflow services by using the APIs exposed by the workflow service. The APIs enable clients to communicate with the workflow service by using remote EJBs, SOAP, and HTTP.

This chapter includes the following sections:

33.1 Introduction to Building Clients for Workflow Services

When creating a Java client application to call Human Workflow service, ensure that JRF is running on the same environment as the Java client application. The typical sequence of calls when building a simple worklist application is as follows.

To build a simple worklist application:

  1. Get a handle to IWorklistServiceClient from WorkflowServiceClientFactory.
  2. Get a handle to ITaskQueryService from IWorklistServiceClient.
  3. Authenticate a user by passing a username and password to the authenticate method on ITaskQueryService. Get a handle to IWorkflowContext.
  4. Query the list of tasks using ITaskQueryService.
  5. Get a handle to ITaskService from IWorklistServiceClient.
  6. Iterate over the list of tasks returned, performing actions on the tasks using ITaskService.

The code sample below demonstrates how to build a client for workflow services. A list of all tasks assigned to jstein is queried. A task whose outcome has not been set is approved.

try
{
 //Create JAVA WorflowServiceClient
 IWorkflowServiceClient  wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(
  WorkflowServiceClientFactory.REMOTE_CLIENT);
 //Get the task query service
 ITaskQueryService querySvc = wfSvcClient.getTaskQueryService();

 //Login as jstein
 IWorkflowContext ctx = querySvc.authenticate("jstein","welcome1".toCharArry(),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 jstein
 List tasks = querySvc.queryTasks(ctx,
              queryColumns,                   
              null, //Do not query additional info
              ITaskQueryService.AssignmentFilter.MY,
              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...
 for(int i = 0 ; i < tasks.size() ; i ++)
 {
  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();
  if(outcome == null)
  {
   outcome = "APPROVE";
   taskSvc.updateTaskOutcome(ctx,taskId,outcome);
  }
  System.out.println("Task #"+taskNumber+" ("+title+") is "+outcome);
 }

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

33.2 Packages and Classes for Building Clients

Use the following packages and classes for building clients:

  • oracle.bpel.services.workflow.metadata.config.model

    The classes in this package contain the object model for the workflow configuration in the task definition file. The ObjectFactory class can create objects.

  • oracle.bpel.services.workflow.metadata.routingslip.model

    The classes in this package contain the object model for the routing slip. The ObjectFactory class can create objects.

  • oracle.bpel.services.workflow.metadata.taskdisplay.model

    The classes in this package contain the object model for the task display. The ObjectFactory class can create objects.

  • oracle.bpel.services.workflow.metadata.taskdefinition.model

    The classes in this package contain the object model for the task definition file. The ObjectFactory class can create objects.

  • oracle.bpel.services.workflow.client.IWorkflowServiceClient

    The interface for the workflow service client.

  • oracle.bpel.services.workflow.client.WorkflowServiceClientFactory

    The factory for creating the workflow service client.

  • oracle.bpel.services.workflow.metadata.ITaskMetadataService

    The interface for the task metadata service.

  • oracle.bpel.services.workflow.task.ITaskService

    The interface for the task service.

  • oracle.bpel.services.workflow.task.IRoutingSlipCallback

    The interface for the callback class to receive callbacks during task processing.

  • oracle.bpel.services.workflow.task.IAssignmentService

    The interface for the assignment service.

33.3 Workflow Service Clients

Any worklist application accesses the various workflow services through the workflow service client. The workflow service client code encapsulates all the logic required for communicating with the workflow services using different local and remote protocols. After the worklist application has an instance of the workflow service client, it does not need to consider how the client communicates with the workflow services.

The advantages of using the client are as follows:

  • Hides the complexity of the underlying connection mechanisms such as SOAP/HTTP and Enterprise JavaBeans

  • Facilitates changing from using one particular invocation mechanism to another, for example from SOAP/HTTP to remote Enterprise JavaBeans

The following class is used to create instances of the IWorkflowServiceClient interface:

oracle.bpel.services.workflow.client.WorkflowServiceClientFactory

WorkflowServiceClientFactory has several methods that create workflow clients. The simplest method, getWorkflowServiceClient, takes a single parameter, the client type. The client type can be one of the following:

  • WorkflowServiceClientFactory.REMOTE_CLIENT—The client uses a remote Enterprise JavaBeans interface to invoke workflow services located remotely from the client.

  • WorkflowServiceClientFactory.SOAP_CLIENT—The client uses SOAP to invoke web service interfaces to the workflow services, located remotely from the client.

The other factory methods enable you to specify the connection properties directly (rather than having the factory load them from the wf_client_config.xml file), and enable you to specify a logger to log client activity.

The following enhancements to the workflow service clients are included in this release:

  • You can specify the workflow client configuration using either a JAXB object or a map, as shown in example 1 and 2 below:

    Example 1

    WorkflowServicesClientConfigurationType wscct = new  WorkflowServicesClientConfigurationType();
       List<ServerType> servers = wscct.getServer();
       ServerType server = new ServerType();
       server.setDefault(true);
       server.setName(serverName);
       servers.add(server);
    
       RemoteClientType rct = new RemoteClientType();
       rct.setServerURL("t3://stapj73:7001");
       rct.setUserName("weblogic");
       rct.setPassword("weblogic"));
       rct.setInitialContextFactory("weblogic.jndi.WLInitialContextFactory");
       rct.setParticipateInClientTransaction(false);
       server.setRemoteClient(rct);
       IWorkflowServiceClient wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(
                                            WorkflowServiceClientFactory.REMOTE_CLIENT, wscct, logger);
    

    Example 2

    Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY,java.lang.String> properties = new
       HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY,java.lang.String>();
     
    properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.MODE,
       IWorkflowServiceClientConstants.MODE_DYNAMIC);
     
    properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.SOAP_END_POINT_ROOT,
       "http://localhost:8888");
     
    IWorkflowServiceClient client =
       WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.SOAP_CLIENT,
       properties, null);
    
  • Clients can optionally pass in a java.util.logging.Logger where the client logs messages. If no logger is specified, then the workflow service client code does not log anything. The code sample below shows how a logger can be passed to the workflow service clients:

    java.util.logging.Logger logger = ....;
     
    IWorkflowServiceClient client =
     WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT,
     properties, logger);
    

Through the factory, it is possible to get the client libraries for all the workflow services. See Table 34-1 for the clients available for each of the services.

You can obtain instances of BPMIdentityService and BPMIdentityConfigService by calling the getSOAPIdentityServiceClient and getSOAPIdentityConfigServiceClient methods on WorkflowServiceClientFactory. You can obtain all other services through an instance of IWorkflowServiceClient.

The client classes use the configuration file wf_client_config.xml for the service endpoints. In the client class path, this file is in the class path directly, meaning the containing directory is in the class path. The wf_client_config.xml file contains:

  • A section for remote clients, as shown in the code sample below:

<remoteClient>
      <serverURL>t3://hostname.domain_name:7001</serverURL>
  <userName>weblogic</userName>
  <password>weblogic</password>
  <initialContextFactory>weblogic.jndi.WLInitialContextFactory
     </initialContextFactory>
  <participateInClientTransaction>false</participateInClientTransaction>
</remoteClient>
  • A section for SOAP endpoints for each of the services, as shown in the code sample below:

<soapClient>
   <rootEndPointURL>http://hostname.domain_name:7001</rootEndPointURL>
   <identityPropagation mode="dynamic" type="saml">
   <policy-references>
      <policy-reference enabled="true" category="security" 
         uri="oracle/wss10_saml_token_client_policy"/>
      </policy-references>
   </identityPropagation>
</soapClient>

The workflow client configuration XML schema definition is in the wf_client_config.xsd file.

33.3.1 The IWorkflowServiceClient Interface

The IWorkflowServiceClient interface provides methods, summarized in Table 33-1, for obtaining handles to the various workflow services interfaces.


Table 33-1 IWorkflowServiceClient Methods

Method Interface
getTaskService
oracle.bpel.services.workflow.task.ITaskService
getTaskQueryService
oracle.bpel.services.workflow.query.ITaskQueryService
getTaskReportService
oracle.bpel.services.workflow.report.ITaskReportService
getTaskMetadataService
oracle.bpel.services.workflow.metadata.ITaskMetadataService
getUserMetadataService
oracle.bpel.services.workflow.user.IUserMetadataService
getRuntimeConfigService
oracle.bpel.services.workflow.runtimeconfig.IRuntimeConfigService
getTaskEvidenceService
oracle.bpel.services.workflow.metadata.ITaskMetadataService

33.4 Class Paths for Clients Using SOAP

SOAP clients must have the following JAR files in their class path:

$SOA_HOME/soa/modules/oracle.bpm.client_11.1.1/
        oracle.bpm.bpm-services.client.jar
        oracle.bpm.bpm-services.interface.jar
        oracle.bpm.client.jar
        oracle.bpm.web-resources.jar

$SOA_HOME/soa/modules/oracle.bpm.project_11.1.1/
        oracle.bpm.project.catalog.jar
        oracle.bpm.project.draw.jar
        oracle.bpm.project.jar
        oracle.bpm.project.model.jar

$SOA_HOME/soa/modules/oracle.bpm.runtime_11.1.1/
        oracle.bpm.bpm-services.implementation.jar
        oracle.bpm.bpm-services.internal.jar
        oracle.bpm.core.jar
        oracle.bpm.lib.jar
        oracle.bpm.metadata.jar
        oracle.bpm.metadata-interface.jar
        oracle.bpm.papi.jar
        oracle.bpm.xml.jar

$SOA_HOME/soa/modules/oracle.soa.fabric_11.1.1/
        fabric-runtime.jar
        bpm-infra.jar

$SOA_HOME/soa/modules/oracle.soa.workflow_11.1.1/
        bpm-services.jar
        bpm-workflow-datacontrol.jar

$SOA_HOME/soa/modules/
        soa-startup.jar

$MW_HOME/oracle_common/modules/oracle.webservices_11.1.1/
        wsclient.jar

$MW_HOME/oracle_common/modules/oracle.jrf_11.1.1/
        jrf-api.jar

$MW_HOME/wlserver_10.3/server/lib/
        wlthint3client.jar

${bea.home}/wlserver/server/lib/
        wlfullclient.jar

$ORACLE_HOME/soa/plugins/jdeveloper/external/
        oracle.external.soa.jrf-wsclient-extended.jar

${bea.home}/oracle_common/module/clients/
        com.oracle.webservices.wls.jaxws-owsm-client_12.1.3.jar

You can generate the wlfullclient.jar file using the commands shown in the code sample below:

cd ${bea.home}/wlserver/server/lib
java -jar ../../../modules/com.bea.core.jarbuilder_2.2.0.0.jar

Note:

Client applications no longer use the system\services\config or system\services\schema directories in the class path.

33.5 Class Paths for Clients Using Remote EJBs

Clients using remote EJBs must have the following JAR files in their class path:

  • wlfullclient.jar

  • oracle.external.soa.jrf-wsclient-extended.jar

  • wlclient.jar

  • xmlparserv2.jar

  • xml.jar

  • bpm-infra.jar

  • bpm-services.jar

  • fabric-runtime.jar

Note:

Client applications no longer use the system\services\config or system\services\schema directories in the class path.

33.6 Initiating a Task

Tasks can be initiated programmatically, in which case the following task attributes must be set:

  • taskDefinitionId

  • title

  • payload

  • priority

The following task attributes are optional, but are typically set by clients:

  • creator

  • ownerUser—Defaults to bpeladmin if empty

  • processInfo

  • identificationKey—Tasks can be queried based on the identification key from the TaskQueryService.

33.6.1 Creating a Task

The task object model is available in the package

oracle.bpel.services.workflow.task.model

To create objects in this model, use the ObjectFactory class.

33.6.2 Creating a Payload Element in a Task

The task payload can contain multiple payload message attributes. Since the payload is not well defined until the task definition, the Java object model for the task does not contain strong type objects for the client payload. The task payload is represented by the AnyType Java object. The AnyType Java object is created with an XML element whose root is payload in the namespace

http://xmlns.oracle.com/bpel/workflow/task

The payload XML element contains all the other XML elements in it. Each XML element defines a message attribute.

The code sample below shows how to set a task payload:

import oracle.bpel.services.workflow.task.model.AnyType;
import oracle.bpel.services.workflow.task.model.ObjectFactory;
import oracle.bpel.services.workflow.task.model.Task;
..........

Document document = //createXMLDocument
Element payloadElem = document.createElementNS("http://xmlns.oracle.com/bpel/workflow/
  task", "payload");
Element orderElem = document.createElementNS("http://xmlns.oracle.com/pcbpel/test/order", "order");
Element child = document.createElementNS("http://xmlns.oracle.com/pcbpel/test/order", "id");
  child.appendChild(document.createTextNode("1234567"));
  orderElem.appendChild(child); 
  payloadElem.appendChild(orderElem);
  document.appendChild(payloadElem);

  task.setPayloadAsElement(payloadElem);

Note:

The AnyType.getContent() element returns an unmodifiable list of XML elements. You cannot add other message attributes to the list.

33.6.3 Initiating a Task Programmatically

The code sample below shows how to initiate a vacation request task programmatically:

  // create task object
  ObjectFactory objectFactory = new ObjectFactory();
  Task task = objectFactory.createTask();

  // set title
  task.setTitle("Vacation request for jcooper"); 

  // set creator
  task.setCreator("jcooper");
 
// set taskDefinitionId. taskDefinitionId is the target
// namespace of the task 
// If namespace is used, the active version of the composite corresponding 
// to that of the namespace will be used.
task.setTaskDefinitionId("http://xmlns.oracle.com/VacationRequest/
Project1/Humantask1");  (Your task definition ID will be different.)

  // create and set payload 
  Document document = XMLUtil.createDocument();
  Element payloadElem = document.createElementNS(TASK_NS, "payload"); 
  Element vacationRequestElem = document.createElementNS(VACATION_REQUEST_NS,
    "VacationRequestProcessRequest");
 
  Element creatorChild = document.createElementNS(VACATION_REQUEST_NS, "creator");
  creatorChild.appendChild(document.createTextNode("jcooper")); 
  vacationRequestElem.appendChild(creatorChild);
  
  Element fromDateChild = document.createElementNS(VACATION_REQUEST_NS, "fromDate");
  fromDateChild.appendChild(document.createTextNode("2006-08-05T12:00:00")); 
  vacationRequestElem.appendChild(fromDateChild);
  
  Element toDateChild = document.createElementNS(VACATION_REQUEST_NS, "toDate");
  toDateChild.appendChild(document.createTextNode("2006-08-08T12:00:00"));
  vacationRequestElem.appendChild(toDateChild);
  
  Element reasonChild = document.createElementNS(VACATION_REQUEST_NS, "reason");
  reasonChild.appendChild(document.createTextNode("Hunting")); 
  vacationRequestElem.appendChild(reasonChild);
  
  payloadElem.appendChild(vacationRequestElem);
  document.appendChild(payloadElem);
  
  task.setPayloadAsElement(payloadElem);
 
  IWorkflowServiceClient workflowServiceClient =
    WorkflowServiceClientFactory.getWorkflowServiceClient
    (WorkflowServiceClientFactory.SOAP_CLIENT);
  ITaskService taskService = workflowServiceClient.getTaskService(); 
  IInitiateTaskResponse iInitiateTaskResponse = taskService.initiateTask(task); 
  Task retTask = iInitiateTaskResponse.getTask(); 
  System.out.println("Initiated: " + retTask.getSystemAttributes().getTaskNumber() + " - " +
    retTask.getSystemAttributes().getTaskId());
  return retTask;

33.7 Changing Workflow Standard View Definitions

The worklist application and the UserMetadataService API provide methods that you can use to create, update, and delete standard views. See User Metadata Service for more information.

33.8 Writing a Worklist Application Using the HelpDeskUI Sample

The following example shows how to modify the help desk interface that is part of the HelpDeskRequest demo.

To write a worklist application

  1. Create the workflow context by authenticating the user.
    // get workflow service client
      IWorkflowServiceClient wfSvcClient =
        WorkflowServiceClientFactory.getWorkflowServiceClient
        (WorkflowServiceClientFactory.REMOTE_CLIENT);
     
    //get the workflow context
    IWorkflowContext wfCtx =
    wfSvcClient.getTaskQueryService().authenticate(userId, pwd, null);
    

    This is Step 3 in Introduction to Building Clients for Workflow Services.

    The login.jsp file of HelpDeskRequest uses the preceding API to authenticate the user and create a workflow context. After the user is authenticated, the statusPage.jsp file displays the tasks assigned to the logged-in user. Example -00 shows sample code from the login.jsp file.

    <%@ page import="javax.servlet.http.HttpSession"
             import="oracle.bpel.services.workflow.client.IWorkflowServiceClient"
             import="oracle.bpel.services.workflow.client.WorkflowServiceClientFactory"
             import="java.util.Set"
             import="java.util.Iterator"
             import="oracle.bpel.services.workflow.verification.IWorkflowContext"
             import="oracle.tip.pc.services.identity.config.ISConfiguration"%>
    <%@ page contentType="text/html;charset=windows-1252"%>
     
    <html>
    <head>
    <title>Help desk request login page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    </head>
     
    <body bgcolor="#F0F0F0" text="#000000" style="font: 12px verdana; line-height:18px">
    <center>
    <div style="width:640px;padding:15px;border-width: 10px; border-color: #87b4d9; border-style:
     solid;
    background-color:white; text-align:left">
     
        <!-- Page Header, Application banner, logo + user status -->
        <jsp:include page="banner.jsp"/>
       
        <!-- Initiate Meta Information -->
     
        <div style="background-color:#F0F0F0; border-top:10px solid white;border-bottom:
          10px solid white;padding:10px;text-align:center" >
        <b>Welcome to the HelpDesk application</b>
        </div>
     
        <% 
         String redirectPrefix =  "/HelpDeskUI/";
          // Ask the browser not to cache the page
          response.setHeader("Pragma", "no-cache");
          response.setHeader("Cache-Control", "no-cache");
     
          HttpSession httpSession = request.getSession(false);
          if (httpSession != null) {
           
            IWorkflowContext ctx = (IWorkflowContext) httpSession.getAttribute("workflowContext");
            if (ctx != null) {
              response.sendRedirect(redirectPrefix + "statusPage.jsp");
            }
            else
            {
              String authFailedStr = request.getParameter("authFailed"); 
              boolean authFailed = false;
              if ("true".equals(authFailedStr))
              {
                authFailed = true;
              }
              else
              {
                authFailed = false;
              }
     
              if (!authFailed)
              {
                //Get page parameters:
                String userId="";
                if(request.getParameter("userId") != null)
                {
                  userId = request.getParameter("userId");
                }
                String pwd="";
                if(request.getParameter("pwd") != null)
                {
                  pwd = request.getParameter("pwd");
                }
     
                if(userId != null && (!("".equals(userId.trim())))
                   && pwd != null && (!("".equals(pwd.trim()))))   
                {
                  try {
                    HttpSession userSession = request.getSession(true);
     
                    IWorkflowServiceClient wfSvcClient =
                            WorkflowServiceClientFactory.getWorkflowServiceClient
                                    (WorkflowServiceClientFactory.REMOTE_CLIENT);
                    IWorkflowContext wfCtx =
                                wfSvcClient.getTaskQueryService().authenticate(userId, pwd, null);
                    httpSession.setAttribute("workflowContext", wfCtx);
                    response.sendRedirect(redirectPrefix + "statusPage.jsp");
                  }
                  catch (Exception e)
                  {
                    String worklistServiceError = e.getMessage();
                    response.sendRedirect(redirectPrefix + "login.jsp?authFailed=true");
                    out.println("error is " + worklistServiceError);
                  }          
                }
              } else
              {
                out.println("Authentication failed");
              }
            }
          }
        %>
     
        <form action='<%= request.getRequestURI() %>' method="post">
          <div style="width:100%">
          <table cellspacing="2" cellpadding="3" border="0" width="30%" align="center">
            <tr>
              <td>Username
              </td>
              <td>
                <input type="text" name="userId"/>
              </td>
            </tr>
            <tr>
              <td>Password
              </td>
              <td>
                <input type="password" name="pwd"/>
              </td>
            </tr>
            <tr>
              <td>
                <input type="submit" value="Submit"/>
              </td>
            </tr>
          </table>
        </form>
        </div>
    </div>
    </center>
      </body>
    </html>
    
    
  2. Query tasks using the queryTask API from TaskQueryService.
    //add list of attributes to be queried from the task
    List displayColumns = new ArrayList();
         displayColumns.add("TASKNUMBER");
         displayColumns.add("TITLE");
         displayColumns.add("PRIORITY");
         displayColumns.add("STATE");
         displayColumns.add("UPDATEDDATE");
         displayColumns.add("UPDATEDBY");
         displayColumns.add("CREATOR");
         displayColumns.add("OUTCOME");
         displayColumns.add("CREATEDDATE");
         displayColumns.add("ASSIGNEEUSERS");
         displayColumns.add("ASSIGNEEGROUPS");
         // get the list of tasks
         List tasks =  wfSvcClient.getTaskQueryService().queryTasks
                            (wfCtx,
                            displayColumns,
                            null,
                            ITaskQueryService.AssignmentFilter.MY_AND_GROUP,
                            null,
                            null,
                            null,
                            0,
                            0);
        // create listing page by using above tasks
        //add href links to title to display details of the task by passing taskId
          as input parameter
       Use getTaskDetailsById(IWorkflowContext wftx, String taskId);
    

    This is Step 4 in Introduction to Building Clients for Workflow Services.

    The statusPage.jsp file of HelpDeskRequest is used to display the status of help desk requests. The code sample below shows the statusPage.jsp.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <%@ page import="oracle.tip.pc.services.identity.BPMAuthorizationService,
                     oracle.bpel.services.workflow.verification.IWorkflowContext,
                     oracle.tip.pc.services.common.ServiceFactory,
                     oracle.bpel.services.workflow.client.IWorkflowServiceClient,
                     oracle.bpel.services.workflow.client.WorkflowServiceClientFactory,
                     oracle.bpel.services.workflow.query.ITaskQueryService,
                     oracle.bpel.services.workflow.task.model.Task,
                     oracle.bpel.services.workflow.task.model.IdentityType,
                     oracle.tip.pc.services.identity.BPMUser,
                     java.util.List,
                     java.util.Calendar,
                     java.text.SimpleDateFormat,
                     java.util.ArrayList"%>
    <%@ page contentType="text/html;charset=UTF-8"%>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>RequestPage</title>
        <style TYPE="text/css">
          Body, Form, Table, Textarea, Select, Input, Option
          {  
            font-family : tahoma, verdana, arial, helvetica, sans-serif;
            font-size : 9pt;
          }
          table.banner
          {
            background-color: #eaeff5;
          }
          tr.userInfo
          {
            background-color: #eaeff5;
          }
          tr.problemInfo
          {
            background-color: #87b4d9;
          }
        </style>
      </head>
      <body bgcolor="White">
      <%
         HttpSession httpSession = request.getSession(false);
         httpSession.setAttribute("pageType","STATUSPAGE");
      %>
      <table bordercolor="#eaeff5" border="4" width="100%">
        <tr><td> <jsp:include page="banner.jsp"/> </td></tr>
      </table>
      <%
          BPMUser bpmUser = null;
          String redirectPrefix =  request.getContextPath() + "/";
          IWorkflowContext ctx = null;
          if (httpSession != null) {
            
            ctx = (IWorkflowContext) httpSession.getAttribute("workflowContext");
            if (ctx != null) {
                bpmUser = getAuthorizationService(ctx.getIdentityContext()).
                                 lookupUser(ctx.getUser());
            }
            else
            {
               response.sendRedirect(redirectPrefix + "login.jsp");
               return;
            }
          }
          else
          {
             response.sendRedirect(redirectPrefix + "login.jsp");
             return;
          }
          if(bpmUser == null)
          {
            response.sendRedirect(redirectPrefix + "login.jsp");
             return;
          }
          String status = (String)httpSession.getAttribute("requeststatus");
          if(status != null && !status.equals(""))
          {
        %>
           <p></p>
           <div style="text-align:left;color:red" >
             <%= status %>
           </div>
        <%    
          }
          httpSession.setAttribute("requeststatus",null);
          IWorkflowServiceClient  wfSvcClient =
                            WorkflowServiceClientFactory.getWorkflowServiceClient(
                                     WorkflowServiceClientFactory.REMOTE_CLIENT);
          List displayColumns = new ArrayList();
          displayColumns.add("TASKNUMBER");
          displayColumns.add("TITLE");
          displayColumns.add("PRIORITY");
          displayColumns.add("STATE");
          displayColumns.add("UPDATEDDATE");
          displayColumns.add("UPDATEDBY");
          displayColumns.add("CREATOR");
          displayColumns.add("OUTCOME");
          displayColumns.add("CREATEDDATE");
          displayColumns.add("ASSIGNEEUSERS");
          displayColumns.add("ASSIGNEEGROUPS");
          List tasks =  wfSvcClient.getTaskQueryService().queryTasks
                            (ctx,
                            displayColumns,
                            null,
                            ITaskQueryService.ASSIGNMENT_FILTER_CREATOR,
                            null,
                            null,
                            null,
                            0,
                            0);
      %>
      <p></p>
      <div style="text-align:left;color:green" >
       <b>
        Previous help desk request
       </b>
      </div>
      <p></p>
      <div style="text-align:center" >
      <table cellspacing="2" cellpadding="2" border="3" width="100%">
         <TR class="problemInfo">
             <TH>TaskNumber</TH>
             <TH>Title</TH>
             <TH>Priority</TH>
             <TH>CreatedDate</TH>
             <TH>Assignee(s)</TH>
             <TH>UpdatedDate</TH>
             <TH>UpdatedBy</TH>
             <TH>State</TH>
             <TH>Status</TH>
         </TR>
         <%
           SimpleDateFormat dflong = new SimpleDateFormat( "MM/dd/yy hh:mm a" );
           for(int i = 0 ; i < tasks.size() ; i ++)
           {
              Task task = (Task)tasks.get(i);
              int taskNumber = task.getSystemAttributes().getTaskNumber();
              String title = task.getTitle();
              int priority = task.getPriority();
              String assignee = getAssigneeString(task);
              Calendar createdDate = task.getSystemAttributes().getCreatedDate();              
              Calendar updateDate =  task.getSystemAttributes().getUpdatedDate();
              String updatedBy = task.getSystemAttributes().getUpdatedBy().getId();
              String state = task.getSystemAttributes().getState();
              String outcome = task.getSystemAttributes().getOutcome();
              if(outcome == null) outcome = "";
              String titleLink = "http://" + request.getServerName() +
                                 ":" + request.getServerPort() +
                                  "/integration/worklistapp/TaskDetails?taskId=" +  
                                  task.getSystemAttributes().getTaskId();
          %>
            <tr class="userInfo">
               <td><%=taskNumber%></td>
               <td><a href="<%=titleLink%>" target="_blank"><%=title%></a></td>
               <td><%=priority%></td>
               <td><%=dflong.format(createdDate.getTime())%></td>
               <td><%=assignee%></td>
               <td><%=dflong.format(updateDate.getTime())%></td>
               <td><%=updatedBy%></td>
               <td><%=state%></td>
               <td><%=outcome%></td>
            <tr>
         <%
           }
         %>
      </table>
      </div>
      <%!
          private BPMAuthorizationService getAuthorizationService(String identityContext)
          {
           BPMAuthorizationService authorizationService =
     ServiceFactory.getAuthorizationServiceInstance();
           if (identityContext != null)
             authorizationService = ServiceFactory.getAuthorizationServiceInstance(identityContext);
     
           return authorizationService;
          }
          private String getAssigneeString(Task task) throws Exception
          {
             List assignees = task.getSystemAttributes().getAssigneeUsers();
             StringBuffer buffer = null;
             for(int i = 0 ; i < assignees.size() ; i++)
             {
               IdentityType type = (IdentityType)assignees.get(i);
               String name = type.getId();
               if(buffer == null)
               {
                  buffer = new StringBuffer();
               }
               else
               {
                 buffer.append(",");
               }
               buffer.append(name).append("(U)");
             }
             assignees = task.getSystemAttributes().getAssigneeGroups();
             for(int i = 0 ; i < assignees.size() ; i++)
             {
               IdentityType type = (IdentityType)assignees.get(i);
               String name = type.getId();
               if(buffer == null)
               {
                  buffer = new StringBuffer();
               }
               else
               {
                 buffer.append(",");
               }
               buffer.append(name).append("(G)");
             }
             if(buffer == null)
             {
                return "";
             }
             else
             {
               return buffer.toString();
             }
          }
      %>
     </body>
    </html>