`
sbtmbj2014
  • 浏览: 26169 次
社区版块
存档分类
最新评论

Archiving Audit Diagrams as Images in Oracle SOA Suite BPM Processes2

 
阅读更多

July 26, 2011

Archiving Audit Diagrams as Images in Oracle SOA Suite BPMProcesses

In myprevious postI had described how we can create a custom Java Class to save custom business indicators in a formatted PDF file. It might be useful in cases where businesses wants process data be presented in a meaningful way.

Another practical case that i had encountered in the past while designing business processes is to save the Audit diagram of the process once it is complete. The audit instance diagram can be viewed in the EM console by clicking on Flow Trace for any process instance.

In the good all Oracle BPM 10g days (prior to Oracle SOA/BPM Suite 11g) we had a fully documented API’s for interacting with process instances. PAPI interfaces were available both as web service and java API’s to connect to a in-flight or completed instance and retrieve all audit data from it.

Getting an audit image from a business process instance using PAPI was a cake walk. The below code sample shows its ease

ProcessService processService = null;
ProcessServiceSession session = null;
try {
processService = ProcessService.create(configuration);
session = processService.createSession(USERNAME, PASSWORD, HOSTNAME);
for (String processId : session.processesGetIds())
{
 fuego.papi.Process process = session.processGet(processId);
 ProcessDiagram diagram = session.processGetDiagram(processId);
 diagram.setTheme(ProcessDiagram.THEME_COLOR_BPMN);
 diagram.setDrawFlowOnly(true);
 Image image = diagram.getImage();
 File pngImage = new File(createPngFilename("image"));
 image.write(pngImage, ImageExtension.PNG);
}
catch (Exception e)
{
 e.printStackTrace();
}
finally
{
 session.close();
 processService.close();
}

Whoa! Pretty Simple and elegant.

However if we want to achieve something similar in Oracle SOA Suite 11g it is a lot more challenging.

Oracle BPM Suite 11g doesn’t have any published API’s that developers can refer. This makes it an even bigger nightmare.

The process instance data in Oracle SOA suite 11g is stored in the dehydration store in theSOA_INFRAschema. In all practical scenarios this store will be subjected to purging and maintenance. So many a people/project might need to archive the flow trace of a process instance as an image. As we all know how significant is historical data for business process improvements and reengineering.

In this blog post I will show how the same functionality of getting an instance image from a process can be achieved using Oracle SOA Suite 11g and explain the code in steps.

Assuming we are using Oracle SOA Suite 11g PS3 that has a running domain and a BPM process deployed with a couple of running/completed instances.

Create a Generic Java project in JDeveloper sayArchiveInstanceImage.Create a Java class of the same name inside it. Right click on the project and add the following JAR’s to the project’s classpath.

Oracle.bpm.bpm-services.client.jar
Oracle.bpm.bpm-services.interface.jar
Oracle.bpm.client.jar
Bpm-infra.jar
Bpm-services.jar
Oracle.bpm.project.model.jar
Oracle.bpm.project.draw.jar
Oracle.bpm.project.catalog.jar
Wlfullclient.jar
Wsclient_extended.jar
Oracle.bpm.core.jar
Oracle.bpm.lib.jar
Oracle.bpm.papi.jar
Oracle.bpm.xml.jar
Oracle.bpm.diagram.draw.jar
Oracle-bpm.jar
Oracle.bpm.bpm-services.implementation.jar
Oracle.bpm.bpm-services.internal.jar
Oracle.bpm.bpmobject.jar
Oracle.bpm.runtime.jar
Oracle.bpm.ui.jar

All these above JAR’s can be found at the following directories

<JDevHome>\soa\modules\oracle.bpm.client_11.1.1
<JDevHome>\soa\modules\oracle.soa.fabric_11.1.1
<JDevHome>\soa\modules\oracle.soa.workflow_11.1.1
<JDevHome>\soa\modules\oracle.bpm.project_11.1.1
<MiddlewareHome>\wlserver_10.3\server\lib
<MiddlewareHome>\oracle_common\webservices
<JDevHome>\soa\modules\oracle.bpm.runtime_11.1.1
<JDevHome>\soa\modules\oracle.bpm.workspace_11.1.1

You can createdWlfullclient.jaras under

Change directories to theserver/libdirectory.

cd <MiddlewareHome>wlserver_10.3/server/lib

Use the following command to createwlfullclient.jarin theserver/libdirectory:

java -jar wljarbuilder.jar

You can now copy and bundle thewlfullclient.jarwith client applications.

Add thewlfullclient.jarto the client application’sclasspath.

See here for more information

http://download.oracle.com/docs/cd/E12840_01/wls/docs103/client/jarbuilder.html

First and foremost like any remote client we need to get aninstanceof the SOA server runtime to be able to gain access to any running processes inside it. This is pretty simple. The following lines of code demonstrates how we can useBPMServiceClientFactoryclass to get an instance of the server runtime.

Next initialize anIBPMContextfromBPMServiceClientFactory.

// URL of the SOA Server and PORT on which the application is deployed
private static String soaURL = "t3://localhost:4003";

public static BPMServiceClientFactory getBPMServiceClientFactory()
{
Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY,String> properties = new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY,String>();
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,WorkflowServiceClientFactory.REMOTE_CLIENT);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,soaURL);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,"weblogic");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,"welcome123");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
return BPMServiceClientFactory.getInstance(properties, null, null);
}

public static IBPMServiceClient getBPMServiceClient(){
return getBPMServiceClientFactory().getBPMServiceClient();
}
public static IBPMContext getIBPMContextForAuthenticatedUser() throws Exception{
return getBPMServiceClientFactory().getBPMUserAuthenticationService().getBPMContextForAuthenticatedUser();
}

We also have to get a handle to theIBPMServiceClientinterface. Create a self initializing constructor for our main class to get a hook to this interface.

// Get a handle to the IBPMServiceClient interface in the ArchiveInstanceImage class
public ArchiveInstanceImage(IBPMServiceClient bpmServiceClient)
{
this.bpmServiceClient = bpmServiceClient;
}

Using the IBPMContext and a searchable instance id from the process we can get process data using theIProcessInstanceinterface.

See the code snippet below that shows how we can retrieve the audit diagram for a process instance

public InputStream getProcessAuditImage(IBPMContext bpmContext, String instanceId)
throws BPMException
{
IInstanceQueryService instanceQueryService = this.bpmServiceClient.getInstanceQueryService();
IProcessInstance processInstance = instanceQueryService.getProcessInstance(bpmContext, instanceId);

if (processInstance == null) {
return null;
}
IProcessModelPackage processModelPackage = this.bpmServiceClient.getProcessModelService().getProcessModel(bpmContext, processInstance.getSca().getCompositeDN(), processInstance.getSca().getComponentName());

AuditProcessDiagrammer auditProcessImage = new AuditProcessDiagrammer(processModelPackage.getProcessModel());
return getProcessImage(auditProcessImage);
}

private InputStream getProcessImage(AuditProcessDiagrammer processImage)
throws BPMException
{
InputStream processImageStream = null;
ByteArrayOutputStream auditImageOutputStream = new ByteArrayOutputStream();
try {
// Get base64 encoded image String from processImage
String base64Image = processImage.getImage();
Image image = Image.createFromBase64(base64Image);
BufferedImage bufferedImage = (BufferedImage)image.asAwtImage();
// Use the Image Extension that suites you from .PNG, .JPG and .GIF
ImageIOFacade.writeImage(bufferedImage, ImageExtension.PNG, auditImageOutputStream);
processImageStream = new ByteArrayInputStream(auditImageOutputStream.toByteArray());
// Archives the Process Image at any suitable location
archiveDiagramToFile(processImageStream);
}
catch (Exception e)
{
throw new BPMException(e);
}
finally {
}
return processImageStream;
}

// Utility method to Archive the InputStream into a PNG File
private void archiveDiagramToFile(InputStream istream) throws IOException {
File outputFile = new File("C:\\Arrun\\ProcessAuditImage\\ProcessImage.png");
OutputStream out = new FileOutputStream(outputFile);

// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = istream.read(buf)) > 0) {
out.write(buf, 0, len);
}
istream.close();
out.close();
}

Finally to test the code that we had written add a main method to invoke getProcessAuditImage(iBPMContext, instanceId)to see the process audit image created.

public static void main (String args[]) throws BPMException, Exception
{
ArchiveInstanceImage instImage = new ArchiveInstanceImage(getBPMServiceClient());
// Use any instanceId that is existing for the process in the server
InputStream istream= instImage.getProcessAuditImage(getIBPMContextForAuthenticatedUser(),"840001");
}

Running the standalone Java program from inside JDeveloper creates the following process image in the target archive directory.

image

A quick look at the image and we will realize what it is lacking. Off course we have been quite able to get the image for the process (similar to what we used to get using PAPI in OBPM 10g). However we don’t see the flow trace i.e the sequence of activities that the instance traversed in its flow.

To get that we have get aListofDiagramEventand highlight the process image by passing this list to it.

Create another private function to get a list of allEventsthat the instance encountered in its flow as below.

private List<DiagramEvent> getHighlightEvents(Process processModel, IAuditInstance auditInstance)
{
List events = new ArrayList();

String activityId = auditInstance.getActivityId();
Date eventDate = auditInstance.getCreateTime().getTime();
DiagramEvent nodeEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.FLOW_NODE_IN, activityId, eventDate);

events.add(nodeEvent);
String sourceActivity;
String targetActivity;
if (auditInstance.getAuditInstanceType().equalsIgnoreCase("START")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
sourceActivity = auditInstance.getSourceActivity();
Sequence<SequenceFlow> incommingSequenceFlows = flowNode.getIncomingSequenceFlows();
if ((incommingSequenceFlows != null) && (!incommingSequenceFlows.isEmpty()) && (sourceActivity != null)) {
Iterator<SequenceFlow> seqIterator = incommingSequenceFlows.iterator();
while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getSource().getId().equalsIgnoreCase(sourceActivity)) {
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}
else if (auditInstance.getAuditInstanceType().equalsIgnoreCase("END")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
targetActivity = auditInstance.getTargetActivity();
Sequence<SequenceFlow> outgoingSequenceFlows = flowNode.getOutgoingSequenceFlows();

if ((outgoingSequenceFlows != null) && (!outgoingSequenceFlows.isEmpty()) &&
(targetActivity != null)) {
Iterator<SequenceFlow> seqIterator = outgoingSequenceFlows.iterator();
while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getTarget().getId().equalsIgnoreCase(targetActivity))
{
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}

Add these following line to the getProcessAuditImage(IBPMContext bpmContext, String instanceId) method before the return statement to highlight the image

List auditInstances = this.bpmServiceClient.getInstanceQueryService().queryAuditInstanceByProcessId(bpmContext, instanceId);
List diagramEvents = new ArrayList();

for (int IAuditInstance=0; IAuditInstance< auditInstances.size(); IAuditInstance++)
{
diagramEvents.addAll(getHighlightEvents(process, (IAuditInstance)auditInstances.get(IAuditInstance)));
}
auditProcessImage.highlight(diagramEvents);

Run the Java program once again and view the image created this time.

image

This time you can see that the activities and transitions that the instance took are highlighted in the image.

The complete Java Class can be found below

package blog.beatechnologies.soasuiteutil;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;

import oracle.bpm.client.BPMServiceClientFactory;
import oracle.bpm.collections.Sequence;
import oracle.bpm.draw.diagram.AuditProcessDiagrammer;
import oracle.bpm.draw.diagram.DiagramEvent;
import oracle.bpm.project.model.processes.FlowNode;
import oracle.bpm.project.model.processes.Process;
import oracle.bpm.project.model.processes.SequenceFlow;
import oracle.bpm.services.client.IBPMServiceClient;
import oracle.bpm.services.common.exception.BPMException;
import oracle.bpm.services.instancemanagement.model.IProcessInstance;
import oracle.bpm.services.instancequery.IAuditInstance;
import oracle.bpm.services.instancequery.IInstanceQueryService;
import oracle.bpm.services.internal.processmodel.model.IProcessModelPackage;
import oracle.bpm.ui.Image;
import oracle.bpm.ui.utils.ImageExtension;
import oracle.bpm.ui.utils.ImageIOFacade;

public class ArchiveInstanceImage
{
private IBPMServiceClient bpmServiceClient;
// URL of the SOA Server and PORT on which the application is deployed
private static String soaURL = "t3://soasitapp03.us.dell.com:5411";

public ArchiveInstanceImage(IBPMServiceClient bpmServiceClient)
{
this.bpmServiceClient = bpmServiceClient;
}

public InputStream getProcessAuditImage(IBPMContext bpmContext, String instanceId)
throws BPMException
{
IInstanceQueryService instanceQueryService = this.bpmServiceClient.getInstanceQueryService();
IProcessInstance processInstance = instanceQueryService.getProcessInstance(bpmContext, instanceId);

if (processInstance == null) {
return null;
}
IProcessModelPackage processModelPackage = this.bpmServiceClient.getProcessModelService().getProcessModel(bpmContext, processInstance.getSca().getCompositeDN(), processInstance.getSca().getComponentName());

AuditProcessDiagrammer auditProcessImage = new AuditProcessDiagrammer(processModelPackage.getProcessModel());
List auditInstances = this.bpmServiceClient.getInstanceQueryService().queryAuditInstanceByProcessId(bpmContext, instanceId);

List diagramEvents = new ArrayList();

for (int IAuditInstance=0; IAuditInstance< auditInstances.size(); IAuditInstance++)
{
diagramEvents.addAll(getHighlightEvents(processModelPackage.getProcessModel(), (IAuditInstance)auditInstances.get(IAuditInstance)));
}
auditProcessImage.highlight(diagramEvents);
return getProcessImage(auditProcessImage);
}

private InputStream getProcessImage(AuditProcessDiagrammer processImage)
throws BPMException
{
InputStream processImageStream = null;
ByteArrayOutputStream auditImageOutputStream = new ByteArrayOutputStream();
try {
// Get base64 encoded image String from processImage
String base64Image = processImage.getImage();
Image image = Image.createFromBase64(base64Image);
BufferedImage bufferedImage = (BufferedImage)image.asAwtImage();
// Use the Image Extension that suites you from .PNG, .JPG and .GIF
ImageIOFacade.writeImage(bufferedImage, ImageExtension.PNG, auditImageOutputStream);
processImageStream = new ByteArrayInputStream(auditImageOutputStream.toByteArray());
// Archives the Process Image at any suitable location
archiveDiagramToFile(processImageStream);
}
catch (Exception e)
{
throw new BPMException(e);
}
finally {
}
return processImageStream;
}

private List<DiagramEvent> getHighlightEvents(Process processModel, IAuditInstance auditInstance)
{
List events = new ArrayList();

String activityId = auditInstance.getActivityId();
Date eventDate = auditInstance.getCreateTime().getTime();
DiagramEvent nodeEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.FLOW_NODE_IN, activityId, eventDate);

events.add(nodeEvent);
String sourceActivity;
String targetActivity;
if (auditInstance.getAuditInstanceType().equalsIgnoreCase("START")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
sourceActivity = auditInstance.getSourceActivity();
Sequence<SequenceFlow> incommingSequenceFlows = flowNode.getIncomingSequenceFlows();

if ((incommingSequenceFlows != null) && (!incommingSequenceFlows.isEmpty()) && (sourceActivity != null)) {
Iterator<SequenceFlow> seqIterator = incommingSequenceFlows.iterator();

while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getSource().getId().equalsIgnoreCase(sourceActivity)) {
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}
else if (auditInstance.getAuditInstanceType().equalsIgnoreCase("END")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
targetActivity = auditInstance.getTargetActivity();
Sequence<SequenceFlow> outgoingSequenceFlows = flowNode.getOutgoingSequenceFlows();

if ((outgoingSequenceFlows != null) && (!outgoingSequenceFlows.isEmpty()) && (targetActivity != null)) {
Iterator<SequenceFlow> seqIterator = outgoingSequenceFlows.iterator();
while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getTarget().getId().equalsIgnoreCase(targetActivity)) {
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}
return events;
}
public static BPMServiceClientFactory getBPMServiceClientFactory() {
Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String> properties = new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String>();
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,WorkflowServiceClientFactory.REMOTE_CLIENT);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,soaURL);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,"arun_pareek");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,"#Jannu12");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
return BPMServiceClientFactory.getInstance(properties, null, null);
}
public static IBPMServiceClient getBPMServiceClient(){
return getBPMServiceClientFactory().getBPMServiceClient();
}
public static IBPMContext getIBPMContextForAuthenticatedUser() throws Exception{
return getBPMServiceClientFactory().getBPMUserAuthenticationService().getBPMContextForAuthenticatedUser();
}

public static void main (String args[]) throws BPMException, Exception
{
ArchiveInstanceImage instImage = new ArchiveInstanceImage(getBPMServiceClient());
InputStream istream= instImage.getProcessAuditImage(getIBPMContextForAuthenticatedUser(),"10002");
}
void archiveDiagramToFile(InputStream istream) throws IOException {
File outputFile = new File("C:\\Arrun\\process.png");
OutputStream out = new FileOutputStream(outputFile);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = istream.read(buf)) > 0) {
out.write(buf, 0, len);
}
istream.close();
out.close();
}
}

This was all about getting this Java API’s to work with SOA Suite 11g PS3. I also tried to test the same with a PS2 domain and with PS2 libraries.

Everything was almost same except for a few things.

There is no class calledIProcessModelPackagethat I could find in PS2 BPM jar’s

So the process image was obtained usingIProcessModelServiceclass like below

IProcessModelService processModelService = this.bpmServiceClient.getProcessModelService();
Process process = processModelService.getProcessModel(bpmContext, processInstance.getSca().getCompositeDN(), processInstance.getSca().getComponentName());
AuditProcessDiagrammer auditProcessImage = new AuditProcessDiagrammer(process);

The additional libraries that we need to put in the project’s classspath are

Oracle.bpm.project.io.jar <JDevHome>\soa\modules\oracle.bpm.project_11.1.1
Oracle.bpm.project.jar <JDevHome>\soa\modules\oracle.bpm.project_11.1.1
Oracle.bpm.project.compile.jar <JDevHome>\soa\modules\oracle.bpm.project_11.1.1
Oracle.bpm.vfilesystem.jar <JDevHome>\soa\modules\oracle.bpm.runtime_11.1.1

In case you would need the entire class here is what you should use in case you are on Oracle SOA Suite 11g PS2

package blog.beatechnologies.soautil;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;

import oracle.bpm.client.BPMServiceClientFactory;
import oracle.bpm.collections.Sequence;
import oracle.bpm.draw.diagram.AuditProcessDiagrammer;
import oracle.bpm.draw.diagram.DiagramEvent;
import oracle.bpm.project.model.processes.FlowNode;
import oracle.bpm.project.model.processes.Process;
import oracle.bpm.project.model.processes.SequenceFlow;
import oracle.bpm.services.client.IBPMServiceClient;
import oracle.bpm.services.common.exception.BPMException;
import oracle.bpm.services.instancemanagement.model.IProcessInstance;
import oracle.bpm.services.instancequery.IAuditInstance;
import oracle.bpm.services.instancequery.IInstanceQueryService;
import oracle.bpm.services.internal.processmodel.IProcessModelService;
import oracle.bpm.services.util.AuditTrail;
import oracle.bpm.ui.Image;
import oracle.bpm.ui.utils.ImageExtension;
import oracle.bpm.ui.utils.ImageIOFacade;

public class ArchiveInstanceImage
{
private IBPMServiceClient bpmServiceClient;
// URL of the SOA Server and PORT on which the application is deployed
private static String soaURL = "t3://wxp-fxhp7bs.blr.amer.dell.com:4003";

// Get a handle of IBPMServiceClient through the class constructor
public ArchiveInstanceImage(IBPMServiceClient bpmServiceClient)
{
this.bpmServiceClient = bpmServiceClient;
}

public InputStream getProcessAuditImage(IBPMContext bpmContext, String instanceId)
throws BPMException
{
IInstanceQueryService instanceQueryService = this.bpmServiceClient.getInstanceQueryService();
IProcessInstance processInstance = instanceQueryService.getProcessInstance(bpmContext, instanceId);

System.out.println("Composite DN " + processInstance.getSca().getCompositeDN());
System.out.println("Composite DN " + processInstance.getSca().getComponentName());

if (processInstance == null) {
return null;
}

IProcessModelService processModelService = this.bpmServiceClient.getProcessModelService();
Process process = processModelService.getProcessModel(bpmContext, processInstance.getSca().getCompositeDN(), processInstance.getSca().getComponentName());
AuditProcessDiagrammer auditProcessImage = new AuditProcessDiagrammer(process);
List auditInstances = this.bpmServiceClient.getInstanceQueryService().queryAuditInstanceByProcessId(bpmContext, instanceId);

List diagramEvents = new ArrayList();

for (int IAuditInstance=0; IAuditInstance< auditInstances.size(); IAuditInstance++)
{
diagramEvents.addAll(getHighlightEvents(process, (IAuditInstance)auditInstances.get(IAuditInstance)));
}
auditProcessImage.highlight(diagramEvents);
//auditProcessImage.getImage()
return getProcessImage(auditProcessImage);
}

private InputStream getProcessImage(AuditProcessDiagrammer processImage)
throws BPMException
{
InputStream processImageStream = null;
ByteArrayOutputStream auditImageOutputStream = new ByteArrayOutputStream();
try {
// Get base64 encoded image String from processImage
String base64Image = processImage.getImage();
Image image = Image.createFromBase64(base64Image);
BufferedImage bufferedImage = (BufferedImage)image.asAwtImage();
// Use the Image Extension that suites you from .PNG, .JPG and .GIF
ImageIOFacade.writeImage(bufferedImage, ImageExtension.PNG, auditImageOutputStream);
processImageStream = new ByteArrayInputStream(auditImageOutputStream.toByteArray());
// Archives the Process Image at any suitable location
archiveDiagramToFile(processImageStream);
}
catch (Exception e)
{
throw new BPMException(e);
}
finally {
}
return processImageStream;
}

private List<DiagramEvent> getHighlightEvents(Process processModel, IAuditInstance auditInstance)
{
List events = new ArrayList();
String activityId = auditInstance.getActivityId();
Date eventDate = auditInstance.getCreateTime().getTime();
DiagramEvent nodeEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.FLOW_NODE_IN, activityId, eventDate);
events.add(nodeEvent);
String sourceActivity;
String targetActivity;
if (auditInstance.getAuditInstanceType().equalsIgnoreCase("START")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
sourceActivity = auditInstance.getSourceActivity();
Sequence<SequenceFlow> incommingSequenceFlows = flowNode.getIncomingSequenceFlows();

if ((incommingSequenceFlows != null) && (!incommingSequenceFlows.isEmpty()) && (sourceActivity != null)) {
Iterator<SequenceFlow> seqIterator = incommingSequenceFlows.iterator();
while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getSource().getId().equalsIgnoreCase(sourceActivity)) {
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}
else if (auditInstance.getAuditInstanceType().equalsIgnoreCase("END")) {
FlowNode flowNode = (FlowNode)processModel.findDescendant(FlowNode.class, auditInstance.getActivityId());

if (flowNode != null) {
targetActivity = auditInstance.getTargetActivity();
Sequence<SequenceFlow> outgoingSequenceFlows = flowNode.getOutgoingSequenceFlows();

if ((outgoingSequenceFlows != null) && (!outgoingSequenceFlows.isEmpty()) &&
(targetActivity != null)) {
Iterator<SequenceFlow> seqIterator = outgoingSequenceFlows.iterator();
while(seqIterator.hasNext())
{
SequenceFlow sequenceFlow= seqIterator.next();
if (sequenceFlow.getTarget().getId().equalsIgnoreCase(targetActivity))
{
DiagramEvent sequenceEvent = DiagramEvent.create(DiagramEvent.DiagramEventType.SEQUENCE_FLOW, sequenceFlow.getId(), eventDate);
events.add(sequenceEvent);
}}
}}
}
return events;
}
public static BPMServiceClientFactory getBPMServiceClientFactory() {
Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String> properties = new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, String>();
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,WorkflowServiceClientFactory.REMOTE_CLIENT);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,soaURL);
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,"weblogic");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,"welcome123");
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
return BPMServiceClientFactory.getInstance(properties, null, null);
}
public static IBPMServiceClient getBPMServiceClient(){
return getBPMServiceClientFactory().getBPMServiceClient();
}
public static IBPMContext getIBPMContextForAuthenticatedUser() throws Exception{
return getBPMServiceClientFactory().getBPMUserAuthenticationService().getBPMContextForAuthenticatedUser();
}
public static void main (String args[]) throws BPMException, Exception {

ArchiveInstanceImage instImage = new ArchiveInstanceImage(getBPMServiceClient());
InputStream istream= instImage.getProcessAuditImage(getIBPMContextForAuthenticatedUser(),"840001");
}
// Utility method to Archive the InputStream into a PNG File
private void archiveDiagramToFile(InputStream istream) throws IOException {
File outputFile = new File("C:\\Arrun\\ProcessAuditImage\\ProcessImage.png");
OutputStream out = new FileOutputStream(outputFile);

// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = istream.read(buf)) > 0) {
out.write(buf, 0, len);
}
istream.close();
out.close();
}
}

Now there are a couple of ways to use this Java Code in real practical cases

  1. Use it from any Custom UI/ Workflow UI to access the process image if need be.
  2. Create a Web service wrapper over the Java Class and use it as a WS API that can be invoked from any BPM process and hence it can be reused across multiple BPM processes.
  3. In case you would want to limit the use inside a composite then create a Spring SCA component for this custom Java class and then invoke it from inside a BPM process

In my future blogs I will try to come up with more interesting utilities with these BPM API’s. This will probably be of great use to folks who have worked with the PAPI API’s and find it a great miss in Oracle SOA Suite 11g.

Meanwhile also wondering what is stopping Oracle to publish a well document API for these interfaces.:-)

.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics