In this article, we take a look at merging data from HTML5 form submission with XDPtemplate to generate pdf using output service.

Please visit the AEM Forms samples page for a link to a live demo of this capability.

HTML5 forms are xfa form templates rendered in HTML5 format. To learn about HTML5 forms, please read the online documentation.

A common use case is to merge the HTML5 data with XDP to generate the PDF. To accomplish this use case we need to do the following

Capture the data from the HTML5 form submission

Convert the data into com.adobe.aemfd.docmanager.Document object.

Use AEM Forms Output service to merge the submitted data with the XDP template to generate the PDF

Stream the PDF back to the user submitting the HTML5 form

Configure submit URL of XDP template

The submit URL you specify here will be invoked when the user submits the HTML5 form. This URL is typically a POST end point within AEM .We get access to the submitted data,merge it with XDP template using output service and stream the PDF back to the submitter.

<%@include file="/libs/foundation/global.jsp"%>
<%@ page import="*,,*,javax.xml.*,javax.xml.transform.dom.*,javax.xml.parsers.*,javax.xml.transform.*,org.xml.sax.InputSource,org.w3c.dom.*,com.adobe.fd.output.api.OutputService,com.adobe.aemfd.docmanager.Document,*,javax.jcr.Node,com.adobe.fd.output.api.PDFOutputOptions,java.util.Random,java.sql.Timestamp,javax.jcr.Binary,org.apache.commons.logging.Log,org.apache.commons.logging.LogFactory"%>
		Log logger = LogFactory.getLog(this.getClass());
    	logger.debug("##### In Mobile Forms to PDF Demo");
		com.mergeandfuse.getserviceuserresolver.GetResolver aemDemoListings = sling.getService(com.mergeandfuse.getserviceuserresolver.GetResolver.class);
		StringBuffer stringBuffer = new StringBuffer();
		String line = null;
		    	BufferedReader reader = request.getReader();
		    	while ((line = reader.readLine()) != null)
		  	} 	catch (Exception e) 
		  		String xmlData = new String(stringBuffer);
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
    			DocumentBuilder builder;  
        			builder = factory.newDocumentBuilder();  
        			org.w3c.dom.Document xmlDocument = builder.parse(new InputSource(new StringReader(xmlData)));  
        			logger.debug("$$$$ Got xml Document");
					TransformerFactory transformerFactory = TransformerFactory.newInstance();
					ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
					Transformer transformer = transformerFactory.newTransformer();
					DOMSource source = new DOMSource(xmlDocument);
					StreamResult outputTarget = new StreamResult(outputStream);
					TransformerFactory.newInstance().newTransformer().transform(source, outputTarget);
					InputStream xmlDataIs = new ByteArrayInputStream(outputStream.toByteArray());
					logger.debug("The input Stream length ...."+xmlDataIs.available());
					com.adobe.aemfd.docmanager.Document xmlDataDoc = new com.adobe.aemfd.docmanager.Document(xmlDataIs);
         			logger.debug("##### got xmlDataDoc");
	        		OutputService outputService = sling.getService(OutputService.class);
					if(outputService == null)
    						logger.debug("The output service is null.....");

                 	logger.debug("##### got output service");
					PDFOutputOptions pdfOptions = new PDFOutputOptions();

                	// get the xdp template

    	            resource = resourceResolver.getResource("/apps/AEMFormsDemoListings/MobileFormToPDF/address.xdp");
					Node xdpDocument = resource.adaptTo(Node.class);
               		Node jcrContent = xdpDocument.getNode("jcr:content");
					InputStream is =  jcrContent.getProperty("jcr:data").getBinary().getStream();
					com.adobe.aemfd.docmanager.Document xdpTemplate = new com.adobe.aemfd.docmanager.Document(is);
					com.adobe.aemfd.docmanager.Document generatedPDF = outputService.generatePDFOutput(xdpTemplate, xmlDataDoc, pdfOptions);
                	response.addHeader("Content-Disposition", "attachment; filename=AemFormsRocks.pdf");
                	response.setContentLength((int) generatedPDF.length());
                	InputStream fileInputStream =  generatedPDF.getInputStream();
                	OutputStream responseOutputStream = response.getOutputStream();
					int bytes;
                	while ((bytes = != -1) {

				    } catch (Exception e) {  
		  			logger.debug("The xml data submiited was  "+xmlData);

Create service user

  • Create a system user by following this document. Please deploy the OSGi bundle associated with that article
  • Grant read permission to system user "data" on the following node     apps/AEMFormsDemoListings/MobileFormToPDF/address.xdp. We will use the system user to access the address.xdp template to merge data 


To get this working on your server please follow the following steps. This article is assuming that AEM is installed and running on localhost 4502.

  • Download and install the assets related to this article using the package manager
  • Create a service user as described in this article. Provide the necessary read prvileges to the system user "data" on the  /apps/AEMFormsDemoListings/MobileFormToPDF/address.xdp node.
  • Configure the submit url of the MobileFormToPDF template. Make sure the port number is matching your AEM installtion.
  • Preview your template
  • Fill in the form and submit. 
  • You should get back PDF with the data merged from the HTML5 form submission