- Making House Calls Possible
- The Results
- The Server
- Rendering and Reader Extending
- Using Assembler to Combine PDFs
- Moving On
Using Assembler to Combine PDFs
As you read in Chapter 7, Adobe LiveCycle Assembler is a shared service that comes with Forms ES, Output ES, and other LiveCycle solution components. You can use the Assembler service at runtime to combine multiple PDFs into one PDF or to split one PDF into multiple PDFs. Assembler can also add additional content to the combined PDF, including page numbers, headers and footers, and even a table of contents.
This is a useful service for paperless health care solutions because Assembler can combine an interactive XFA PDF and numerous pages of flattened traditional PDFs into one cohesive document. The XFA PDF can contain the interactive fields that the user needs to complete or the digital signature field that the user needs to sign. The flattened traditional PDFs can be the legal documents or supporting agreements that need to be part of the document but don’t need to be interactive.
For example, Figure 10.11 shows a server-based system that generates a multi-page PDF that begins with an upfront informational section and ends with a one-page XFA PDF. This final page needs to be rendered as a static and interactive form so the user can digitally sign the document.

Figure 10.11 In this diagram, Assembler ES is used to create a PDF that needs to be read and signed by the end user.
The upfront legal and other information is rendered by Output ES, which offers two advantages in this case:
- Output ES will create a flattened PDF that is locked down and cannot be changed by the user.
- In many cases, Output ES will render faster and create a smaller file size compared to Forms ES.
If your paperless system includes the rendering of a multipage document and only some of the pages need to be interactive, you may be able to improve the performance of your system by rendering the noninteractive pages with Output ES and combining them with the interactive XFA PDFs using the Assembler service.
The following code shows how the Assembler service can be called to assemble the different PDF files illustrated in Figure 10.11. Comments at the beginning of each section of code explain the subsequent lines:
private static Document assemblerService(ServiceClientFactory scf, Document xfaDoc, Document nonxfaDoc) { //Generate an Assembler Service client object AssemblerServiceClient assemblerClient = new AssemblerServiceClient(scf); //Construct the DDX StringBuffer ddxStr = new StringBuffer(); ddxStr.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); ddxStr.append("<DDX xmlns=\"http://ns.adobe.com/DDX/1.0/\">"); ddxStr.append("<PDF result=\"AssemblerResultPDF.pdf\">"); ddxStr.append("<PDF source=\"" + "nonxfaDoc" + "\">"); ddxStr.append("<NoForms/>"); ddxStr.append("</PDF>"); ddxStr.append("<PDF source=\"" + "xfaDoc" + "\" baseDocument=\"true\">"); ddxStr.append("</PDF></PDF></DDX>"); //Create a Document object for the DDX java.io.InputStream is = new java.io.ByteArrayInputStream(ddxStr.toString().getBytes()); Document myDDX = new Document(is); //Create a Map object to store the PDF source documents Map inputs = new HashMap(); //Place two entries into the Map object inputs.put("xfaDoc",xfaDoc); inputs.put("nonxfaDoc",nonxfaDoc); //Create an AssemblerOptionsSpec object AssemblerOptionSpec assemblerSpec = new AssemblerOptionSpec(); assemblerSpec.setFailOnError(true); //Submit the job to Assembler service AssemblerResult jobResult = null; try { jobResult = assemblerClient.invokeDDX(myDDX,inputs,assemblerSpec); } catch (Exception e1) { e1.printStackTrace(); System.out.println("Error OCCURRED: "+e1.getMessage()); } java.util.Map allDocs = jobResult.getDocuments(); //Retrieve the resulting PDF document from the Map object Document outDoc = null; //Iterate through the map object to retrieve the resulting PDF document for (Iterator i = allDocs.entrySet().iterator(); i.hasNext();) { // Retrieve the Map object's value Map.Entry e = (Map.Entry)i.next(); Object o = e.getValue(); if (o instanceof Document) { //Cast the Object to a Document outDoc = (Document)o; } } return outDoc; }
Working with Assembler and DDX
Assembler relies on a DDX (Document Description XML) file for the specific instructions on how PDFs should be combined together and what the resultant document should look like. In the preceding example, the DDX file is constructed on the fly with the following code:
//Construct the DDX file StringBuffer ddxStr = new StringBuffer(); ddxStr.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); ddxStr.append("<DDX xmlns=\"http://ns.adobe.com/DDX/1.0/\">"); ddxStr.append("<PDF result=\"AssemblerResultPDF.pdf\">"); ddxStr.append("<PDF source=\"" + "nonxfaDoc" + "\">"); ddxStr.append("<NoForms/>"); ddxStr.append("</PDF>"); ddxStr.append("<PDF source=\"" + "xfaDoc" + "\" baseDocument=\"true\">"); ddxStr.append("</PDF></PDF></DDX>");
This DDX file is passed as a parameter to the invokeDDX method:
jobResult = assemblerClient.invokeDDX(myDDX,inputs,assemblerSpec);
DDX is a declarative markup language, and you can use DDX to manipulate documents while you assemble or disassemble them. You can add or remove any of the following elements at runtime with DDX:
- Headers and footers
- Watermarks or backgrounds
- Page numbering
- File attachments, bookmarks, comments, and links
For instance, you can combine two PDFs and add a watermark to them with this simple DDX file:
<DDX xmlns="http://ns.adobe.com/DDX/1.0/"> <PDF result="result"> <PDF source="sourcePDF1"/> <PDF source="sourcePDF2"/> <Watermark rotation="30" scale="900%" opacity="25%"> <StyledText> <p>Confidential</p> </StyledText> </Watermark> </PDF> <?ddx-source-hint name="sourcePDF1"?> <?ddx-source-hint name="sourcePDF2"?> </DDX>
The watermark will not interfere with your existing PDF content because it will be placed behind the content. It is best to set the opacity of your watermark to a number less than 50 so that any text overlaying the watermark remains readable. Your resultant PDF will look like Figure 10.12.

Figure 10.12 You can add watermarks—such as the “Confidential” watermark shown here—to your files with Assembler and DDX.