Code review

This section describes the steps that are necessary in order to create and execute queries based on query properties using the query() API. Before these queries can be executed, it is required to create the query properties in the business process, as described in the Build it Yourself section.

Required Java libraries

Several Java libraries have to be imported for this sample:

import com.ibm.bpe.api.*;
import javax.naming.*;
import java.util.TimeZone;

Configuring the Deployment Descriptor

In order to be able to process queries, the stateless session EJB that represents the public API of the Business Process Choreographer has to be accessed. For this, the remote session bean or the local session bean are available. In this sample, the local session bean is used. To be able to access the BusinessFlowManager EJB, it is necessary to add a reference to this EJB to the deployment descriptor of your client application. The reference to the local home interface for process applications is shown in the following code snippet:

<ejb-local-ref>
   <ejb-ref-name>ejb/LocalBusinessFlowManagerHome</ejb-ref-name>
   <ejb-ref-type>Session</ejb-ref-type>
   <local-home>com.ibm.bpe.api.LocalBusinessFlowManagerHome</local-home>
   <local>com.ibm.bpe.api.LocalBusinessFlowManager</local>
</ejb-local-ref>

Subsequently, the binding has to be added to the EJB reference. You can do this in the lower right field of the "References" tab of the Deployment Descriptor Editor:

Accessing the BusinessFlowManager bean

The following code snippet shows how to create the BusinessFlowManager using the Java Naming and Directory Interface (JNDI) lookup mechanism:

// Obtain the default initial JNDI context
Context initialContext = new InitialContext();

// Lookup the local home interface of the LocalBusinessFlowManager bean
Object resultLookup = initialContext.lookup("java:comp/env/ejb/LocalBusinessFlowManagerHome");

// Convert the lookup to the proper type
LocalBusinessFlowManagerHome processHome = (LocalBusinessFlowManagerHome)resultLookup;

//Create the EJB
LocalBusinessFlowManager flowManager = processHome.create();

Retrieving the defined query properties

It is possible to retrieve all query properties that have been defined for a specific process template. To do so, either the name of the process template or the process template ID (PTID) have to be known, and the following method has to be used:

java.util.List queryProperties = flowManager.getQueryProperties(<identifier>);

The placeholder <identifier> has to be replaced with either the process template name or ID. The list returned by the method contains objects of the type QueryProperty, which hold the description of the query properties defined for the specified process template.

Performing a query

Each query consists of a select, where and order-by part, as described in the Overview section of this sample. The following code snippet shows how to invoke the query consisting of these three SQL-like strings:

String selectClause = <selectPart>;
String whereClause = <wherePart>;
String orderByClause = <orderByPart>;

QueryResultSet result = flowManager.query(selectClause,
                                          whereClause,
                                          orderByClause,
                                          (Integer)null,
                                          (Integer)null,
                                          (TimeZone)null);

The sample queries

The queries used in this sample will now be explained in detail. They are created and processed in the performQuery.jsp file, which is part of the sample project that can be downloaded in the Download section.

Query 1: All tasks

The following code extract is the query that is used in this sample in order to retrieve all insurance claim review tasks that still have to be processed:

selectClause =
      "TASK.TKIID," +
      "TASK.NAME," +
      "TASK_DESC.DESCRIPTION," +
      "PROCESS_INSTANCE.PIID," +
      "PROCESS_INSTANCE.NAME," +
      "QUERY_PROPERTY0.NUMBER_VALUE," +
      "QUERY_PROPERTY1.STRING_VALUE," +
      "QUERY_PROPERTY2.NUMBER_VALUE";

whereClause =
      "TASK.STATE = TASK.STATE.STATE_READY AND " +
      "TASK.KIND = TASK.KIND.KIND_PARTICIPATING AND " +
      "WORK_ITEM.REASON = WORK_ITEM.REASON.REASON_POTENTIAL_OWNER AND " +
      "TASK_DESC.LOCALE = 'default' AND " +
      "QUERY_PROPERTY0.NAME = 'customerID' AND " +
      "QUERY_PROPERTY1.NAME = 'claimDescription' AND " +
      "QUERY_PROPERTY2.NAME = 'claimAmount'";

