Posts Tagged 'API'

Using BPM Java API – Add Attachment

In this post, will show you how to add task attachment using BPM java api.  For demonstration, i am taking simple string for input stream and same can be extended to any file.


public void addAttachment(String taskId, String fileName)
{
IWorkflowContext wfCtx = null;

try
{
String fileContents = "Using the sample string for attachment and this can be a file along with correct mime type";
InputStream is = null;

//creating the attachmenttype
AttachmentType attachmentType = new ObjectFactory().createAttachmentType();

//setting the attributes
attachmentType.setTaskId(taskId);
attachmentType.setName(fileName);
attachmentType.setDescription("From BPM Java API");
attachmentType.setMimeType("text/plain");

//setting the input stream
is = new ByteArrayInputStream(fileContents.getBytes());
attachmentType.setInputStream(is);

//get the admin workflow context
wfCtx = getAdminWorkflowContext();

//Task qryTask = getWfServiceClient().getTaskQueryService().getTaskDetailsById(wfCtx, taskId);
//getWfServiceClient().getTaskService().addAttachment(wfCtx, qryTask, attachmentType);

getWfServiceClient().getTaskService().addAttachment(wfCtx, taskId, attachmentType);
}
catch (Exception ex)
{
System.out.println("in addAttachment exception");
ex.printStackTrace();
}
}

The commented lines in the above code is another way of achieving the same. Pass root task id or any child task id for this method call. We can verify this attachment in WFATTACHMENT table as shown below.

select * from WFATTACHMENT where taskid = ‘c14791b7-7e43-475d-bb9a-003ab05aaf36’

Observations:

  • When roottaskid is used to add the attachments, the task form will show this attachment for all child tasks.
  • addAttachment API is inserting an entry into WFATTCHMENT table even when there is no task id passed.

  • The above behavior can be used in a scenario when we want to add task attachment task creation. To make this works, set the correlation id in attachment type like below and use the same correlation id during task creation.

attachmentType.setCorrelationId(correlationId);

  • By default Admin, Approvers, Assignees, Reviewers, Owner and Creator can add attachments to a task which is configured in Access tab of human task as shown below. We will get an exception when unauthorized user trying to add the attachment as shown below.

<Nov 14, 2017, 2:45:36,118 PM IST> <Error> <oracle.soa.services.workflow.persistency> <BEA-000000> <<.> exception.code:30327
exception.type: ERROR
exception.severity: 2
exception.name: Current user does not have the ADD privilege on task attribute: ATTACHMENTS.
exception.description: Current user siva does not have ADD privilege for ATTACHMENTSon task with taskI
d b4ce32d1-d2e9-4f73-abc0-18c1447facf4.
exception.fix: Grant the ADD access for the current user/role. If the error persists, contact Oracle Support Services.

Advertisement

Using BPM Java API to manipulate Custom Attributes

In this post, will show you how to manipulate Custom attributes using BPM java API.

WFTASK table has the following columns along with columns used for public/private flex fields (Mapped attributes). Refer to this link for more information on mapped attributes.

CUSTOMATTRIBUTESTRING1 VARCHAR2(2000)
CUSTOMATTRIBUTESTRING2 VARCHAR2(2000)
CUSTOMATTRIBUTENUMBER1 NUMBER
CUSTOMATTRIBUTENUMBER2 NUMBER
CUSTOMATTRIBUTEDATE1 DATE
CUSTOMATTRIBUTEDATE2 DATE

BPM worklist also provides a search on these custom attributes as shown below. So when we are creating any custom worklist or in some other scenarios we can always populate these custom attributes using java apis.


public void updateCustomAttributes(String taskId, String customAttrStr1,String customAttrStr2)
{
IWorkflowContext wfCtx = null;

try
{
//creating the customattrtype
CustomAttributesType custAttrType = new ObjectFactory().createCustomAttributesType();
if(customAttrStr1 != null && !customAttrStr1.isEmpty())
{
custAttrType.setCustomAttributeString1(customAttrStr1);
}
if(customAttrStr2 != null && !customAttrStr2.isEmpty())
{
custAttrType.setCustomAttributeString2(customAttrStr2);
}

//get the admin workflow context
wfCtx = getAdminWorkflowContext();

Task qryTask = getWfServiceClient().getTaskQueryService().getTaskDetailsById(wfCtx, taskId);
qryTask.setCustomAttributes(custAttrType);

getWfServiceClient().getTaskService().updateTask(wfCtx, qryTask);
}
catch (Exception ex)
{
System.out.println("in updateCustomAttributes exception");
ex.printStackTrace();
}
}

To test this, send task id and values for custom attributes. We can use the following query to check the values.

select roottaskid, taskid, state,assignees,tasknumber,customattributestring1, customattributestring2
from wftask where roottaskid = ‘c1786a2b-f0a9-4058-aea2-43a0d40713eb’

Observations:

  • We can update these attribute values by passing roottaskid also.
  • When we update only one custom attribute its setting other values to null. To verify this, you can do first iteration by passing both attribute values and pass only one of these attribute values in second iteration of method calls.
  • When custom attributes are set during human task creation using apis, same set of values will be copied to roottaskid and all child tasks.

Using BPM Java API – Add Comments

In this post, we will see how to use BPM java api to add comments to human tasks.

Task Service provides different methods to add comments to a human task as shown below. I will show you how to make use of the method accepting CommentType as argument and using other methods is simple and straight forward.


import oracle.bpel.services.workflow.task.model.CommentType;
import oracle.bpel.services.workflow.task.model.ObjectFactory;
public void addCommentToTask(String taskId, String approverComments)
 { 
 IWorkflowContext wfCtx = null;
 
 try
 {
 //creating the commenttype
 CommentType comments = (new ObjectFactory()).createCommentType();
 comments.setComment(approverComments);
 
 //get the admin workflow context
 wfCtx = getAdminWorkflowContext();
 
 getWfServiceClient().getTaskService().addComment(wfCtx, taskId, comments); 
 }
 catch (Exception ex)
 {
 System.out.println("in addCommentToTask exception");
 ex.printStackTrace();
 } 
 }

Get the child taskid using roottaskid which has to be passed to the above method.

select roottaskid, taskid, state,assignees,tasknumber from wftask where roottaskid = ‘c033ea46-d632-4f4b-acf8-21b2cad709d8’

After executing the above method, we can check the comments using the following sql query.

select * from wfcomments where taskid = ‘c033ea46-d632-4f4b-acf8-21b2cad709d8’

Following piece of code demonstrates the approach to use Task object to add the comment.

 public void addCommentToTask(String taskId, String approverComments)
 { 
 IWorkflowContext wfCtx = null;
 
 try
 {
 //creating the commenttype
 CommentType comments = (new ObjectFactory()).createCommentType();
 comments.setComment(approverComments);
 
 //get the admin workflow context
 wfCtx = getAdminWorkflowContext();
 
 Task qryTask = getWfServiceClient().getTaskQueryService().getTaskDetailsById(wfCtx, taskId);
 getWfServiceClient().getTaskService().addComment(wfCtx, qryTask, comments); 
 }
 catch (Exception ex)
 {
 System.out.println("in addCommentToTask exception");
 ex.printStackTrace();
 } 
 }

Following is another approach of adding task comments using TaskService.updateTask method.


public void addCommentUsingTaskUpdate(String taskId, String approverComments)
{
IWorkflowContext wfCtx = null;

try
{
//creating the commenttype
CommentType comments = (new ObjectFactory()).createCommentType();
comments.setComment(approverComments);

//get the admin workflow context
wfCtx = getAdminWorkflowContext();

Task qryTask = getWfServiceClient().getTaskQueryService().getTaskDetailsById(wfCtx, taskId);
qryTask.addUserComment(comments);

getWfServiceClient().getTaskService().updateTask(wfCtx, qryTask);
}
catch (Exception ex)
{
System.out.println("in addCommentUsingTaskUpdate exception");
ex.printStackTrace();
}
}

