Issue converting a Dynamic XFA PDF to Static XFA PDF when it includes text fields that span more than one page using Java | Community
Skip to main content
Level 2
August 10, 2023
Solved

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

  • August 10, 2023
  • 3 replies
  • 3810 views

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

 

  

Best answer by MarkAtArtech

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

3 replies

Vijay_Katoch
Community Advisor
Community Advisor
August 11, 2023

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

Vijay_Katoch
Community Advisor
Community Advisor
August 14, 2023

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.

bbak4379
May 28, 2024

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? 

Level 2
May 29, 2024

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?

November 6, 2024

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

Angele_Taylor
Adobe Champion
Adobe Champion
November 7, 2024

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.

November 7, 2024

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.