Adding Process Instance Audit Images to the Worklist

I have just uploaded another update for the custom BPM worklist sample, the second one this week!  This update adds the ‘process instance audit image’ to the ‘process instance detail’ page.  That means the a picture of the actual process model with the path that this instance of the process has followed (so far) highlighted in green.

Here are a couple of examples so you can see what I mean:

And another:

As always, you can download the source code from Subversion and the Javadoc and WARs from the main worklist page.

This update adds some interesting new API usage, which we will discuss in this article.  It also requires the addition of some more libraries into your Maven repository to allow you to build with the necessary dependencies.  There are getting to be enough of these now, that I thought it was time to write a script to save you some work.  You can download the script from here (for Windows) or here (Unix-like).  Warning:  The scripts are not ‘thoroughly tested’ so please check the results carefully.  Please leave a comment if you have problems with them.

You will also need one more JAR file that I am making available for download here.  This file contains a utility class that you will need to use to get the image.  We do not currently have a working API in the product (i.e. as of to get the process instance audit image.  This JAR file contains a utility class from Oracle that will allow you to get the image, and its API is fairly similar to what we have planned for the real API we plan to introduce in a future release.  Hopefully this will minimise any changes you need to make in the future should we release a real API.

Please note, as for the worklist as a whole, this JAR file is a sample, that is provided “as is” without any warranty or support.

This JAR file contains a class called oracle.bpm.example.util.ProcessDiagramUtil.  This class has a constructor that takes the BPMServiceClient which we have seen before, and a method called InputStream getProcessAuditDiagram(IBPMContext ctx, String instanceId) which retrieves the actual image in PNG format.

Here is the basic usage of this utility class:

  // get the utility class which will retrieve the image for us
  ProcessDiagramUtil pdu = new ProcessDiagramUtil(

  // get the image for the requested instance
  InputStream auditDiagramData = pdu.getProcessAuditDiagram(
      (IBPMContext) ContextCache.getContextCache().get(user), instanceId);

We need to create an instance of the class, passing the constructor the BPMServiceClient.  Then we are able to get the instance audit image (in PNG format) as an InputStream.

The controller in this case is also a little different, so it is presented here.  It is just returning the PNG image, without a ‘page’ wrapped around it, so the intention is that it is called from and img tag, not from the browser URL.  We will see this later in the view.

Here is the controller code:


import org.springframework.web.servlet.ModelAndView;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;



    A Controller that will display the grpahical audit image for a given process instance.
    This controller should only be called in an 'img' tag - not the main application window.
public class AuditImageController extends SimpleSuccessFailureController {

  private static final int IO_BUFFER_SIZE = 1;

  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    MLog.log("AuditImageController", "Entering handleRequest()");
    // get parameters from request
    String xProcessId = request.getParameter("x_processid");

    InputStream image = null;

    try {
      image = MTaskList.getAuditImage(request.getUserPrincipal().getName(), xProcessId);
      if (image == null) {
        MLog.log("AuditImageController", "image is null");
        return null;
    } catch (Exception e) {
      MLog.log("AuditImageController", "Got an exception in the call to MTaskList.getAuditImage(), bailing out...");
      return null;

    // set up the response

    ServletOutputStream out = response.getOutputStream();
    copy(image, out);
    return null;

  private static void copy(InputStream in, OutputStream out) throws IOException {
    byte[] b = new byte[IO_BUFFER_SIZE];
    int read;
    while ((read = != -1) {
      out.write(b, 0, read);


This controller uses a similar approach to the one we used in the DownloadAttachmentController.  We set the ContentType of the HttpServletResponse and then write the image data directly into the ServletOutputStream and return null from the controller.  This is how we deliver binary data to the browser in the Spring Web MVC framework.

Here is the part of the view that calls this controller:

 <h2 class="td-h2">Process Audit Image for this Instance</h2>
  <img src="<c:out value="${model.instance.systemAttributes.processInstanceId}"/>"  />

Good luck and enjoy!

About Mark Nelson

Mark Nelson is an Architect in the Enterprise Cloud-Native Java Team at Oracle. Mark works mainly on making Java (traditional and microservices) easy to use in Kubernetes and the CNCF ecosystem. Before joining this team, Mark worked on Wercker, WebLogic and was a senior member of the A-Team since 2010, and worked in Sales Consulting at Oracle since 2006 and various roles at IBM since 1994.
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

12 Responses to Adding Process Instance Audit Images to the Worklist

  1. Your post was invaluable and it was a kind of functionality that we urgently sought. I confirm that it also works with release .

    Thanks again,
    Serafeim (

  2. Arun Pareek says:

    I found out that there is one class that isnt being set in the classpath of the standalone java code..


    Can you point out as which jar is this class file part of?

  3. hemantmalik says:

    Hi Mark,

    I am trying to get this working with PS5 release. The ProcessDiagramUtil class throws a NoClassDefFoundError for oracle/bpm/xml/XMLSerializer class. I see that there are few Serializer classes available in bpmcore jar but none of them is with name XMLSerializer. Any idea what I could be missing out here in the whole setup?


  4. hemantmalik says:

    Hi Mark,

    I got the NoClassDefFoundError for oracle/bpm/xml/XMLSerializer error (thrown in the utility class for getting the audit trail image) which was not allowing the audit trail image to come up in the worklist. I had to add oracle.bpm.fdi.jar which contains the above specified class. I installed it into maven’s repo and updated the pom accordingly. I am using PS5 ( release.

    Thank you.

  5. ashosheh says:

    Hi Mark,

    Thanks for the valuable post.. Can we manipulate the output image for example change the green highlight color or this is not doable?


    • Mark Nelson says:

      Thanks for your comment. In the current release you cannot manipulate the image, but I think that we may add this ability in some future release.

  6. ashosheh says:

    Hi Mark,
    Just discovered something strange in the API. In BPM process design, I changed the default icon for human task activity to be (approver_lg). Then the following exception was thrown when the image is produced: no protocol: images/approver_lg.png
    at oracle.bpm.ui.CustomImageHelper.getCustomImageUrl(
    at oracle.bpm.ui.CustomImageHelper.getCustomImageUrl(
    at oracle.bpm.ui.CustomImageHelper.getCustomImage(
    at oracle.bpm.ui.CustomImageHelper.getCustomImage(
    at oracle.bpm.draw.renderer.FlowElementImageRenderer.getCustomImage(
    at oracle.bpm.draw.renderer.FlowElementImageRenderer.getNormalImage(
    at oracle.bpm.draw.renderer.FlowElementImageRenderer.getImage(
    at oracle.bpm.draw.renderer.FlowElementImageRenderer.contains(
    at oracle.bpm.draw.DrawableFlowNodeImpl.contains(
    at oracle.bpm.diagram.draw.DrawableUtils.outbound(
    at oracle.bpm.diagram.draw.DrawableConnectionImpl.updatePath(
    at oracle.bpm.diagram.draw.DrawableConnectionImpl.refresh(
    at oracle.bpm.draw.DrawableSequenceFlow.refresh(
    at oracle.bpm.draw.DrawableChildPopulator.populateChild(
    at oracle.bpm.draw.DrawableChildPopulator.populate(
    at oracle.bpm.draw.DrawableChildPopulator.populateChild(
    at oracle.bpm.draw.diagram.ImageProcessDiagrammer.addProcessToRoot(
    at oracle.bpm.draw.diagram.ImageProcessDiagrammer.(
    at oracle.bpm.draw.diagram.AuditProcessDiagrammer.(

    • Mark Nelson says:

      Yeah that is strange. Can you share the code you are using to call the API please, looks like it might be a bug 🙂

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s