Observations:

  • RootTaskId also can be used to add the comments.
  • By default, Admin, Assignees, Owner, Creator, Approvers and Reviewers will have the write access and this can be modified in Access tab of human task definition as shown below.

  • When a user attempt to add comments who does not have access, we will observe the following error in logs. We can reproduce this issue by turning off the write access for Approvers and Assignees in Access tab of human task. Also create the workflowContext using the user siva as siva is the assigness and approver here.

<Nov 14, 2017, 2:45:36,118 PM IST> <Error> <oracle.soa.services.workflow.persistency> <BEA-000000> <<.> exception.code:30327
exception.type: ERROR
exception.severity: 2
exception.name: Current user does not have the ADD privilege on task attribute: COMMENTS.
exception.description: Current user siva does not have ADD privilege for COMMENTS on task with taskI
d b4ce32d1-d2e9-4f73-abc0-18c1447facf4.
exception.fix: Grant the ADD access for the current user/role. If the error persists, contact Oracle Support Services.

Using BPM Java API – Withdraw Task

In this post, we will see how to withdraw a task using BPM Java API. I will use a human task having parallel participant for the demo purpose as shown below.

Following is piece of code to be used for withdrawing a human task.


public void withdrawTask(String taskId)
{
try
{
getWfServiceClient().getTaskService().withdrawTask(getAdminWorkflowContext(), taskId);
}
catch (Exception ex)
{
System.out.println("in withdrawTask exception");
ex.printStackTrace();
}
}

Note: we should destroy the workflow context when there is no need of the same which is not shown here.

Task Service has another variation of withdraw method where we can pass the task object as shown below.


public void withdrawTask(String taskId)
{
Task taskDetail = null;
IWorkflowContext wfCtx = null;

try
{
wfCtx = getAdminWorkflowContext();
taskDetail = getWfServiceClient().getTaskQueryService().getTaskDetailsById(wfCtx, taskId);
getWfServiceClient().getTaskService().withdrawTask(wfCtx, taskDetail);
}
catch (Exception ex)
{
System.out.println("in withdrawTask exception");
ex.printStackTrace();
}
}

To test this code, create a task and query the WFTASK table using roottaskid as shown below. Observe that 2 child tasks are created for the roottaskid as we are using parallel participant with 2 approvers.

Now execute the above method by passing roottaskid. Query the WFTASK table again to verify all tasks are marked as WITHDRAWN as shown below.

Observations:

  • Using roottaskid for withdrawal will result into withdraw of all child tasks.
  • The above statement is true even if some of the child tasks are in approved/rejected state. In this case, using roottaskid will withdraw only the eligible child tasks.
  • The above statement is also true even if some of the child tasks are in ALERTED state. Typically tasks get into this state because BPM runtime unable to resolve the assignee. In the following screenshot, the user siva1 is not existing in my server hence the created task is in ALERTED state.

  • By default, Admin, Creator and Owner of the task can do withdraw of a task. we can see this information in Access tab of human task editor in jdeveloper. Observe the usage of Admin WorkflowContext in the above code.

We will get an error like below when unauthorized user try to withdraw the task. To reproduce the error, we can create the task using weblogic user and try to withdraw that user using another user who is not admin, creator and assignee.

<Nov 13, 2017, 6:19:03,842 PM IST> <Error> <oracle.soa.services.workflow.query> <BEA-000000> <<.> exception.code:30513
exception.type: ERROR
exception.severity: 2
exception.name: Insufficient privileges to access the task information for this task. The task must have either expired or assigned to another user.
exception.description: User siva cannot access the task information for task: fd1df834-04b3-4a5f-a7b5-8bbf83f8dc72.
exception.fix: Ensure that the user has been granted appropriate privileges to access the task information for this task or check on expiration and esclation policies.

  • We can get owner, creator and assignee details for a task using following sql query against soainfra schema.

select roottaskid, taskid, state,assignees,tasknumber,OWNERUSER,CREATOR from wftask where roottaskid = ‘fd1df834-04b3-4a5f-a7b5-8bbf83f8dc72’

Using BPM Java API – WorkflowContext

 