orderByClause =
      "QUERY_PROPERTY2.NUMBER_VALUE DESC";

The where clause states that only those tasks will be returned that are in the state ready (TASK.STATE = TASK.STATE.STATE_READY) and that are participating tasks (TASK.KIND = TASK.KIND.KIND_PARTICIPATING). This is being done because the task list should only contain insurance claim review tasks that still have to be worked on. Moreover, only those tasks should be included for which the employee who is performing the query is a potential owner (WORK_ITEM.REASON = WORK_ITEM.REASON.REASON_POTENTIAL_OWNER). The task information that will be returned also contains the description of the task, and this text should be returned in the default locale. Therefore, the where clause has to specify this requirement (TASK_DESC.LOCALE = 'default').
In addition to these conditions, the where clause also specifies three query properties QUERY_PROPERTY0, QUERY_PROPERTY1 and QUERY_PROPERTY2, which will be used in the select clause to provide the customer ID and the claim information for each task. As can be seen in the code extract, the query properties in this sample are identified by specifying their names, which can be done because these names are unique in the sample process. For details, refer to the Overview section.

Note:

When multiple query properties are being used in the arguments of a query, the name of the QUERY_PROPERTY view has to be extended with a number ranging from 0 to 9. For example, QUERY_PROPERTY0.

The select clause defines the data that will be returned by the query in the result set. By combining the specified query properties and information from the predefined task view, task description view, and process instance view, the query will return for each matching task:

  • the task instance ID,
  • the name,
  • the description,
  • the ID and the name of the process instance the task is part of,
  • the ID of the customer, and
  • the amount and the description of the claim.

Finally, the orderBy clause specifies how the result set of the query will be sorted. In this case, it will be sorted by claim amount in descending order, i.e. the insurance claim review task with the highest claim amount will be in the first place.

Note:

Be aware that only those tasks will be included in the query's result set which contain all query properties that are specified in the query. In this example, only those tasks will be returned which are part of processes that contain the query properties customerID, claimDescription and claimAmount.

Query 2: All tasks for a given customer ID

The following code extract is the query that is used in this sample in order to retrieve all insurance claim review tasks that still have to be processed for a given customer ID:

selectClause =
      "TASK.TKIID," +
      "TASK.NAME," +
      "TASK_DESC.DESCRIPTION," +
      "PROCESS_INSTANCE.PIID," +
      "PROCESS_INSTANCE.NAME," +
      "QUERY_PROPERTY1.STRING_VALUE," +
      "QUERY_PROPERTY2.NUMBER_VALUE";

whereClause =
      "TASK.STATE = TASK.STATE.STATE_READY AND " +
      "TASK.KIND = TASK.KIND.KIND_PARTICIPATING AND " +
      "WORK_ITEM.REASON = WORK_ITEM.REASON.REASON_POTENTIAL_OWNER AND " +
      "TASK_DESC.LOCALE = 'default' AND " +
      "QUERY_PROPERTY0.NAME = 'customerID' AND " +
      "QUERY_PROPERTY0.NUMBER_VALUE = "+idInput+" AND " +
      "QUERY_PROPERTY1.NAME ='claimDescription' AND " +
      "QUERY_PROPERTY2.NAME ='claimAmount'";

orderByClause =
      "QUERY_PROPERTY2.NUMBER_VALUE DESC";

The are two differences to Query 1:

  1. The select clause does not contain QUERY_PROPERTY0.NUMBER_VALUE, because the customer ID is already known and there is no need to return it as part of the query.
  2. The where clause specifies the additional condition that only those task instances should be returned whose value for the customer ID equals the given customer ID idInput.