Expand my Community achievements bar.

SOLVED

Issue converting a Dynamic XFA PDF to Static XFA PDF when it includes text fields that span more than one page using Java

Avatar

Level 2

Hello,

I have a Dynamic XFA PDF form that collects data.  This includes a text field set to 'Allow Multiple Lines'.

The Dynamic XFA PDF needs to be converted to a Static XFA PDF so that DocuSign can process it for signing.

The problem arises when there are so many lines in the text field, that it spans a page break.

 

For explanation purposes, lets say the field can contain 30 lines of text before causing a page break and splitting the field.

Case 1:  30 line of text - no problem, Dynamic and Static PDF look as expected.

Case 2:  More than 30 lines of Text ( 100 Line example ) -

               Dynamic PDF looks as expected ( lines 1 to 30 on page 1, and 31 to 100 on page 2).

               Static PDF has issues - the proper amount of vertical space is reserved across 2 pages for 100 lines of content. 

                                                     (Page 1 shows Line 1 to 30,  Page 2 shows lines 1 to 70) - this repeats the first 30 lines and never shows the last 30 lines.

I am using renderPDFForm2 - passing in a PDFFormRenderSpec that has RenderAtClient = No to convert the Dynamic XFA to Static.

 

Am I missing something or is this a bug?

 

Thank You

Mark

 

  

1 Accepted Solution

Avatar

Correct answer by
Level 2

I believe I have found the solution to this issue.

I needed to render the PDF with setGenerateServerAppearance(true), and then send the output directly into Assembler to convert it to a Static XFA, with Tagging renderAtClient set False, and Tagging enabled without re-opening the document.

 

This generates the proper flowed content and split text fields render as expected without scrollbars or plus signs.

 

Here is the DDX for Asssembler:

<DDX xmlns="http://ns.adobe.com/DDX/1.0/">

    <PDF result="flattenedform.pdf" save="Full">

        <PDF source="docsource"><NoXFA flatten="true"/></PDF>

    </PDF>

    <XFAConversionSettings renderAtClient="false" tagged="true"/>

</DDX>

 

Here is some code I put together in Workbench/ExecuteScript that does what I needed: (not the cleanest)

 

/*
patExecContext.getProcessDataStringValue("/process_data/xmlResult/RESULT/err_dttm")
getProcessDataDocumentValue
getProcessDataStringValue
http://192.168.1.72:8080/lc/libs/ws/index.html

*/
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.adobe.livecycle.assembler.client.* ;

import com.adobe.livecycle.contentservices.client.CRCResult;
import com.adobe.livecycle.contentservices.client.impl.DocumentManagementServiceClientImpl;
import com.adobe.livecycle.formsservice.client.* ;

import com.adobe.livecycle.formsservice.client;
import java.util.* ;
import java.util.Map;
import java.util.Entry;
import java.io.InputStream;

import java.io.File;
import java.io.FileInputStream;

import com.adobe.idp.Document;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactory;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactoryProperties;
import com.adobe.livecycle.formdataintegration.client.* ;

System.out.println("@@@ AEMF Test @@@");

//Create a ServiceClientFactory object
ServiceClientFactory myFactory = ServiceClientFactory.createInstance();

System.out.println("@@@ AEMF A @@@");

//Create a FormsServiceClient object
FormsServiceClient formsClient = new FormsServiceClient(myFactory);
System.out.println("@@@ AEMF B @@@");

//Create and load document variables for the Document XML Data, and the DDX
Document oInputData = patExecContext.getProcessDataDocumentValue("/process_data/xmlData");
Document myDDXFile = patExecContext.getProcessDataDocumentValue("/process_data/xmlDDX");

System.out.println("@@@ AEMF C @@@");
//Get the form design from Content Services (deprecated)
Document formDesign = patExecContext.getProcessDataDocumentValue("/process_data/docTemplate");