Once the human task instance is created, we can perform several actions like:

  • Withdraw
  • Delegate
  • Update Task outcome
  • Add Attachment
  • Add Comments
  • Query Task details
  • etc..

If we observe these actions, we can guess that all users of the system should not be able to perform these actions and should be controlled through roles/privileges/permissions. So all these actions requires a user context to determine these permissions. BPM APIs accept this user context in form of WorkflowContext. WorkflowContext is a session object maintained by SOA server tied to an user.

How to create workflowcontext for a specific user?

Task Query service has authenticate method that accepts user credentials and returns a WorkflowContext as shown below.


public IWorkflowServiceClient getWfServiceClient()
 {
 IWorkflowServiceClient wfSvcClient = null;

wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT);
return wfSvcClient;
 }

public IWorkflowContext getUserWorkflowContext()
 {
 IWorkflowContext wfCtx = null;
 try
 {
 wfCtx = getWfServiceClient().getTaskQueryService().authenticate("weblogic", "weblogic1".toCharArray(), null);
 }
 catch(WorkflowException wex)
 {
 wex.printStackTrace();
 }

 return wfCtx; 
 }

How to create workflowcontext for a logged in user?

Same Task Query service is used to get workflowcontext for the logged in user as shown below. Make sure that your java/web application is security enabled.

 public IWorkflowContext getLoggedinUserWorkflowContext()
 {
 IWorkflowContext wfCtx = null;
 try
 {
 wfCtx = getWfServiceClient().getTaskQueryService().getWorkflowContextForAuthenticatedUser();
 }
 catch(WorkflowException wex)
 {
 wex.printStackTrace();
 }

 return wfCtx; 
 }

How to create workflowcontext on behalf of a user?

In some of the cases, password may not be available to get the user context but the task actions should be performed by this user. In those cases, we can create admin workflow context and use authenticateOnBehalfOf method of Task Query Service as shown below. Here the user weblogic is admin i.e. having BPMWorkflowAdmin role.

 public IWorkflowContext getOnbehalfOfUserWorkflowContext()
 {
 IWorkflowContext wfCtx = null;
 try
 {
 wfCtx = getWfServiceClient().getTaskQueryService().authenticate("weblogic", "weblogic1".toCharArray(), null);
 wfCtx = getWfServiceClient().getTaskQueryService().authenticateOnBehalfOf(wfCtx, "svgonugu");
 }
 catch(WorkflowException wex)
 {
 wex.printStackTrace();
 }
 return wfCtx; 
 }

How to assign BPMWorkflowAdmin role to an User?

  • Login to EM console and navigate to Weblogic Domain -> <<domainName>> -> Security -> Application Roles.
  • Search for BPMWorkflowAdmin role by choosing soa-infra as application stripe.

search.jpg

  • Click Edit to assign this role to an user and click Add. Note that weblogic user will have admin role by default so the screenshots presented here are only demo purpose.

add.jpg

  • Search for the user weblogic and click ok.

add1

add3.jpg

  • You will observe the following error when try to use authenticateOnBehalfOf method using the workflowcontext created using non-admin user.

ORABPEL-30509

exception.code:30509
exception.type: ERROR
exception.severity: 2
exception.name: Insufficient privileges to authenticate on behalf of another user.
exception.description: User siva cannot authenticate on behalf of user svgonugu without admin privil
eges.
exception.fix: Only users with admin privileges can authenticate on behalf of another user.

Do we have any timeout settings for WorkflowContext?

As mentioned earlier, Workflowcontext is a session object maintained by SOA/BPM server in heap memory. So creating more and more workflowcontexts might cause out of memory errors on the server. So whenever we are done with workflowcontext we should always destroy the context. Also BPM runtime has a default timeout of 60 min after which the workflowcontext object is destroyed. This timeout setting can be modified by navigating to Weblogic Domain -> <<domain name>> -> System MBean Browser -> Application Defined MBeans -> oracle.as.soainfra.config -> Workflow Config -> WorkflowServiceSesionTimeoutInMinutes as shown below.

timeout

If we use workflowcontext after timeout, we will get WorkflowException.

How to destroy WorkflowContext?


