Posts tagged "LiveCycle"

Purging long-lived processes in LiveCycle

The amount of data, both disk space and database rows, that is saved by LiveCycle can build over time. Sooner or later the LiveCycle administrator will probably find himself having to clean up and get rid of old, unused, completed, long-lived processes.

Creating images from PDFs that are proportionally the same size in LiveCycle ES2 and ES3

Problem:

What if images produced from PDFs within the timeline of LiveCycle need to all be the same size? PDFs that are the same size, dimension-wise, can turn out as images of different sizes after processing with the toImage activity. For example, two PDFs could be 8.5 x 11 inches in size. But one would convert to an image that is 1700 x 2200 pixels in size and the other would convert to an image that is 2550 x 3300 pixels in size.

Resolution:

Use the same DPI argument for each of the PDFs. The resulting images will not be an exact match with one another, however. In my test a variation of ten pixels or so could be seen as the result of differences in the areas of the PDF page that are converted to image. But PDFs that are the same dimensions before conversions result in images that are the same pixel height and width (or very close to it).

See Also:

The documentation for the toImage operation of the Convert PDF service

Appending values to collections within Process Management orchestrations

Within the Process Management module for ADEP Document Services or LiveCycle, values returned from services, if not explicitly XML or primitives, are Java-based. These values, like XML in orchestrations, can be created, modified and deleted using the Set Value service or by using BeanScript within the Execute Script service.

Manipulating Java objects within BeanScript is very similar to how it works in Java. However, setting Java objects in the Set Value service can be very different. It uses XPath as its language. Values for XML behave as described within the W3C XPath specification. In addition, associating schema with XML supports functionality to add values to XML that fit a very specific object model. Though XPath is meant for querying XML, it has been purposed for setting and editing the Java elements within orchestrations as well.

There are many differences in the way Java objects are treated within the Set Value service’s XPath than XML or primitives behave. One difference is in the way items are added to collections within Java objects.

First, to create a collection, a variable must be set to be a new, empty, collection:

/process_data/myList = empty-list()

To append an item to an already existing collection, set the collection to be equal that value you wish to append:

/process_data/myList = empty-list()
/process_data/myList = "a" // collection is now ["a"]
/process_data/myList = "b" // collection is now ["a","b"]
/process_data/myList = "c" // collection is now ["a","b","c"]

To reset the value of the list, do not set it to a different collection. This only appends the collection to the existing list:

/process_data/myList = empty-list()
/process_data/myList = "a" // myList is ["a"]
/process_data/list2 = empty-list()
/process_data/list2 = "b" // list2 is ["b"]
/process_data/myList = /process_data/list2 // myList is ["a",["b"]]

To replace the value of a varible with a new list, first set the list to null:

/process_data/myList = empty-list()
/process_data/myList = "a" // myList is ["a"]
/process_data/list2 = empty-list()
/process_data/list2 = "b" // list2 is ["b"]
/process_data/myList = null
/process_data/myList = /process_data/list2 // myList is ["b"]

One big implication of this is, whenever a collection variable is set to the result of a service, if that variable is not empty the result is appended to the collection. This is sometimes desired, but can cause problems if not expected.

Creating and manipulating XML within Process Management in LiveCycle ES 2

Using xPath and creating XML is interesting in process orchestrations. The primary way of manipulating variables within processes is to use the Set Value service. This uses as its “scripting” language xPath. As a scripting language xPath is limited. It is meant to be a query language and does that very well. For creating XML, however, it can be a blunt tool.

Within a process there are three basic ways to create and edit XML.

  1. Using xPath within a Set Value service
  2. Building the XML as text and then deserializing the text into XML. This, too, uses xPath within a Set Value activity. Instead of using xPath to manipulate the XML it is used to manipulate string variables.
  3. Editing an XML variable within an Execute Script service

Using xPath to Build XML Variables

XML may be created within the Set Value service using the xPath syntax if the XML has schema associated with it.

For example, it is possible to start with an empty XML variable that is associated with a schema and add nodes.

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"

 
In this example, the variable, node, is now:

<resources>
     <resource id="itemOne" value="itemTwo"/>
</resources>

 
But what if there is more than one resource node? Let’s add code to set the value of a second resource node:

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"
/process_data/node/resources/resource[number(2)]/@id = "id for second resource"
/process_data/node/resources/resource[number(2)]/@value = "value for second resource"

 
This, sadly, fails. To be able to set the value of a node that is referenced by index, the item must already exist.

It is possible to add items to list items using xPath syntax.

/process_data/stringList = empty-list()
/process_data/stringList = "item one"
/process_data/stringList = "item two"

 
Now, /process_data/stringList[number(1)] equals “item one” and process_data/stringList[number(2)] equals “item two”

Can we do the same with XML in the xPath syntax? Unfortunately, no. The Set Value service treats Java objects (such as the list) and XML completely different.

/process_data/node = "" // make sure the XML is empty
/process_data/node/resources/resource/@value = "value for first resource"
/process_data/node/resources/resource/@id = "id for first resource"
/process_data/node/resources/resource/@id = "id for second resource"
/process_data/node/resources/resource/@value = "value for second resource"

 
This replaces the value of a node with a new value. The value of XML is now:

<resources>
     <resource id="id for second resource" value="value for second resource"/>
</resources>

 

Building XML as text

We can build an XML value in a more cumbersome way by building the xml in text.

/process_data/@nodeId = "id for first resource"
/process_data/@nodeValue = "value for first resource"
/process_data/@stringVariable = "<resources>" // add the start tag to the string
/process_data/@stringVariable = concat(/process_data/@stringVariable,"<resource") // add the beginning of the resource tag
/process_data/@stringVariable = concat(/process_data/@stringVariable," id='",/process_data/@nodeId,"'") // add the id attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable," value='",/process_data/@nodeValue,"'") // add the value attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable,"/></resource>") // close tags
/process_data/node = deserialize(/process_data/@stringVariable)

 
Building XML with text may be more cumbersome for simple XML, but it does provide a way to add nodes that xPath does not provide. In addition, a schema is not required. To add another resource to the sample above:

/process_data/@nodeId = "id for second resource"
/process_data/@nodeValue = "value for second resource"
/process_data/@stringVariable = serialize(/process_data/node) // get existing node as a string
/process_data/@stringVariable = string-before(/process_data/@stringVariable,"</resources>") // returns everything but the closing resources tag
/process_data/@stringVariable = concat(/process_data/@stringVariable,"<resource") // add the beginning of the new resource tag
/process_data/@stringVariable = concat(/process_data/@stringVariable," id='",/process_data/@nodeId,"'") // add the id attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable," value='",/process_data/@nodeValue,"'") // add the value attribute
/process_data/@stringVariable = concat(/process_data/@stringVariable,"/></resource>") // close tags
/process_data/node = deserialize(/process_data/@stringVariable) // turn string back into XML

 

Building XML using Java

Within orchestrations Java may be used within the Execute Script service. The Execute Script service within Process Management orchestrations uses BeanScript, a scriptable version of Java. Java is much more adapted to complex manipulation of XML data.

Process Management uses the Apache Xerces DOM parser to create and store XML variables within processes. Xerces is a Java implementation of W3C’s Document Object Model specification, http://www.w3.org/DOM/. The DOM specification is a standard way of manipulating XML that has been around since 1998. The Java implementation of Xerces, Xerces-J, supports DOM Level 2 version 1.0.

There is an extended explanation of how to manipulate XML within the Execute Script service within the article, Using the Execute Script Service in LiveCycle Workbench ES2 to build XML data.

How to iterate through an XML collection within LiveCycle/Document Services Process Management

The Set Value activity within Process Management orchestrations uses xPath for  building expressions. And xPath has some quirks features that can frustrate developers who are not used to it.

One thing that can be confusing is how to iterate through XML collections. The problem is caused by the fact that xPath interprets all variables as strings unless they are coerce to some other type. And this coercion can happen automatically in some circumstances.

In this case, the variable @i is treated as a number because it is being added to another number:

/process_data/@i = /process_data/@i + 1
// this performs addition and increments @i by 1

 

But when used as an xPath reference variables are treated as strings:

/process_data/@i = 1
/process_data/myXML/topElement/childElement[/process_data/@i]
// this will return the first item
/process_data/@i = 20
/process_data/myXML/topElement/childElement[/process_data/@i]
// this returns the first item, too!

 

When used a reference, always coerce variables to be a Number:

/process_data/@i = 20
/process_data/myXML/topElement/childElement[Number(/process_data/@i)]
// this returns the 20th item