System.out.println("@@@ AEMF D @@@");
//Cache the PDF form
PDFFormRenderSpec pdfFormRenderSpec = new PDFFormRenderSpec();
pdfFormRenderSpec.setAcrobatVersion(AcrobatVersion.Acrobat_8);
pdfFormRenderSpec.setCacheEnabled(new Boolean(true));
pdfFormRenderSpec.setLinearizedPDF(true);
pdfFormRenderSpec.setGenerateServerAppearance(true);
pdfFormRenderSpec.setTaggedPDF(true);
//pdfFormRenderSpec.setRenderAtClient(RenderAtClient.No);

//Invoke the renderPDFForm2 and pass to the Document that contains the form design

System.out.println("@@@ AEMF E @@@");
FormsResult formOut = formsClient.renderPDFForm2(
formDesign,
oInputData,
pdfFormRenderSpec,
null,
null);

System.out.println("@@@ AEMF F @@@");

//Create a Document object that stores form data
Document myData = formOut.getOutputContent();

System.out.println("@@@ AEMF G @@@");
//Get the content type of the response and
//set the HttpServletResponse object?s content type
String contentType = myData.getContentType();
//resp.setContentType(contentType);

System.out.println("@@@ AEMF H @@@");

// ASSEMBLER
//Create a ServiceClientFactory instance
ServiceClientFactory myASMFactory = ServiceClientFactory.createInstance();

//Create an AssemblerServiceClient object
AssemblerServiceClient assemblerClient = new AssemblerServiceClient(myASMFactory);

System.out.println("@@@ AEMF I @@@");
//Create an empty Output document
// Map<String, Object> inputs = new HashMap<String, Object>();
Document outDoc = null;

System.out.println("@@@ AEMF J @@@");
//Create a Document object based on the source file
Document myPDFDXXSource = new Document(myData);

//Create a map to contain the input assets
Map inputs = new HashMap();

//Place the entry into the Map object
inputs.put("docsource",myPDFDXXSource);

//Create a Document object based on the DDX file data
Document myDDX = new Document(myDDXFile);

//Create an AssemblerOptionsSpec object
AssemblerOptionSpec assemblerSpec = new AssemblerOptionSpec();
assemblerSpec.setFailOnError(false);

//Submit the job to Assembler service and get back a non-interactive PDF document
AssemblerResult jobResult = assemblerClient.invokeDDX(myDDX, inputs, assemblerSpec);

//Get the Documents from the job result object
java.util.Map allDocs = jobResult.getDocuments();

System.out.println(allDocs);

//Get the first result document
int count = 1;
for (Iterator i = allDocs.entrySet().iterator(); i.hasNext(); ) {
// Retrieve the Map object's value
Map.Entry e = (Map.Entry)i.next();
//Get the key name as specified in the
//DDX document
String keyName = (String)e.getKey();
System.out.println("---->" + keyName);
Object o = e.getValue();
outDoc = (Document)o;
System.out.println("Before Temp");
Document myDDXOutData = outDoc;
System.out.println("After Temp");

}


System.out.println("@@@ AEMF K @@@");

//Save the non-interactive PDF document
Document myDDXOutData = outDoc;

System.out.println("@@@ AEMF Test @@@");


patExecContext.setProcessDataDocumentValue("/process_data/docResult", myData);

patExecContext.setProcessDataDocumentValue("/process_data/docDDXResult", myDDXOutData);

 

Thanks Again for your interest and assistance.

Mark

View solution in original post

10 Replies

Avatar

Community Advisor

Share your form @ (vkatoch07@gmail.com) will have a look.

Avatar

Community Advisor

I have checked your form and I created one sample static form with a field and rendered it with data that span 2-3 pages. It's behaving like this only, Field is breaking into different pages but there is a scroll bar in the field and all data is available on each page. I can see the whole data on every page, unlike dynamic pdf.

Avatar

Correct answer by
Level 2

I believe I have found the solution to this issue.

I needed to render the PDF with setGenerateServerAppearance(true), and then send the output directly into Assembler to convert it to a Static XFA, with Tagging renderAtClient set False, and Tagging enabled without re-opening the document.

 