getWfServiceClient().getTaskQueryService().destroyWorkflowContext(wfCtx);

Using BPM Java API – wf_client_config.xml

In previous posts (post1 & post2), we have seen how to use SOAP and Remote clients to work with BPM Java APIs. One immediate problem we can see is using server urls in the code which makes deployment across environments difficult. In this post, we will see how to take care of this.

WorkflowServiceClientFactory class has different overloaded methods to get the client. When we don’t pass any properties like below, BPM run time will look for a file wf_client_config.xml in classpath of ear file.


private IWorkflowServiceClient getWfServiceClient()
{
IWorkflowServiceClient wfSvcClient = null;

wfSvcClient = WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT);
return wfSvcClient;
}

We can create wf_client_config.xml with the following contents having the server details and information pertaining to both SOAP and REMOTE clients. The file can be placed in a folder like conf under our project folder.


<?xml version="1.0" encoding="UTF-8"?>
<workflowServicesClientConfiguration xmlns="http://xmlns.oracle.com/bpel/services/client">
<server name="default" default="true">
<remoteClient>
<serverURL>t3://localhost:7005/soa-infra</serverURL>
<userName>weblogic</userName>
<password>weblogic1</password>
<initialContextFactory>weblogic.jndi.WLInitialContextFactory</initialContextFactory>
<participateInClientTransaction>false</participateInClientTransaction>
</remoteClient>
<soapClient>
<rootEndPointURL>http://localhost:7005</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>
</server>
</workflowServicesClientConfiguration>

Include this file in the ear deployment profile using the below steps i.e. corresponding to ADF BC Service project. Create new file group APP-INF/classes as shown below.

app-inf

Add the contributor pointing to conf directory having wf_client_config.xml file.

app-inf1.jpg

Now filters section of APP-INF/classes group should be shown like below.

app-inf2.jpg

Deploy the ear file and re-test your webservice method.

During testing, if the following error is seen in the logs make sure that <?xml version = ‘1.0’ encoding = ‘UTF-8’?> is present as first line in wf_client_config.xml file.

