Enabling Reader Extension to PDF using AEM Forms APIs
This article provides the steps on how to programmatically enable Reader Extension to a PDF file using AEM Forms APIs.

The business use case
An organization wants to provide a seamless onboarding experience to their prospective users. The organization wants to do this by allowing their users to switch from an online to an offline PDF form mid-way or even download an offline form to start the process where they can continue to enter their details and finally submit the information. This will provide a seamless onboarding experience to the user thus leading to more satisfied users in the long run.

Pre-requisites
- AEM 6.4+
- Forms Add-on
- AEM Maven project should have the following dependencies (artifactId)
adobe-lc-forms-bedrock-connector
adobe-aemds-core-docmanager
adobe-aemfd-docassurance
adobe-aemfd-readerextensions
adobe-aemfd-signatures
com.adobe.aemfd
Solution
The solution is to use AEM forms technology and leveraging the reader extension mechanism where a PDF form can be enabled for editing to the end user. The process of programmatically enabling reader extension in the application is a technical one and comprises of the following steps
- Open the sling.properties that is there in the folder crx-quickstart/conf folder of your AEM extension and add the below lines
sling.bootdelegation.class.com.rsa.jsafe.provider.JsafeJCE=com.rsa.*
sling.bootdelegation.class.org.bouncycastle.jce.provider.BouncyCastleProvider=org.bouncycastle.
2. Configure the Apache Sling Service User Mapper Service for user fd-service and add a mapping in the format of ‘bundleId [ “:” subServiceName ] “=” userName’
3. Add the same mapping in Apache Sling Service User Mapper Service Amendment
Steps 2 and 3 are required in order to get the repository connection and is the preferred way instead of using resolverFactory.loginAdministrative
4. The next step is to create a keystore for user fd-service and adding the provided certificate for the reader extension
a) Go to AEM Logo -> Tools -> Security -> Users -> fd-service


b) Clicking on Keystore will bring up the screen

c) Clicking on Create Keystore will bring up the screen

d) Add a New Password and click Save after adding in both fields. This will bring up

e) Enter data in the relevant section in the above screen. The following needs to be entered for the fields
"realias" for New Alias
Select the provided PFX file that you would be having for the field Keystore File
Enter the password for the PFX file in the fields Keystore File Password and Private Key Password
The Private Key Alias can be extracting by executing the command "keytool list -v -keystore <path to PFX file> -storetype pkcs12"
f) Click on Save and Close to exit the editing of fd-service.
5) The AEM form is created based on a XSD schema which allows us to Download a Document of Record as a XDP file. This can be done by clicking on the Download Document of Record link as shown in the below screenshot

6) The XDP file can be saved as Adobe Dynamic XML (PDF) using Livecycle Designer which can be stored in AEM as a template.
a) This template can be provided on need basis and the data in the XML from the online form can be merged programmatically and provided for download as an offline form to the end user. This step is only for scenarios where a user is either filling up an online form and wants to save a draft on their system or there is a requirement to merge with some data from the system. A code snippet is provided below
org.w3c.dom.Node result = (org.w3c.dom.Node) xPath.evaluate("afData/afBoundData/details", doc, XPathConstants.NODE);Document xmlDocument = new Document(new ByteArrayInputStream((XMLUtils.nodeToString(result)).getBytes(StandardCharsets.UTF_8)));Document pdfDocument = new Document(inputStream);Document generatedDocument = this.formsService.importData(pdfDocument, xmlDocument);
b) The next step is to programmatically apply the reader extension to the generated document before being sent for download as an offline PDF. A code snippet is provided below. Note that the credential alias is same as the value that was provided at the time of creating the KeyStore.
public Document enableReaderExtension(Document document, ResourceResolver resolver) throws Exception {UsageRights usageRights = new UsageRights();usageRights.setEnabledComments(true);
usageRights.setEnabledFormFillIn(true);
usageRights.setEnabledDigitalSignatures(true);
usageRights.setEnabledEmbeddedFiles(true);
usageRights.setEnabledFormDataImportExport(true);ReaderExtensionOptions readerOpts = ReaderExtensionOptions.getInstance();readerOpts.setReOptions(new ReaderExtensionsOptionSpec(usageRights, "Enable commenting in PDF and Form Fill In"));
readerOpts.setCredentialAlias("realias");
readerOpts.setResourceResolver(resolver);ReaderExtensionsOptionSpec reOptionsSpec = new ReaderExtensionsOptionSpec(usageRights, "Sample ARES");
readerOpts.setReOptions(reOptionsSpec);return this.docAssuranceService.secureDocument(document, null, null, readerOpts, null);}
7) The Document that is returned from the above method is then finally made available for download to the user. A code snippet is provided below
Document generatedDocument = this.docService.enableReaderExtension(generatedDocument, resolver);
outputInStream = generatedDocument.getInputStream();response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=accountapplication.pdf");
out = response.getOutputStream();
byte[] buffer = new byte[4096];
int length;
while ((length = outputInStream.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
out.flush();
Summary
Finally, using the above steps, a user will have an offline PDF form on their device/desktop, on which they can fill up the information. The information will be sent to the server once the user clicks on the Submit button on the form.
Referring all of the above, it should be clear on how to programmatically apply the reader extension on an offline PDF form and allow the users to submit information once they come online.
It should be easy to implement the same in any AEM Forms implementation that meets the pre-requisites.