This generates the proper flowed content and split text fields render as expected without scrollbars or plus signs.

 

Here is the DDX for Asssembler:

<DDX xmlns="http://ns.adobe.com/DDX/1.0/">

    <PDF result="flattenedform.pdf" save="Full">

        <PDF source="docsource"><NoXFA flatten="true"/></PDF>

    </PDF>

    <XFAConversionSettings renderAtClient="false" tagged="true"/>

</DDX>

 

Here is some code I put together in Workbench/ExecuteScript that does what I needed: (not the cleanest)

 

/*
patExecContext.getProcessDataStringValue("/process_data/xmlResult/RESULT/err_dttm")
getProcessDataDocumentValue
getProcessDataStringValue
http://192.168.1.72:8080/lc/libs/ws/index.html

*/
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.adobe.livecycle.assembler.client.* ;

import com.adobe.livecycle.contentservices.client.CRCResult;
import com.adobe.livecycle.contentservices.client.impl.DocumentManagementServiceClientImpl;
import com.adobe.livecycle.formsservice.client.* ;

import com.adobe.livecycle.formsservice.client;
import java.util.* ;
import java.util.Map;
import java.util.Entry;
import java.io.InputStream;

import java.io.File;
import java.io.FileInputStream;

import com.adobe.idp.Document;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactory;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactoryProperties;
import com.adobe.livecycle.formdataintegration.client.* ;

System.out.println("@@@ AEMF Test @@@");

//Create a ServiceClientFactory object
ServiceClientFactory myFactory = ServiceClientFactory.createInstance();

System.out.println("@@@ AEMF A @@@");

//Create a FormsServiceClient object
FormsServiceClient formsClient = new FormsServiceClient(myFactory);
System.out.println("@@@ AEMF B @@@");

//Create and load document variables for the Document XML Data, and the DDX
Document oInputData = patExecContext.getProcessDataDocumentValue("/process_data/xmlData");
Document myDDXFile = patExecContext.getProcessDataDocumentValue("/process_data/xmlDDX");

System.out.println("@@@ AEMF C @@@");
//Get the form design from Content Services (deprecated)
Document formDesign = patExecContext.getProcessDataDocumentValue("/process_data/docTemplate");

System.out.println("@@@ AEMF D @@@");
//Cache the PDF form
PDFFormRenderSpec pdfFormRenderSpec = new PDFFormRenderSpec();
pdfFormRenderSpec.setAcrobatVersion(AcrobatVersion.Acrobat_8);
pdfFormRenderSpec.setCacheEnabled(new Boolean(true));
pdfFormRenderSpec.setLinearizedPDF(true);
pdfFormRenderSpec.setGenerateServerAppearance(true);
pdfFormRenderSpec.setTaggedPDF(true);
//pdfFormRenderSpec.setRenderAtClient(RenderAtClient.No);

//Invoke the renderPDFForm2 and pass to the Document that contains the form design

System.out.println("@@@ AEMF E @@@");
FormsResult formOut = formsClient.renderPDFForm2(
formDesign,
oInputData,
pdfFormRenderSpec,
null,
null);

System.out.println("@@@ AEMF F @@@");

//Create a Document object that stores form data
Document myData = formOut.getOutputContent();

System.out.println("@@@ AEMF G @@@");
//Get the content type of the response and
//set the HttpServletResponse object?s content type
String contentType = myData.getContentType();
//resp.setContentType(contentType);

System.out.println("@@@ AEMF H @@@");

// ASSEMBLER
//Create a ServiceClientFactory instance
ServiceClientFactory myASMFactory = ServiceClientFactory.createInstance();

//Create an AssemblerServiceClient object
AssemblerServiceClient assemblerClient = new AssemblerServiceClient(myASMFactory);

System.out.println("@@@ AEMF I @@@");
//Create an empty Output document
// Map<String, Object> inputs = new HashMap<String, Object>();
Document outDoc = null;

System.out.println("@@@ AEMF J @@@");
//Create a Document object based on the source file
Document myPDFDXXSource = new Document(myData);

//Create a map to contain the input assets
Map inputs = new HashMap();

//Place the entry into the Map object
inputs.put("docsource",myPDFDXXSource);

//Create a Document object based on the DDX file data
Document myDDX = new Document(myDDXFile);

//Create an AssemblerOptionsSpec object
AssemblerOptionSpec assemblerSpec = new AssemblerOptionSpec();
assemblerSpec.setFailOnError(false);

//Submit the job to Assembler service and get back a non-interactive PDF document
AssemblerResult jobResult = assemblerClient.invokeDDX(myDDX, inputs, assemblerSpec);

//Get the Documents from the job result object
java.util.Map allDocs = jobResult.getDocuments();

System.out.println(allDocs);

//Get the first result document
int count = 1;
for (Iterator i = allDocs.entrySet().iterator(); i.hasNext(); ) {
// Retrieve the Map object's value
Map.Entry e = (Map.Entry)i.next();
//Get the key name as specified in the
//DDX document
String keyName = (String)e.getKey();
System.out.println("---->" + keyName);
Object o = e.getValue();
outDoc = (Document)o;
System.out.println("Before Temp");
Document myDDXOutData = outDoc;
System.out.println("After Temp");

}


System.out.println("@@@ AEMF K @@@");

//Save the non-interactive PDF document
Document myDDXOutData = outDoc;

System.out.println("@@@ AEMF Test @@@");


patExecContext.setProcessDataDocumentValue("/process_data/docResult", myData);

patExecContext.setProcessDataDocumentValue("/process_data/docDDXResult", myDDXOutData);

 

Thanks Again for your interest and assistance.

Mark

Avatar

Level 1

Hello, I am having a simialr issue where I need to convert a Dynamic XFA PDF to a Static XFA PDF for Docusign. Are you able to help me? 

Avatar

Level 2

It would depend on the issue you are having.  The steps above detail merging the xdp and xml and generating a document that has it's rendering determined and locked in place prior to passing it to DocuSign.  What are the details of your issue?

Avatar

Level 1

The original document I need to upload to DocuSign to process for signing is a Dynamic XFA PDF created in Designer 6.5 which I do not have access.

I have been able to get a version of said document up, but not all datafields, tooltips and other field information are properly recognized by DocuSign. I was able to get a xml using Adobe, but don't have xdp. 

Just trying to save myself hours of editing fields in DocuSign. I have no programming knowledge unfortunately.

Avatar

Level 2

Hello,

Sadly, I am not sure I can assist you in this case.  The solution I found was dependent on leveraging the services of the Adobe Experience Manager server software to generate a static version of the dynamic pdf, and force all the rendering events to fire and be captured on the server.  This results in a pdf with no client side presentation rendering.

 

What I found was that the paginated field reserved the correct amount of vertical space for the content, but that the content started displaying again from the top in the second instance of the field.  It seems to be an issue with the Adobe PDF software, as I was able to trap this defect before my document was passed to DocuSign.

 

Without access to a server, I'm afraid I don't know how to guide you.  Perhaps there are other DocuSign or Static from Dynamic PDF generation focused threads that might help you. 

Avatar

Level 1

Why not convert the document to PNG, open the image with Acrobat, detect the texts, and save the PNG back?

Avatar

Adobe Champion

The big issue with converting the forms into an image with Acrobat is that the document is no longer a document it is an image. That means if the file is viewed in a digital format it will not be accessible and you will have issues modifying the file in the future.

 

If the file doesn't change and is only being used as a print file then you may get away with using an image but it is important to remember that forms and images are different things and have different functionality associated with them.

Avatar

Level 1

You're right. When I encountered the issue, it was for a DocuSign form, and the owner only needed the information in the Adobe document attachment. So, the image approach worked, but I agree with your point.