[Exception [EclipseLink-25008] (Eclipse Persistence Services – 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element workflowServicesClientConfiguration was not found in the project]

Since the server details are externalized you can use tokens in wf_client_config.xml and replace them using actual server urls before deploying to specific environments.

 

Using BPM Java API – Creating Human Task (Contd..)

In the previous post, we used SOAP client to invoke BPM java APIs to create a human task. As i mentioned, we will not be able to test remote interface unless we create some java application and deploy to WLS. So in this post, i will create ADF BC Service project to demonstrate this and assume the readers have basic understanding on how to create ADF BC Services.

Following code snippet shows getting the remote client to invoke BPM java API. note the usage of URL.


//admin credentials
private static final String wlsUser = "weblogic";
private static final String wlsPassword = "weblogic1";

//soa-infra url
private static final String soaURL = "t3://localhost:7005/soa-infra";

private Map<CONNECTION_PROPERTY, String> getClientProp(String clientType)
{
Map<CONNECTION_PROPERTY, String> properties = new HashMap<CONNECTION_PROPERTY, String>();

if (WorkflowServiceClientFactory.REMOTE_CLIENT.equals(clientType))
{
properties.put(CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");

//soa-infra url
properties.put(CONNECTION_PROPERTY.EJB_PROVIDER_URL, soaURL);

//admin user
properties.put(CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL, wlsUser);

//admin pwd
properties.put(CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS, wlsPassword);
}
else if (WorkflowServiceClientFactory.SOAP_CLIENT.equals(clientType))
{
properties.put(CONNECTION_PROPERTY.SOAP_END_POINT_ROOT,
"http://localhost:7005");
properties.put(CONNECTION_PROPERTY.SOAP_IDENTITY_PROPAGATION, "non-saml");
}
return properties;
}

private IWorkflowServiceClient getWfServiceClient()
{
IWorkflowServiceClient wfSvcClient = null;

wfSvcClient =
WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.REMOTE_CLIENT,getClientProp(WorkflowServiceClientFactory.REMOTE_CLIENT),null);
return wfSvcClient;
}

The AM method code which is exposed as webservice method remains similar as shown below.


private Element getTaskPayload() throws Exception
{
String payloadStr =
" <payload xmlns=\"http://xmlns.oracle.com/bpel/workflow/task\">" +
"<EmployeeExpenseInput xmlns=\"http://xmlns.oracle.com/expenses/approval/schema\">" +
" <employeeId></employeeId> " + " <firstName></firstName> " + " <lastName></lastName>" +
" <expenseType></expenseType>" + " <expenseDescription></expenseDescription>" +
" <expenseLocation></expenseLocation>" + " <expenseDate></expenseDate>" +
" <amount></amount>" + "</EmployeeExpenseInput>" + " </payload>";
Document doc = null;

try
{
doc = XMLUtil.parseDocumentFromXMLString(payloadStr);
}
catch (Exception e)
{
throw new Exception("Exception in parsing string to xml");
}
return doc.getDocumentElement();
}

public String createHumanTask(String taskTitle)
{
String taskId = null;
IInitiateTaskResponse taskResponse = null;

try
{
ObjectFactory of = new ObjectFactory();
Task newTask = of.createTask();

//set required attribute before calling BPM task api
newTask.setTaskDefinitionId(taskNameSpace);
newTask.setPayloadAsElement(getTaskPayload());
newTask.setCreator(wlsUser);
if(taskTitle == null || taskTitle.isEmpty())
{
newTask.setTitle("BPM API TESTING USING CREATE HUMAN TASK");
}
else
{
newTask.setTitle(taskTitle);
}

newTask.setCategory("TESTING");
newTask.setIdentificationKey("587776676");

taskResponse = getWfServiceClient().getTaskService().initiateTask(newTask);

if (taskResponse != null)
{
newTask = taskResponse.getTask();
taskId = newTask.getSystemAttributes().getTaskId();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return taskId;
}

When the service method is invoked for the first time, we may observe the following error.


<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>JBO-29000: Unexpected exception caught: java.lang.NoClassDefFoundError, msg=oracle/bpel/services/workflow/task/model/ObjectFactory</faultstring>
<detail>
<tns:ServiceErrorMessage xmlns:tns="http://xmlns.oracle.com/adf/svc/errors/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tns:code>29000</tns:code>
<tns:message>JBO-29000: Unexpected exception caught: java.lang.NoClassDefFoundError, msg=oracle/bpel/services/workflow/task/model/ObjectFactory</tns:message>
<tns:severity>SEVERITY_ERROR</tns:severity>
<tns:detail xsi:type="tns:ServiceErrorMessage">
<tns:message>oracle/bpel/services/workflow/task/model/ObjectFactory</tns:message>
<tns:severity>SEVERITY_ERROR</tns:severity>
<tns:exceptionClassName>java.lang.NoClassDefFoundError</tns:exceptionClassName>
</tns:detail>
<tns:exceptionClassName>oracle.jbo.JboException</tns:exceptionClassName>
</tns:ServiceErrorMessage>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>

This error can be resolved by adding oracle.soa.workflow.wc as library reference in weblogic-application.xml. The file can be found in Application Resources -> Descriptors -> META-INF in JDeveloper.


	<library-ref>
	<library-name>oracle.soa.workflow.wc</library-name>
</library-ref>

Testing

Input

input

Output

output

output2

output3.jpg

The sample ADF BC service project can be found here.

Using BPM Java API – Creating Human Task

In the previous post, I described how different participant types work when we use Named User, Approval Group, Application Role etc in the assignment. Now we will see how to use BPM Java APIs in a series of post. I used 12.2.1.2.0 release for demonstration. This article assumes basic working knowledge of Human Workflows and does not get into finer details of the same.

SOA/BPM exposes number of human workflow services as listed below and all these services can be invoked either using SOAP or remote interface with an exception of Identity service which can be invoked only through SOAP interface. You can refer to url for more information on accessing the service and functionality exposed by each. In this post, we will see how to use Task Service to create a human task from java code.

  • Task service
  • Task query service
  • Identity service
  • Task metadata service
  • User metadata service
  • Task report service
  • Runtime config service
  • Evidence store service

Steps:

  • Create a Human Workflow in a SOA composite and deploy to SOA Server.
  • Create a java project in Jdeveloper with a java class having main method.
  • Add BPM Workflow library by navigating to Project properties -> Libraries and Classpath. This jar will have necessary classes to work with human workflow services mentioned above. Note that the libraries Oracle XML Parser V2 and JAX-WS client also need to be added.
  • To call any of the human workflow services, we need to get workflow service client as the first step which can either SOAP or REMOTE. Following snippet of code shows how to get a SOAP based workflow service client.
private IWorkflowServiceClient getWfServiceClient()
{
IWorkflowServiceClient wfSvcClient = null;
wfSvcClient =
WorkflowServiceClientFactory.getWorkflowServiceClient(WorkflowServiceClientFactory.SOAP_CLIENT,
getClientProp(WorkflowServiceClientFactory.SOAP_CLIENT),null);
return wfSvcClient;
}

private Map<CONNECTION_PROPERTY, String> getClientProp(String clientType)
{
Map<CONNECTION_PROPERTY, String> properties = new HashMap<CONNECTION_PROPERTY, String>();
if (WorkflowServiceClientFactory.REMOTE_CLIENT.equals(clientType))
{
properties.put(CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");

//soa-infra url
properties.put(CONNECTION_PROPERTY.EJB_PROVIDER_URL, soaInfraURL);

//admin use
properties.put(CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL, wlsUser);

//admin pwd
properties.put(CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS, wlsPassword);
}
else if (WorkflowServiceClientFactory.SOAP_CLIENT.equals(clientType))
{
properties.put(CONNECTION_PROPERTY.SOAP_END_POINT_ROOT, "http://host:soaPort");
properties.put(CONNECTION_PROPERTY.SOAP_IDENTITY_PROPAGATION, "non-saml");
}
return properties;
}
  • Use the following code to create a task using Task service. You can get task namespace from .task file and is the targetNamespace mentioned there. The Task payload preparation should be as per payload defined in Data section of the human task. Note the usage of workflow service client to get the task service.

private Element getTaskPayload()
throws Exception
{
String payloadStr =
" <payload xmlns=\"http://xmlns.oracle.com/bpel/workflow/task\">" +
"<EmployeeExpenseInput xmlns=\"http://xmlns.oracle.com/expenses/approval/schema\">" +
" <employeeId></employeeId> " + " <firstName></firstName> " + " <lastName></lastName>" +
" <expenseType></expenseType>" + " <expenseDescription></expenseDescription>" +
" <expenseLocation></expenseLocation>" + " <expenseDate></expenseDate>" +
" <amount></amount>" + "</EmployeeExpenseInput>" + " </payload>";
Document doc = null;

try
{
doc = XMLUtil.parseDocumentFromXMLString(payloadStr);
}
catch (Exception e)
{
throw new Exception("Exception in parsing string to xml");
}
return doc.getDocumentElement();
}

public String createHumanTask()
{
String taskId = null;
IInitiateTaskResponse taskResponse = null;

try
{
ObjectFactory of = new ObjectFactory();
Task newTask = of.createTask();

//set required attribute before calling BPM task api
newTask.setTaskDefinitionId(taskNameSpace);
newTask.setPayloadAsElement(getTaskPayload());
newTask.setCreator(wlsUser);
newTask.setTitle("BPM API TESTING USING CREATE HUMAN TASK");
newTask.setCategory("TESTING");
newTask.setIdentificationKey("587776676");

taskResponse = getWfServiceClient().getTaskService().initiateTask(newTask);

if (taskResponse != null)
{
newTask = taskResponse.getTask();
taskId = newTask.getSystemAttributes().getTaskId();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return taskId;
}

  • Similarly, other human workflow services can be accessed using workflow service client. Note that you may not be able to test the remote client from java main method. You need to deploy this to WLS to see it in action.
  • You can download the java project from here.

Pages

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 379 other subscribers

Enter your email address to follow this blog and receive notifications of new posts by email.


%d bloggers like this: