You can configure Correspondence Management solution to
use Adobe® LiveCycle® Reader Extensions module. This facilitates
processing of PDF documents, such as saving, printing, and sharing,
before they are rendered. Note that configuring Reader Extensions
is not necessary if a client machine has Adobe® Acrobat® installed
on it.
Implementation overviewThe implementation for this user story involves code changes,
re-building, and re-deploying the solution. Before you begin, ensure
that you have performed the steps outlined in the Setting up your development environment chapter. After this, perform
the following steps before you implement the user story.
Add the following Document Services client JARs to the classpath
of the Services project of the Solution Template: adobe-reader-extensions-client.jar
adobe-livecycle-client.jar
adobe-usermanager-client.jar
To add these client JARs to your classpath: Copy these
to a folder named DS_SDK under the CorrespondenceManagementSolutionTemplate
folder.
In your Eclipse environment, right-click on the Services
project, select Build Path > Configure Build Path.
In the Properties pop-up window, click on Add External JARs...
Browse to the DS_SDK folder, select all three JARs and click
Open.
Notice the three client JARs added to the Build path. Click
OK to save your changes.
Next, provide a custom implementation of the DocumentRenderHandler interface
that will reader-extend the PDF.
Provide a custom implementation of the DocumentRenderHandler interface
that will help extend the PDF document. See the code snippet below for
an example: package com.adobe.icc;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.icc.ddg.api.DocumentRenderHandler;
import com.adobe.idp.Document;
import com.adobe.idp.dsc.clientsdk.ServiceClientFactory;
import com.adobe.livecycle.readerextensions.client.ReaderExtensionsOptionSpec;
import com.adobe.livecycle.readerextensions.client.ReaderExtensionsServiceClient;
import com.adobe.livecycle.readerextensions.client.UsageRights;
/**
* Register document processing handler for Reader extending PDFs.
*/
public class ReaderExtendDocumentHandler implements DocumentRenderHandler {
protected final Logger logger = LoggerFactory.getLogger(getClass());
private ServiceClientFactory serviceClientFactory;
public ServiceClientFactory getServiceClientFactory() {
return serviceClientFactory;
}
public void setServiceClientFactory(
ServiceClientFactory serviceClientFactory) {
this.serviceClientFactory = serviceClientFactory;
}
@Override
public int getHandlerType() {
return INTERACTIVE_DOCUMENT_HANDLER;
}
@Override
public Map<String, byte[]> preProcessDocument(byte[] xdp, byte[] xml) {
Map<String, byte[]> result = new HashMap<String, byte[]>();
result.put(XDP_KEY, xdp);
result.put(XML_KEY, xml);
// doing nothing here - just return what we are given
return result;
}
@Override
public byte[] postProcessDocument(byte[] inputDoc) {
logger.info("[CUSTOMIZATION] RE document...");
try {
return readerExtendDocument(inputDoc);
} catch (Exception e) {
logger.error("Failed to RE document : " + e.getMessage());
e.printStackTrace();
}
return inputDoc;
}
private byte[] readerExtendDocument(byte[] doc) throws Exception {
Document inputPDF = new Document(doc);
// Create a UsageRight object and specify specific usage rights
UsageRights useRight = new UsageRights();
useRight.setEnabledDynamicFormFields(true);
useRight.setEnabledComments(true);
useRight.setEnabledFormFillIn(true);
useRight.setEnabledDigitalSignatures(true);
useRight.setEnabledFormDataImportExport(true);
// Create a ReaderExtensionsOptions object
ReaderExtensionsOptionSpec reOptions = new ReaderExtensionsOptionSpec();
// Set the usage rights
reOptions.setUsageRights(useRight);
reOptions.setMessage("This is a Rights-Enabled PDF Document");
ReaderExtensionsServiceClient readerExtensionClient = new ReaderExtensionsServiceClient(
serviceClientFactory);
logger.info("Performing RE now...");
// Apply usage rights to a PDF document
Document rightsEnabledPDF = readerExtensionClient.applyUsageRights(
inputPDF, "PRODUCTION", null, reOptions);
InputStream is = rightsEnabledPDF.getInputStream();
long length = is.available();
byte[] bytes = new byte[(int) length];
is.read(bytes);
logger.info("RE done. Returning bytes...");
return bytes;
}
}
The following APIs have to be implemented for
the DocumentRenderHandler interface: - Map<String, byte[]> preProcessDocument(byte[]
xdpBytes, byte[] xmlBytes)
- The pre process API where you can use the XDP and XML data
used for rendering the document. We are not doing anything with
it for this user story.
- byte[] postProcessDocument(byte[])
- The API invoked from IRenderService that
determines the post processing of the document. Use this API for
your custom implementation.
- int getHandlerType()
- The API that determines type of the document being processed
(interactive or non-interactive).
Note: The
above class is present in the com.adobe.icc package
of the Services project.
Register the custom implementation to the IRenderService by
defining the following Spring initializing bean: package com.adobe.icc.bootstrap;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.adobe.icc.ReaderExtendDocumentHandler;
import com.adobe.icc.ddg.api.DocumentRenderHandler;
import com.adobe.icc.render.IRenderService;
/**
* Register document processing handlers.
*/
public class DocumentHandlerRegistration implements InitializingBean {
protected final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
IRenderService renderService; // catch hold of the RenderService reference
@Autowired
ReaderExtendDocumentHandler readerExtendDocumentHandler; // your handler's instance
public void afterPropertiesSet() throws Exception
{
List<DocumentRenderHandler> handlers = new ArrayList<DocumentRenderHandler>();
handlers.add(readerExtendDocumentHandler); // we have only one handler at this time, so add this to the list
renderService.setRenderHandlers(handlers); // register handlers
}
}
Note: The above class is present in the com.adobe.icc.bootstrap package
of the Services project.
Define appropriate beans for the custom implementation in
the adobe-cm-spring-config.xml file present at CorrespondenceManagementSolutionTemplate\Services\resources\META-INF\spring\cm\adobe-cm-spring-config.xml. See
the following example for a sample bean definition: <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-init-method="init">
//IMPORTANT: If the following higlighted lines are not defined in the adobe-cm-spring-config.xml, you need to include them
<bean id="serviceClientFactory"
factory-bean="serviceClientFactoryProvider" factory-method="getDefaultServiceClientFactory" scope="prototype">
</bean>
<bean id="lc.cm.readerExtendHandler" class="com.adobe.icc.ReaderExtendDocumentHandler">
<property name="serviceClientFactory" ref="serviceClientFactory" />
</bean>
<bean id="lc.cm.documentRegistration" class="com.adobe.icc.bootstrap.DocumentHandlerRegistration" />
<!-- ___________________ BootStraper beans _____________________ -->
<bean id="lc.cm.assetDefinitionsDeployer" class="com.adobe.icc.bootstrap.AssetDefinitionsDeployer">
<property name="assetDefinitions">
<list>
<value>/apps/solutions/cm/assetDefinitions/ConditionalDataModule.fml</value>
<value>/apps/solutions/cm/assetDefinitions/ImageModule.fml</value>
<value>/apps/solutions/cm/assetDefinitions/Letter.fml</value>
<value>/apps/solutions/cm/assetDefinitions/Layout.fml</value>
<value>/apps/solutions/cm/assetDefinitions/ListDataModule.fml</value>
<value>/apps/solutions/cm/assetDefinitions/TextModule.fml</value>
<value>/apps/solutions/cm/assetDefinitions/DataDictionary.fml</value>
<value>/apps/solutions/cm/assetDefinitions/Category.fml</value>
<value>/apps/solutions/cm/assetDefinitions/DataModule.fml</value>
<value>/apps/solutions/cm/assetDefinitions/FragmentLayout.fml</value>
<value>/apps/solutions/cm/assetDefinitions/Asset.fml</value>
</list>
</property>
<property name="defaultCharacterEncoding" value="${defaultCharacterEncoding}"/>
</bean>
</beans>
Note: Ensure that the text highlighted
above is found in the adobe-cm-spring-config.xml file. Else, you
need to include this text in the file.
The IRenderService is
exposed by the ACM Building Block. Hence, import it within the CM
solution bundle by adding a reference to it in the osgi-context.xml present
at CorrespondenceManagementSolutionTemplate\Services\resources\META-INF\spring\osgi-context.xml.
The bean would reflect the following changes: <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd">
//IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it
<import resource="cm/adobe-cm-spring-config.xml"/>
<bp:blueprint>
<!-- <bp:service interface="com.adobe.icc.ddg.api.LetterRenderService" ranking="10" ref="customRenderService">
<bp:service-properties>
<entry key="connectors.httpinvoker" value="true" />
<entry key="connectors.httpinvoker.alias" value="/lc.icc.renderlib.letterRenderService" />
</bp:service-properties>
</bp:service> -->
<bp:reference id="osgi.resourceResolverFactory" interface="org.apache.sling.api.resource.ResourceResolverFactory"/>
<bp:reference interface="org.apache.sling.settings.SlingSettingsService"/>
<bp:reference interface="com.adobe.livecycle.content.config.ApplicationManager" />
<bp:reference id="serviceClientFactoryProvider" interface="com.adobe.livecycle.dsc.clientsdk.ServiceClientFactoryProvider" />
<!-- <bp:reference interface="com.adobe.idp.applicationmanager.service.ApplicationManager" /> -->
//IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it
<bp:reference interface="com.adobe.icc.render.IRenderService" />
<bp:reference interface="com.adobe.dct.service.DataDictionaryUtilService" />
<bp:reference interface="com.adobe.dct.service.DataDictionaryRegistryService" />
<bp:reference interface="com.adobe.livecycle.content.activate.ActivateBootstrapper" />
<bp:reference id="lc.content.remote.fileService" interface="com.adobe.livecycle.content.repository.FileService" />
</bp:blueprint>
<osgix:cm-properties id="cmProps" persistent-id="com.adobe.livecycle.cm">
<prop key="tmpfolder">C:/temp</prop>
<prop key="xmlfile.name">/WEB-INF/classes/ExampleData.xml</prop>
<prop key="letterfile.name">/WEB-INF/classes/InsuranceCorrespondance.xml</prop>
<prop key="icc.letter.id.name">cmLetterName=</prop>
<prop key="icc.user.testdata.name">cmLetterState=1&cmUseTestData=1</prop>
<prop key="icc.data.url">cmDataUrl=assets/</prop>
<prop key="icc.preview.name">cmPreview=0</prop>
<prop key="defaultCharacterEncoding">UTF-8</prop>
</osgix:cm-properties>
<context:property-placeholder properties-ref="cmProps" />
<!-- IMPORTANT: This tag is responsible for enabling annotations like autowiring etc -->
//IMPORTANT: If the following higlighted lines are not defined in the adobe-cm-spring-config.xml, you need to include them
<context:annotation-config/>
<bean id="serviceClientFactory"
factory-bean="serviceClientFactoryProvider" factory-method="getDefaultServiceClientFactory">
</bean>
</beans>
Note: Ensure that the text highlighted
above is found in the the osgi-context.xml file. Else, you need
to include this text in the file.
Import packages of Services/APIs found in the LiveCycle SDK ( com.adobe.idp and com.adobe.idp.dsc)
into the BND configuration file (cmsa.bnd) of the Correspondence
Management bundle present at CorrespondenceManagementSolutionTemplate\Services\bnd\cmsa.bnd.
See the following code snippet of the BND file for an example: version=1.0.0
Export-Package: com.adobe.icc;com.adobe.icc.bootstrap;version=${version}
//IMPORTANT: If the following higlighted line is not defined in the adobe-cm-spring-config.xml, you need to include it
Import-Package: com.adobe.idp,com.adobe.idp.dsc,com.adobe.livecycle.readerextensions.client.*
Bundle-Version: ${version}
Bundle-Description: Adobe Correspondence Management Solution Bundle
Bundle-SymbolicName: com.adobe.livecycle.cm
X-Spring-Context: META-INF/spring/cm
Spring-Context: META-INF/spring/osgi-context.xml
Note: Ensure
that the text highlighted above is found in the BND configuration file.
Else, you need to include this text in the file.
Perform the following steps to make necessary changes to
the build.xml file of the Services project
present at CorrespondenceManagementSolutionTemplate\Services\build.xml:
The
build.xml file will reflect the above changes: <?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* ADOBE SYSTEMS INCORPORATED
* Copyright 2010 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the
* terms of the Adobe license agreement accompanying it. If you have received this file from a
* source other than Adobe, then your use, modification, or distribution of it requires the prior
* written permission of Adobe.
*/
-->
<project name="solution-template-build" default="build-bundle" basedir=".">
<property file="../build/build.properties"/>
<property file="build.properties"/>
<target name="compile" description="Compile and copy the source" depends="clean">
<echo>Compile classes ...</echo>
<path id="build.class.path">
<fileset dir="../">
<include name="*.jar"/>
</fileset>
<fileset dir="../DS_SDK">
<include name="*.jar"/>
</fileset>
<fileset dir="${tp.lib.dir}">
<include name="*.jar"/>
</fileset>
<fileset dir="${[SDK]}/riaservices/assetcomposer/10.0.0.0/java">
<include name="*.jar"/>
</fileset>
<fileset dir="${[SDK]}/riaservices/datadictionary/10.0.0.0/java">
<include name="*.jar"/>
</fileset>
<fileset dir="${[SDK]}/riaservices/riacore/10.0.0.0/java">
<include name="*.jar"/>
</fileset>
</path>
<mkdir dir="dist/classes"/>
<javac destdir="dist/classes" srcdir="./src" classpathref="build.class.path" debug="true" verbose="false"/>
<jar destfile="dist/cmsa.jar">
<fileset dir="dist/classes">
<include name="**/*"/>
</fileset>
<fileset dir="./resources">
<include name="**/*"/>
</fileset>
</jar>
</target>
<target name="clean">
<echo>Cleanup..</echo>
<delete dir="dist"/>
</target>
<target name="build-bundle" depends="compile">
<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${tp.lib.dir}/biz.aQute.bnd.jar"/>
<bndwrap definitions="bnd" output="dist" jars="dist/cmsa.jar">
</bndwrap>
<zip destfile="dist/cmsa_withRE.bar">
<zipgroupfileset dir="../"
includes="Services/dist/cmsa.bar,DS_SDK/adobe-reader-extensions-client.jar"/>
</zip>
<move file="dist/cmsa_withRE.bar" overwrite="true" tofile="dist/cmsa.jar"/>
</target>
</project>
Build and deploy the solution template to complete your custom
implementation of Reader Extensions API for Correspondence Management.
See Building and deploying the Solution Template for more information.
|
|
|