Wednesday, 28 February 2018
Generate BPM process audit through API
package com.poc.bpm.task;
import com.poc.WfAudit;
import com.poc.ProcessUtils;
import java.io.IOException;
import oracle.bpm.services.instancequery.IAuditConstants;
import oracle.bpm.collections.Sequence;
import java.util.ArrayList;
import java.util.List;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.IWorkflowConstants;
import oracle.bpel.services.workflow.WorkflowException;
import oracle.bpel.services.workflow.query.ITaskQueryService;
import oracle.bpel.services.workflow.repos.Ordering;
import oracle.bpel.services.workflow.repos.Predicate;
import oracle.bpel.services.workflow.repos.TableConstants;
import oracle.bpel.services.workflow.task.ITaskAssignee;
import oracle.bpel.services.workflow.task.ITaskService;
import oracle.bpel.services.workflow.task.impl.TaskAssignee;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpm.project.model.processes.Activity;
import oracle.bpm.project.model.processes.SendTask;
import oracle.bpm.project.model.processes.conversation.Conversation;
import oracle.bpm.project.model.processes.conversation.ProcessCallConversationDefinition;
import oracle.bpm.services.instancemanagement.model.IProcessInstance;
import oracle.bpm.services.instancequery.IAuditInstance;
import oracle.bpm.services.instancequery.IColumnConstants;
import oracle.bpm.services.instancequery.IInstanceQueryInput;
import oracle.bpm.services.instancequery.IInstanceQueryService;
import oracle.bpm.services.instancequery.impl.InstanceQueryInput;
import oracle.bpm.services.internal.processmodel.model.IProcessModelPackage;
import oracle.bpm.services.processmetadata.ProcessMetadataSummary;
import oracle.bpel.services.workflow.repos.Column;
import oracle.bpm.services.common.exception.BPMException;
public class AuditServiceClient {
private static final Logger LOGGER = Logger.getLogger("oracle.soa.Logger");
private ProcessUtils _processUtils;
private static final String AUDIT = "AUDIT";
private static final String COMPLETE = "COMPLETE";
private static final String TASKNUMBER = "TASKNUMBER";
private static final String TITLE = "TITLE";
private static final String PRIORITY = "PRIORITY";
private static final String STATE = "STATE";
private static final String ENDDATE = "ENDDATE";
IBPMContext ctx = null;
public AuditServiceClient(String adminUser, String adminPassword, String host, String port) { //
try {
_processUtils = new ProcessUtils(ProcessUtils.getServiceClientFactory(host, port));
ctx =
(IBPMContext) _processUtils.getWorkflowServiceClient().getTaskQueryService().authenticate(adminUser,
adminPassword.toCharArray(),
null);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "\r\ne: " + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] argv) {
AuditServiceClient c = new AuditServiceClient("weblogic", "password1$", "localhost", "7001");
long startTm = System.currentTimeMillis();
List<WfAudit> auditTrail = c.getAuditEntries("2d520f16-0665-4d8a-b9c3-4fe0f71595b6-0001930e");
long endTm = System.currentTimeMillis();
System.out.println(endTm-startTm);
for(WfAudit a : auditTrail){
System.out.println(a.getActivity()+"::"+a.getAction()+"::"+a.getParticipant()+"::"+a.getDt());
}
//List<WfAudit> auditTrail = c.prepareInstanceAudit("140010");//30002, ,140010
}
public List<WfAudit> getAuditEntries(String workItemId) {
List<WfAudit> auditTrail = null;
try{
String instanceId = this.getInstanceId(workItemId);
auditTrail = this.prepareInstanceAudit(instanceId);
auditTrail.sort(Comparator.comparing(o -> o.getDt()));
}catch(Exception ex){
ex.printStackTrace();
}
return auditTrail;
}
private String getInstanceId(String ecid) throws Exception {
List<Column> columns = new ArrayList<Column>();
columns.add(IColumnConstants.PROCESS_ID_COLUMN);
columns.add(IColumnConstants.PROCESS_ECID_COLUMN);
columns.add(IColumnConstants.PROCESS_INSTANCEID_COLUMN);
Ordering ordering = new Ordering(IColumnConstants.PROCESS_INSTANCEID_COLUMN, true, true);
Predicate pred = new Predicate(IColumnConstants.PROCESS_ECID_COLUMN, Predicate.OP_EQ, ecid);
IInstanceQueryInput input = new InstanceQueryInput();
input.setAssignmentFilter(IInstanceQueryInput.AssignmentFilter.ALL);
List<IProcessInstance> instances =
_processUtils.getBPMServiceClient().getInstanceQueryService()
.queryProcessInstances(ctx, columns, pred,ordering, input);
if(!instances.isEmpty())
return instances.get(0).getSystemAttributes().getProcessInstanceId();
return null;
}
private List<WfAudit> prepareInstanceAudit(String instanceId) {
List<WfAudit> auditTrail = new ArrayList<>();
try {
List<IAuditInstance> auditInstances =
_processUtils.getBPMServiceClient().getInstanceQueryService().queryAuditInstanceByProcessId(ctx,
instanceId);
for (IAuditInstance audit : auditInstances) {
if("USER_TASK".equals(audit.getActivityName())){
WfAudit a = new WfAudit();
a.setActivity(audit.getLabel());
a.setDt(audit.getCreateTime().getTime());
a.setAction("START".equals(audit.getAuditInstanceType())?"ASSIGNED":"COMPLETED");
a.setParticipant(audit.getParticipant());
auditTrail.add(a);
}
if (audit.getActivityName().equals("SEND_TASK") && audit.getAuditInstanceType().equals("START")) {
String invokedProcessName = getInvokedProcess(audit.getActivityId(),audit.getProcessName());
searchInstance(invokedProcessName,audit.getFlowId(), auditTrail);
}
}
} catch (Exception we) {
we.printStackTrace();
}
return auditTrail;
}
private String getInvokedProcess(String activityId, String processName) throws Exception {
ProcessMetadataSummary metadata =
_processUtils.getMetadataForProcess(ctx, processName, null); //TODO: "1.2"
IProcessModelPackage p = _processUtils.getBPMServiceClient().getProcessModelService().getProcessModel(ctx, metadata.getCompositeDN(), processName);
Iterator<Activity> it = p.getProcessModel().getActivities().iterator();
Sequence<Conversation> conversations = p.getProcessModel().getConversations();
while(it.hasNext()){
Activity act = it.next();
if(act.getId().equals(activityId)){
SendTask sendTask = act.as(SendTask.class);
for(Conversation conv : conversations){
if(conv.getId().equals(sendTask.getConversation().getId())){
ProcessCallConversationDefinition pcallConvDef = (ProcessCallConversationDefinition)conv.getConversationDefinition();
return pcallConvDef.getProcessRef().getName();
}
}
}
}
return null;
}
private void searchInstance(String processName,long flowId, List<WfAudit> auditTrail) throws Exception {
String expression = IAuditConstants.COLUMN_COMPONENTNAME + " like '%"+processName +"%'";// and "+IAuditConstants.COLUMN_QUERYID +" = "+flowId;
List<IAuditInstance> auditInstances =
_processUtils.getBPMServiceClient().getInstanceQueryService().queryAuditInstances(ctx, expression);
for (IAuditInstance audit : auditInstances) {
if (audit.getFlowId()==flowId){
if("USER_TASK".equals(audit.getActivityName())){
WfAudit a = new WfAudit();
a.setActivity(audit.getLabel());
a.setDt(audit.getCreateTime().getTime());
a.setAction("START".equals(audit.getAuditInstanceType())?"ASSIGNED":"COMPLETED");
a.setParticipant(audit.getParticipant());
auditTrail.add(a);
}
else if ("SEND_TASK".equals(audit.getActivityName()) && "START".equals(audit.getAuditInstanceType())){
String invokedProcessName = getInvokedProcess(audit.getActivityId(),audit.getProcessName());
searchInstance(invokedProcessName,audit.getFlowId(), auditTrail);
}
}
}
}
}
Using Credential Store to store the UserId/password
While using Oracle BPM APIs in a project, quite often most of us come access the requirement of storing the BPM Administrator user's credential to be used to create the BPMContext. One of most commonly used technique is to store the username and password in a properties file. For security reasons, the password is encrypted before storing in the properties file. This addresses the purpose in most of the cases.
In some of my recent engagements I faced challenge with this approach as SOA Infrastructure Team (Managed by Client) said that they would not handover the BPM Administrator user credential to the Application Team to store it at the application side. They also often change the password of the BPM Administrator user, which would require higher co-ordination in case it is stored at the application side ( may be in a properties file).
The solution for this scenario was using WebLogic Credential Store. We created a credential map through Enterprise Manager, where SOA Infrastructure Team is going to key in the BPM Administrator user name and password. As and when they change the password of the user, it is upto them to login to EM and update the password in the Credential Store. We will programmatically access the username and password from this Credential Store.
Step 1 - Create Credential Store
a. Log on to Enterprise Manager.
b. Go to Weblogic Domain>>Security>>Credentials
c. Create
a map and a key within the map –
Remember
the map and the key name. In the code we will refer to this map and key to
retrieve the username and password.
Step 2 - Edit system-jazn-data.xml file
Open <MW_HOME>\user_projects\domains\<DOMAIN
NAME>\config\fmwconfig\system-jazn-data.xml
Scroll to the end of file, add the following block
within <jazn-policy></jazn-policy>
<grant>
<permissions>
<permission>
<class>oracle.security.jps.service.credstore.CredentialAccessPermission</class>
<name>context=SYSTEM,mapName={mapName},keyName={keyname}</name>
<actions>read</actions>
</permission>
</permissions>
<permission-set-refs>
</permission-set-refs>
</grant>
Replace { mapName } and {keyname} with the one
that you have configured in step 2
Step 3 - Set BpelcClasspath property
a. Login to Enterprise Manager
b. Goto
SOA Infrastructure > SOA Administrator > BPMN properties
c. Goto
“More BPMN Configuration Properties...”
d. set the BpelcClasspath property value to
<MW_HOME>/oracle_common/modules/oracle.jps/jps-manifest.jar
Step 4 - Edit WebLogic.policy file
a. Open /wlserver/server/lib/weblogic.policy
grant codeBase
"file:/user_projects/domains//servers/-"
{
permission
oracle.security.jps.service.credstore.CredentialAccessPermission
"context=SYSTEM,mapName={mapName},keyName={keyName}", "read";
};
Step 5 - Restart the server ( admin and managed servers)
Create a java project and add “BC4J Securities library” in the class path.
Create a class CredentialStorePoc as follows -
import
java.security.AccessController;
import
java.security.PrivilegedActionException;import java.security.PrivilegedExceptionAction;
import oracle.security.jps.JpsException;
import oracle.security.jps.service.JpsServiceLocator;
import oracle.security.jps.service.ServiceLocator;
import oracle.security.jps.service.credstore.PasswordCredential;
import oracle.security.jps.service.credstore.CredentialStore;
public class
CredentialStorePoc {
public CredentialStorePoc() {
super();}
private static PasswordCredential
_getCredentials(String map, String key) throws JpsException {
ServiceLocator locator =
JpsServiceLocator.getServiceLocator();CredentialStore credentialStore = JpsServiceLocator.getServiceLocator().lookup(CredentialStore.class);
return (PasswordCredential) credentialStore.getCredential(map, key);
}
public static String getCredentials(final
String map, final String key) {
PasswordCredential credentials;PrivilegedExceptionAction<PasswordCredential> action = new
PrivilegedExceptionAction<PasswordCredential>() {
public PasswordCredential run() throws JpsException {
return _getCredentials(map, key);
}
};
try {
credentials =
AccessController.doPrivileged(action);} catch (PrivilegedActionException e) {
throw new RuntimeException(e);
}
System.out.println(credentials.getName());
System.out.println(credentials.getPassword());return credentials.getName();
}
}
Promoting Views/Flex Fields defined using workspace in lower environment to higher environment
Often we use views and protected flex fields in a BPM project. These are one of those few artifacts that resides outside of your main source code (BPM Application and BPM project in your jdeveloper). During development the BPM developers login to bpm workspace running on their local bpm runtime (most cases a local compact bpm domain or bpm domain on integrated weblogic ).
So the question is, how we promote these configuration to another environment. Certainly manually making the same changes in the each of the higher environment is erroneous and thus ruled out. The suggested option is to export the configuration from local environment into XML files, store it in the source control system and deploy through script to other environment. the step are illustrated as below -
Export
Flex fields and Views
Login to the server from
which you want to export.
> cd
<MW_HOME>\soa\bin
> set ANT_HOME=<Your
Path>\apache-ant-1.10.1
> set
PATH=%ANT_HOME%\bin\;%PATH%
Export
Flex fields
ant -v -f
ant-t2p-worklist.xml -Dbea.home={ MW_HOME } -Dsoa.home={ MW_HOME/soa }
-Dsoa.hostname={hostname} -Dsoa.rmi.port={port} -Dsoa.admin.user={admin user
name}-Dsoa.admin.password={admin password} -Drealm=jazn.com -Dmigration.file={full
path with filename to store generated flex_data.xml}
-Dmap.file=={full path with filename to
store generated flex_data_map.xml } -DoperationType=EXPORT
-DobjectType=TASK_PAYLOAD_FLEX_FIELD_MAPPING -Dname=ALL -Duser={bpm admin user}
-DgrantPermission=true
-DmigrateAttributeLabel=true
Parameters -
-Dbea.home=<MW_HOME>
-Dsoa.home=<MW_HOME>/soa
-Dsoa.hostname=Server ip/name
-Dsoa.rmi.port=Server port
-Dsoa.admin.user=admin user
-Dsoa.admin.password=admin
user p
-Drealm=realname
-Dmigration.file=file in
which the data will be exported
-Dmap.file=File in which mapping data will be exported
Example -
ant -v -f ant-t2p-worklist.xml
-Dbea.home=C:/Oracle/Middleware/Oracle_Home
-Dsoa.home=C:/Oracle/Middleware/Oracle_Home/soa -Dsoa.hostname=localhost
-Dsoa.rmi.port=7001 -Dsoa.admin.user=weblogic -Dsoa.admin.password=password1$
-Drealm=jazn.com -Dmigration.file=C:/workspace/ViewMigration/data/flex_data.xml
-Dmap.file=C:/workspace/ViewMigration/data/flex_data_map.xml
-DoperationType=EXPORT -DobjectType=TASK_PAYLOAD_FLEX_FIELD_MAPPING -Dname=ALL
-Duser=weblogic -DgrantPermission=true
-DmigrateAttributeLabel=true
To
export Views
ant -v -f
ant-t2p-worklist.xml -Dbea.home={ MW_HOME } -Dsoa.home={ MW_HOME/soa }
-Dsoa.hostname={hostname} -Dsoa.rmi.port={port} -Dsoa.admin.user={admin user
name}-Dsoa.admin.password={admin password} -Drealm=jazn.com -Dmigration.file={full
path with filename to store generated view_data.xml}
-Dmap.file=={full path with filename to
store generated view_data_map.xml } -DoperationType=EXPORT -DobjectType= VIEW
-Dname=ALL -Duser={bpm admin user} -DgrantPermission=true -DmigrateAttributeLabel=true
Parameters -
Most of the parameters
remains same as Export Flex Fields
-DobjectType=VIEW
Example –
ant -f ant-t2p-worklist.xml
-Dbea.home=C:/Oracle/Middleware/Oracle_Home -Dsoa.home=C:/Oracle/Middleware/Oracle_Home/soa
-Dsoa.hostname=localhost -Dsoa.rmi.port=7001 -Dsoa.admin.user=weblogic
-Dsoa.admin.password=password1$ -Drealm=jazn.com
-Dmigration.file=C:/workspace/ViewMigration/data/view_data.xml
-Dmap.file=C:/workspace/ViewMigration/data/view_data_map.xml
-DoperationType=EXPORT -DobjectType=VIEW -Dname=ALL -Duser=weblogic
-DgrantPermission=true
Import
Flex fields and Views
Login to the server in which
you want to import.
> cd
<MW_HOME>\soa\bin
> set ANT_HOME=<Your Path>\apache-ant-1.10.1
> set
PATH=%ANT_HOME%\bin\;%PATH%
Import
Flex fields
ant -v -f
ant-t2p-worklist.xml -Dbea.home={ MW_HOME } -Dsoa.home={ MW_HOME/soa }
-Dsoa.hostname={hostname} -Dsoa.rmi.port={port} -Dsoa.admin.user={admin user
name}-Dsoa.admin.password={admin password} -Drealm=jazn.com -Dmigration.file={full
path with filename of flex_data.xml}
-Dmap.file=={full path with filename of flex_data_map.xml } -DoperationType=IMPORT
-DobjectType=TASK_PAYLOAD_FLEX_FIELD_MAPPING -Dname=ALL -Duser={bpm admin user}
-DgrantPermission=true
-DmigrateAttributeLabel=true
Parameters -
-Dbea.home=<MW_HOME>
-Dsoa.home=<MW_HOME>/soa
-Dsoa.hostname=Server ip/name
-Dsoa.rmi.port=Server port
-Dsoa.admin.user=admin user
-Dsoa.admin.password=admin
user p
-Drealm=realname
-Dmigration.file=file from which
data will be imported
-Dmap.file=File from which mapping data will be imported
Example –
ant -v -f
ant-t2p-worklist.xml -Dbea.home=C:/Oracle/Middleware/Oracle_Home
-Dsoa.home=C:/Oracle/Middleware/Oracle_Home/soa -Dsoa.hostname=localhost
-Dsoa.rmi.port=9001 -Dsoa.admin.user=weblogic -Dsoa.admin.password=password1$
-Drealm=jazn.com -Dmigration.file=C:/workspace/ViewMigration/data/flex_data.xml
-Dmap.file=C:/workspace/ViewMigration/data/flex_data_map.xml -DoperationType=IMPORT -DobjectType=TASK_PAYLOAD_FLEX_FIELD_MAPPING
-Dname=ALL -Duser=weblogic -DgrantPermission=true -DmigrateAttributeLabel=true
Import
Views
ant -v -f
ant-t2p-worklist.xml -Dbea.home={ MW_HOME } -Dsoa.home={ MW_HOME/soa } -Dsoa.hostname={hostname}
-Dsoa.rmi.port={port} -Dsoa.admin.user={admin user name}-Dsoa.admin.password={admin
password} -Drealm=jazn.com -Dmigration.file={full path with filename of view_data.xml} -Dmap.file=={full path with
filename of view_data_map..xml } -DoperationType=IMPORT
-DobjectType= VIEW -Dname=ALL -Duser={bpm admin user}
-DgrantPermission=true
-DmigrateAttributeLabel=true
Parameters -
Most of the parameters
remains same as above except
-DobjectType=VIEW
Example
–
ant -f ant-t2p-worklist.xml
-Dbea.home=C:/Oracle/Middleware/Oracle_Home
-Dsoa.home=C:/Oracle/Middleware/Oracle_Home/soa -Dsoa.hostname=localhost
-Dsoa.rmi.port=9001 -Dsoa.admin.user=weblogic -Dsoa.admin.password=password1$
-Dhwf.t2p.config.file=C:/workspace/ViewMigration/source_cfg/config.properties
-Drealm=jazn.com -Dmigration.file=C:/workspace/ViewMigration/data/view_data.xml
-Dmap.file=C:/workspace/ViewMigration/data/view_data_map.xml -DoperationType=IMPORT -DobjectType=VIEW -Dname=ALL -Duser=weblogic
-DgrantPermission=true
Subscribe to:
Posts (Atom)