Create Custom Profile
[AEM Forms 6.5]{class="badge informative"}
In this part we will create a custom profile. A profile is responsible for rendering the XDP as HTML. A default profile is provided out of the box for rendering XDP’s as HTML. It represents a customized version of Mobile Forms Rendition service. You can use the Mobile Form Rendition service to customize appearance, behavior, and interactions of the Mobile Forms. In our custom profile we will capture the data filled in the mobile form using the guidebridge API. This data is then sent to custom servlet that will then generate an interactive PDF and stream it back to the calling application.
Get the form data using the formBridge
JavaScript API. We make use of the getDataXML()
method:
window.formBridge.getDataXML({success:suc,error:err});
In the success handler method we make a call to custom servlet running in AEM. This servlet will render and return interactive pdf with the data from the mobile form
var suc = function(obj) {
let xhr = new XMLHttpRequest();
var data = obj.data;
let postURL ="/bin/generateinteractivepdf";
console.log("The data: " + data);
xhr.open('POST',postURL);
xhr.responseType = 'blob';
let formData = new FormData();
formData.append("formData", data);
formData.append("xdpPath", window.location.pathname);
let parts = window.location.pathname.split("/");
let formName = parts[parts.length-2];
const updatedFilename = formName.replace(/\.xdp$/, '.pdf');
xhr.send(formData);
xhr.onload = function(e) {
console.log("The data is ready");
if (this.status == 200) {
var blob = new Blob([this.response],{type:'image/pdf'});
let a = document.createElement("a");
a.style = "display:none";
document.body.appendChild(a);
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = updatedFilename;
a.click();
window.URL.revokeObjectURL(url);
}
}
}
Generate Interactive PDF
The following is the servlet code that is responsible for rendering interactive pdf and returning the pdf to the calling application. The servlet invokes mobileFormToInteractivePdf
method of the custom DocumentServices OSGi service.
package com.aemforms.mobileforms.core.servlets;
import com.aemforms.mobileforms.core.documentservices.GeneratePDFFromMobileForm;
import com.adobe.aemfd.docmanager.Document;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletOutputStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
@Component(service={Servlet.class}, property={"sling.servlet.methods=post", "sling.servlet.paths=/bin/generateInteractivePDF"})
public class GeneratePDFFromMobileFormData extends SlingAllMethodsServlet implements Serializable {
private static final long serialVersionUID = 1L;
private final transient Logger logger = LoggerFactory.getLogger(this.getClass());
@Reference
GeneratePDFFromMobileForm generatePDFFromMobileForm;
protected void doPost(SlingHttpServletRequest request,SlingHttpServletResponse response) throws IOException {
String dataXml = request.getParameter("formData");
logger.debug("The data is "+dataXml);
InputStream inputStream = new ByteArrayInputStream(dataXml.getBytes(StandardCharsets.UTF_8));
Document submittedXml = new Document(inputStream);
Document interactivePDF = generatePDFFromMobileForm.generateInteractivePDF(submittedXml,request.getParameter("xdpPath"));
interactivePDF.copyToFile(new File("interactive.pdf"));
try {
InputStream fileInputStream = interactivePDF.getInputStream();
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename=AemFormsRocks.pdf");
response.setContentLength(fileInputStream.available());
ServletOutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
responseOutputStream.flush();
responseOutputStream.close();
}
catch(Exception e)
{
logger.debug(e.getMessage());
}
}
}
Render Interactive PDF
The following code makes use of the Forms Service API to render interactive PDF with the data from the mobile form.
package com.aemforms.mobileforms.core.documentservices.impl;
import com.adobe.aemfd.docmanager.Document;
import com.adobe.fd.forms.api.AcrobatVersion;
import com.adobe.fd.forms.api.FormsService;
import com.adobe.fd.forms.api.FormsServiceException;
import com.adobe.fd.forms.api.PDFFormRenderOptions;
import com.aemforms.mobileforms.core.documentservices.GeneratePDFFromMobileForm;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = GeneratePDFFromMobileForm.class, immediate = true)
public class GeneratePDFFromMobileFormImpl implements GeneratePDFFromMobileForm {
@Reference
FormsService formsService;
private transient Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public Document generateInteractivePDF(Document xmlData, String xdpPath)
{
String uri = "crx:///content/dam/formsanddocuments";
String xdpName = xdpPath.substring(31, xdpPath.lastIndexOf("/jcr:content"));
log.debug("####In mobile form to interactive pdf#### " + xdpName);
PDFFormRenderOptions renderOptions = new PDFFormRenderOptions();
renderOptions.setAcrobatVersion(AcrobatVersion.Acrobat_11);
renderOptions.setContentRoot(uri);
Document interactivePDF = null;
try
{
interactivePDF = this.formsService.renderPDFForm(xdpName, xmlData, renderOptions);
}
catch (FormsServiceException e)
{
log.error(e.getMessage());
}
return interactivePDF;
}
}