Handling HumanTask attachments in Oracle BPM 11g PS4FP+ (I)

Adding attachments to a HumanTask is a feature that exists in Oracle HWF (Human Workflow) since 10g.

However, in 11g there have been many improvements on this feature and this entry will try to summarize them.

Oracle BPM 11g 11.1.1.5.1 (aka PS4 Feature Pack or PS4FP) introduced two great features:

  • Ability to link attachments at a Task scope or at a Process scope:
    • "Task" attachments are only visible within the scope (lifetime) of a task. This means that, initially, any member of the assignment pattern of the Human Task will be able to handle (add, review or remove) attachments. However, once the task is completed, subsequent human tasks will not have access to them. This does not mean those attachments got lost. Once the human task is completed, attachments can be retrieved in order to, i.e., check them in to a Content Server or to inject them to a new and different human task.

    Aside note: a "re-initiated" human task will inherit comments and attachments, along with history and -optionally- payload. See here for more info.

      • "Process" attachments are visible within the scope of the process. This means that subsequent human tasks in the same process instance will have access to them.
    • Ability to use Oracle WebCenter Content (previously known as "Oracle UCM") as the backend for the attachments instead of using HWF database backend. This feature adds all content server document lifecycle capabilities to HWF attachments (versioning, RBAC, metadata management, etc). As of today, only Oracle WCC is supported. However, Oracle BPM Suite does include a license of Oracle WCC for the solely usage of document management within BPM scope.

    Here are some code samples that leverage the above features.

    Retrieving uploaded attachments -Non UCM-

    Non UCM attachments (default ones or those that have existed from 10g, and are stored "as-is" in HWK database backend) can be retrieved after the completion of the Human Task. Firstly, we need to know whether any attachment has been effectively uploaded to the human task. There are two ways to find it out:

    • Through an XPath function:

    • Checking the execData/attachment[] structure. For example:

    Once we are sure one ore more attachments were uploaded to the Human Task, we want to get them. In this example, by "get" I mean to get the attachment name and the payload of the file. 


    Aside note: Oracle HWF lets you to upload two kind of [non-UCM] attachments: a desktop document and a Web URL. This example focuses just on the desktop document one. In order to "retrieve" an uploaded Web URL, you can get it directly from the execData/attachment[] structure.

    Attachment content (payload) is retrieved through the getTaskAttachmentContents() XPath function:

    This example shows how to retrieve as many attachments as those had been uploaded to the Human Task and write them to the server using the File Adapter service.

    The sample process excerpt is as follows:

     A dummy UserTask using "HumanTask1" Human Task followed by a Embedded Subprocess that will retrieve the attachments (we're assuming at least one attachment is uploaded):

    and once retrieved, we will write each of them back to a file in the server using a File Adapter service:

    In detail:

    • We've defined an XSD structure that will hold the attachments (both name and payload):

    • Then, we can create a BusinessObject based on such element (attachmentCollection) and create a variable (named attachmentBPM) of such BusinessObject type.
    • We will also need to keep a copy of the HumanTask output's execData structure. Therefore we need to create a variable of type TaskExecutionData...

    • ...and copy the HumanTask output execData to it:

    • Now we get into the embedded subprocess that will retrieve the attachments' payload. First, and using an XSLT transformation, we feed the attachmentBPM variable with the name of each attachment and setting an empty value to the payload:

    Please note that we're using the XSLT for-each node to create as many target structures as necessary. Also note that we're setting an Empty text to the payload variable. The reason for this is to make sure the <payload></payload> tag gets created. This is needed when we map the payload to the XML variable later.


    Aside note: We are assuming that we're retrieving non-UCM attachments. However in real life you might want to check the type of attachment you're handling. The execData/attachment[]/storageType contains the values "UCM" for UCM type attachments, "TASK" for non-UCM ones or "URL" for Web URL ones. Those values are part of the "Ext.Com.Oracle.Xmlns.Bpel.Workflow.Task.StorageTypeEnum" enumeration.
    • Once we have fed the attachmentsBPM structure and so it now contains the name of each of the attachments, it is time to iterate through it and get the payload. Therefore we will use a new embedded subprocess of type MultiInstance, that will iterate over the attachmentsBPM/attachment[] element:

    • In every iteration we will use a Script activity to map the corresponding payload element with the result of the XPath function getTaskAttachmentContents(). Please, note how the target array element is indexed with the loopCounter predefined variable, so that we make sure we're feeding the right element during the array iteration:

     The XPath function used looks as follows:

    hwf:getTaskAttachmentContents(bpmn:getDataObject('UserTask1LocalExecData')/ns1:systemAttributes/ns1:taskId, bpmn:getDataObject('attachmentsBPM')/ns:attachment[bpmn:getActivityInstanceAttribute('SUBPROCESS3067107484296', 'loopCounter')]/ns:fileName

    where the input parameters are:

    taskId of the just completed Human Task

    attachment name we're retrieving the payload from

    array index (loopCounter predefined variable) 


    Aside note: The reason whereby we're iterating the execData/attachment[] structure through embedded subprocess and not, i.e., using XSLT and for-each nodes, is mostly because the getTaskAttachmentContents() XPath function is currently not available in XSLT mappings. So all this example might be considered as a workaround until this gets fixed/enhanced in future releases.

    • Once this embedded subprocess ends, we will have all attachments (name + payload) in the attachmentsBPM variable, which is the main goal of this sample. But in order to test everything runs fine, we finish the sample writing each attachment to a file. To that end we include a final embedded subprocess to concurrently iterate through each attachmentsBPM/attachment[] element:


    • On each iteration we will use a Service activity that invokes a File Adapter write service. In here we have two important parameters to set. First, the payload itself. The file adapter awaits binary data in base64 format (string). We have to map it using XPath (Simple mapping doesn't recognize a String as a base64-binary valid target):

     Second, we must set the target filename using the Service Properties dialog box:

     Again, note how we're making use of the loopCounter index variable to get the right element within the embedded subprocess iteration.

    Handling UCM attachments will be part of a different and upcoming blog entry. Once I finish will all posts on this matter, I will upload the whole sample project to java.net.

    Comments:

    Hi can you please share the xsd?

    Posted by Saranya on June 05, 2012 at 12:20 AM PDT #

    i am looking for a similar case study. Just want to check if you have uploaded the above sample in java.net?

    Posted by Vikas on July 12, 2012 at 01:58 AM PDT #

    Thank a lot for the detailed info.

    I did the whole thing step by step.But I am getting this error :
    Non Recoverable System Fault :

    <bpelFault><faultType>0</faultType><selectionFailure xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"><part name="summary"><summary>empty expression result. The expression hwf:getTaskAttachmentContents(bpmn:getDataObject('UserTask1LocalExecData')/ns1:systemAttributes/ns1:taskId,bpmn:getDataObject('AttachmentBPM')/ns:attachment[ns:attachment[bpmn:getActivityInstanceAttribute('subprocess2', 'loopCounter')]/ns:filename) is empty. An attempt to read or copy data referenced or computed by the XPath expression either had invalid data, according to the XML schema, or did not contain certain optional data. Ensure that the variable or expression result named in the error message is not empty. Enable XML schema validation of related data elements to ensure the run-time data is valid. </summary></part></selectionFailure></bpelFault>

    I am using 11g.
    I tried to do a lot of debugging and seems that even with constant values 'hwf:getTaskAttachmentContents( ' is producing null values.

    need your help urgently

    Posted by Soham on September 12, 2012 at 03:51 AM PDT #

    Hi,

    Can you please upload the project.

    Thanks/Steve

    Posted by Steve on November 21, 2012 at 09:48 AM PST #

    Hi

    Very well explained.
    How do we handle the reverse case, where you need to add multiple attachments. How is the mapping done?

    There is an 'Attachment' type in the schema while creating business objects, to which is a '<>' symbol which shows that it is an array(Created attachmentsPDO based on this).
    So, what I've done is (I have an array of UCM Response from a BPEL Process in a ProcessDataObject) - using an XSLT for-each, looped over UCMResponse and added each to the attachmentsPDO that was created as above.
    But when I try to map this to the attachments in TaskExecData of a HumanTask Input, it is not letting me do it (Mine is a 11.1.1.5 Pre-feature Pack, so old mapper style exists). This means that the attachmentsPDO that I created was not an array. How do I create an array of some existing type? that would resolve my problem. (In loopDataObjects, we have a flexibility to create Array of a particular data object)

    Please note that for single attachment, without that for-each loop, direct mapping to ExecData.attachments, it is working fine. For multiple, it is saying that multiple nodes exist but only single node is expected

    Posted by guest on May 17, 2013 at 06:05 AM PDT #

    Post a Comment:
    • HTML Syntax: NOT allowed
    About

    Technical and in-depth articles and samples on BPM 11g.

    Search

    Archives
    « April 2014
    SunMonTueWedThuFriSat
      
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    24
    25
    26
    27
    28
    29
    30
       
           
    Today