Article summary

 

Summary
Discusses how to create an Experience Manager OSGi bundle that invokes LiveCycle ES service operations. In this example, the PDFG service is invoked.
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ), LiveCycle ES (LiveCyle ES is part of Adobe Enterprise technology; however, it is not part of Digital Marketing Suite)
Audience
Developer (intermediate)
Required Skills
Java, web services, XML, LiveCycle ES
Tested On Experience Manager 5.5, 5.6

Introduction

As a user of Adobe enterprise technologies, you can create an enterprise solution that uses functionality provided by Experience Manager and LiveCycle ES. By combining the functionality of both products, you can create applications to solve your business requirements. For example, assume that you want to place user submitted data into a PDF/A document for long-term storage. In this situation, you can call LiveCycle ES from an OSGi bundle and pass the submitted data. LiveCycle ES can place the data into a PDF/A document. 

LiveCycle

To invoke LiveCycle ES from an OSGi bundle, you use LiveCycle ES web services. That is, create Java proxy classes that are based on a LiveCycle ES WSDL and wrap those Java classes within an OSGi bundle. As a result, the OSGi bundle can invoke LiveCycle ES. 

To create a PDF/A document, invoke the LiveCycle ES Output service. The Output service merges a form design created in LiveCycle Designer and XML data to create a PDF/A document. In this workflow, the data submitted from a CQ web page is converted into XML that is merged with a form design.

The Output service’s WSDL is as follows:

http://[IP of LiveCycle Server]:8080/soap/services/OutputService?wsdl

Note:

For more information about invoking LiveCycle ES using web services, see Programming with LiveCycle ES3.

Before following along with this development article, make sure that you install Experience Manager 5.5 and LiveCycle ES (version ES, ES2, or ES3). Also, make sure that you have CRXDE, which is the development environment. In addition, ensure that you have Eclipse 3.6.1or higher. Eclipse is used to create the OSGi bundle that contains the Java proxy classes.

To create an Experience Manager web application that contains an OSGi bundle that invokes LiveCycle ES (the Output service), perform the following tasks:

  1. Create an Experience Manager application folder structure.
  2. Create a template on which the page component is based.
  3. Create a render component that uses the template. This component lets a user submit data that is placed into a PDF/A document.
  4. Create Java proxy classes that consume the soap stack of the LiveCycle Output service.
  5. Create a Java server-side class that uses the Java proxy classes to invoke the Output service.
  6. Create and deploy an OSGi bundle that contains the Java proxy classes and the Java server-side class that invokes the Output service.
  7. Setup CSS and JQuery files.
  8. Modify the JSP to call a Java method defined in the OSGi bundle. 
  9. Create a new web page that invokes LiveCycle ES.

Note:

This development article discusses how to integrate with LiveCycle ES using web services. Ensure that you configure Experience Manager to use web services. For more information about integrating web services and CQ, see http://scottsdigitalcommunity.blogspot.ca/2012/05/creating-adobe-cq-bundles-that-consume.html.

Create a CQ application folder structure

Your first step is to create an application folder structure that contains templates, components, and pages by using CRXDE Lite. 

CQAppSetup

The following list describes each application folder:

application name folder: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on.

components folder: contains components that your application uses.

page folder: contains page components. A page component is a script such as a JSP file.

global: contains global components that your application uses.

template folder: contains templates that you can base page components on.

src folder: contains source code that comprises an OSGi component (this development article does not use an OSGi component).

install folder: contains a compiled OSGi bundles container.


Create an application folder structure in CRXDE Lite:

  1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.
  2.  Select CRXDE Lite.
  3.  Right-click the apps folder (or the parent folder), select Create, Create Folder.
  4.  Enter the folder name into the Create Folder dialog box. Enter applicationLC.
  5.  Repeat steps 1-4 for each folder specified in the previous illustration.
  6.  Click the Save All button.

Note:

You have to click the Save All button when working in CRXDE Lite for the changes to be made.

Create a template

Create a CQ template by using CRXDE Lite that defines a consistent style for the pages in your CQ application. A template comprises of nodes that specify the page structure. For more information about templates, see http://docs.adobe.com/docs/en/cq/current/developing/templates.html.

Create a template by using CRXDE Lite:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click the template folder (within your application), select Create, Create Template.

4. Enter the following information into the Create Template dialog box:

  • Label: The name of the template to create. Enter lctemplate.
  • Title: The title that is assigned to the template.
  • Description: The description that is assigned to the template.
  • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter applicationlc/components/page/ lctemplate.
  • Ranking: The order (ascending) in which this template appears in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.

5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.

6. Click Next for Allowed Parents.

7. Select OK on Allowed Children.

Create a render component

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as a CQ developer to create scripts that perform specific functionality. For more information about components, see http://docs.adobe.com/docs/en/cq/current/developing/components.html.

Create a render component:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/applicationmap/components/page, then select Create, Create Component.

4. Enter the following information into the Create Component dialog box:

  • Label: The name of the component. Enter lctemplate.
  • Title: The title that is assigned to the component
  • Description: The description that is assigned to the template

5. Select Next for Advanced Component Settings and Allowed Parents.

6. Select OK on Allowed Children.

7. Open the lctemplate.jps located at: /apps/applicationlc/components/page/lctemplate/lctemplate.jsp.

8. Enter the following JSP code:

<html>
<head>
<title>Hello World !!!</title>
</head>
<body>
<h1>Hello Web Services</h1>
<h2>This page will contain data sent to LiveCycle</h2>
</body>
</html>

Create Java proxy classes that consume the soap stack of the Output service

You can use JAX-WS to convert the Oupput service WSDL to Java proxy classes. These Java classes enable you to invoke LiveCycle ES operations (operations exposed by the Output service). The Output service's operations are exposed by the following WSDL:

http://[IP of LiveCycle Server]:8080/soap/services/OutputService?wsdl


Apache Ant lets you create a build script that generates Java proxy classes by referencing the WSDL. You can generate JAX-WS Java proxy files by performing the following steps:

1. Install Apache Ant on the client computer. (See http://ant.apache.org/bindownload.cgi.)

  • Add the bin directory to your class path.
  • Set the ANT_HOME environment variable to the directory where you installed Ant.

2. Install JDK 1.6 or later.

  • Add the JDK bin directory to your class path.
  • Add the JRE bin directory to your class path. This bin is located in the [JDK_INSTALL_LOCATION]/jre directory.
  • Set the JAVA_HOME environment variable to the directory where you installed the JDK. The JDK 1.6 includes the wsimport program used in the build.xml file. JDK 1.5 does not include that program.

3. Install JAX-WS on the client computer. See http://docs.oracle.com/javaee/6/tutorial/doc/bnayl.html.

4. Use JAX-WS and Apache Ant to generate Java proxy classes. Create an Ant build script to accomplish this task. The sample Ant build script named build.xml is shown at the conclusion of this list.

5. Create a BAT file to execute the Ant build script. The following command can be located within a BAT file that is responsible for executing the Ant build script:

ant -buildfile "build.xml" wsdl

6. Place the ANT build script in the C:\Program Files\Java\jaxws-ri\bin directory (or the correct Java path). The script writes the JAVA files to the ./classes folder. The script generates JAVA files that can invoke the operations exposed by the WSDL.

7. Package the JAVA files into a JAR file by using Eclipse. Perform the following tasks:

  • Create a new Java project that is used to package the proxy JAVA files into a JAR file.
  • Create two packages in the Java project: com.adobe.idp.services and org.apache.xml.xml_soap.
  • Select a package and then import the JAVA files that Ant created. Perform this task for both packages.
  • Add all of the JAR files located in the following LiveCycle install path: [LiveCycle Install Folder]\sdk\client-libs\thirdparty. These JAR files are required to use the SOAP Java classes.
  • Set the Java compiler's compliance level to 5.0 or greater.
  • Build the project.

8. Export the project as a JAR file named LiveCycleProxy.jar.

The following XML code represents the build script.

<?xml version="1.0" encoding="UTF-8"?>

<project basedir="." default="compile">


<target name="clean" >
<delete dir="classes" />
</target>

<target name="wsdl" depends="clean">
<mkdir dir="classes"/>
<exec executable="wsimport" failifexecutionfails="false" failonerror="true" resultproperty="foundWSIMPORT">
<arg line="-keep -d classes http://[IP of LiveCycle Server]:8080/soap/services/OutputService?wsdl"/>
</exec>
<fail unless="foundWSIMPORT">
!!! Failed to execute JDK's wsimport tool. Make sure that JDK 1.6 (or later) is on your PATH !!!
</fail>
</target>

<target name="compile" depends="clean, wsdl" >
<javac destdir="./classes" fork="true" debug="true">
<src path="./src"/>
</javac>
</target>

<target name="run">
<java classname="Client" fork="yes" failonerror="true" maxmemory="200M">
<classpath>
<pathelement location="./classes"/>
</classpath>
</java>
</target>
</project>

Create Java Application logic that creates a PDF/A document

Create Java application logic that uses the Java proxy classes and calls the Output service to produce a PDF/A document. Create another Eclipse Java project and add the LiveCycleProxy.jar file to your project's class path. In addition add all of the JAR files located in the following LiveCycle install path:

[LiveCycle Install Folder]\sdk\client-libs\thirdparty

These JAR files are required to use the SOAP Java classes.

The following Java application logic represents the client code that calls the Output service, creates XML data to merge with the form design, and produces a PDF/A document.

package com.cq.test.pdfa;
/**
 * Ensure that you create Java proxy files that consume
 * the Output services  WSDL. You can use JAX-WS to create
 * the proxy Java files.  
 * 
 * 
 */
 
import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Holder;

import org.w3c.dom.Element;

import com.adobe.idp.services.*;

public class CreatePDFA {

	//Invokes LiveCylce Output service and message data into a PDF/A form
    public void CreatePDFDocument(String mortgage, 
    		String last,
    		String first,
    		String ssn,
    		String positiontitle,
    		String address,
    		String city,
    		String state,
    		String zip,
    		String email,
    		String phone,
    		String fax,
    		String message) {
        
    try{
        // Setting configurations to retrieve the Web service
        String url = "http://localhost:8080/soap/services/OutputService?blob=base64";
        String username = "administrator";
        String password = "password";
    
        //Create a XML schema and get these values into the XML - merges with the form design
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        //Create a new Document object
        org.w3c.dom.Document doc = builder.newDocument(); 

        //Create the root element and append it to the XML DOM
        Element root = (Element)doc.createElement("form1");
        root.setAttribute("xmlns","http://ns.adobe.com/DDX/1.0/");
        doc.appendChild(root);
            
        //Create the PDFsFromBookmarks element
        Element mortgageAmount = (Element)doc.createElement("mortgageAmount");
        mortgageAmount.appendChild(doc.createTextNode(mortgage));
        root.appendChild(mortgageAmount);
        
        //Create lastName
        Element lastName = (Element)doc.createElement("lastName");
        lastName.appendChild(doc.createTextNode(last));
        root.appendChild(lastName);
        
        //Create firstName
        Element firstName = (Element)doc.createElement("firstName");
        firstName.appendChild(doc.createTextNode(first));
        root.appendChild(firstName);
        
        //Create ssn
        Element SSN = (Element)doc.createElement("SSN");
        SSN.appendChild(doc.createTextNode(ssn));
        root.appendChild(SSN);
        
        //Create PositionTitle
        Element PositionTitle = (Element)doc.createElement("PositionTitle");
        PositionTitle.appendChild(doc.createTextNode(positiontitle));
        root.appendChild(PositionTitle);
        
        //Create PositionTitle
        Element Address = (Element)doc.createElement("Address");
        Address.appendChild(doc.createTextNode(address));
        root.appendChild(Address);
        
        //Create City
        Element City = (Element)doc.createElement("City");
        City.appendChild(doc.createTextNode(city));
        root.appendChild(City);
               
        //Create State
        Element StateProv = (Element)doc.createElement("StateProv");
        StateProv.appendChild(doc.createTextNode(state));
        root.appendChild(StateProv);
        
        //Create zip
        Element ZipCode = (Element)doc.createElement("ZipCode");
        ZipCode.appendChild(doc.createTextNode(zip));
        root.appendChild(ZipCode);
        
        //Create email
        Element Email = (Element)doc.createElement("Email");
        Email.appendChild(doc.createTextNode(email));
        root.appendChild(Email);
        
        
        //Create phone
        Element PhoneNum = (Element)doc.createElement("PhoneNum");
        PhoneNum.appendChild(doc.createTextNode(phone));
        root.appendChild(PhoneNum);
        
        //Create FaxNum
        Element FaxNum = (Element)doc.createElement("FaxNum");
        FaxNum.appendChild(doc.createTextNode(fax));
        root.appendChild(FaxNum);
        
        //Create FaxNum
        Element Description = (Element)doc.createElement("Description");
        Description.appendChild(doc.createTextNode(message));
        root.appendChild(Description);
        
        //Convert the W3C Document to a byte array
        byte[] myFormData = convertToDDX(doc);
              
        //Place byte array into a BLOB
        BLOB inXMLData = new BLOB();
        inXMLData.setBinaryData(myFormData);
        
        // Create the service Client objects needed
        OutputServiceService outService = new OutputServiceService();
        OutputService outClient = outService.getOutputService();
    
        // Set authentication values
        ((BindingProvider) outClient).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
        ((BindingProvider) outClient).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
        ((BindingProvider) outClient).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
              
        //Set PDF run-time options    
        PDFOutputOptionsSpec outputOptions = new PDFOutputOptionsSpec();
        outputOptions.setFileURI("C:\\Users\\scottm\\DataServicesOct\\tomcat\\webapps\\PDFA\\LoanArchive.pdf");
        outputOptions.setLookAhead(300);
        outputOptions.setRecordLevel(1);
            
        //Set rendering run-time options
        RenderOptionsSpec pdfOptions = new RenderOptionsSpec(); 
        pdfOptions.setLinearizedPDF(true);
                        
        //Create Holders for the call to outClient
        Holder<BLOB> generatePrintedOutputPrintedDoc = new Holder<BLOB>();
        Holder<BLOB> generatePrintedOutputMetaDataDoc = new Holder<BLOB>();
        Holder<BLOB> generatePrintedOutputResultDoc = new Holder<BLOB>();
        Holder<OutputResult> generatePrintedOutputResult = new Holder<OutputResult>();
        
        //Create a PDFA document            
        outClient.generatePDFOutput(
            TransformationFormat.PDFA,
            "Loan.xdp",
            "C:\\Adobe",
            outputOptions,
            pdfOptions,
            inXMLData,
            generatePrintedOutputPrintedDoc,
            generatePrintedOutputMetaDataDoc,
            generatePrintedOutputResultDoc,
            generatePrintedOutputResult);
        
        //Populate a byte array with BLOB data
        BLOB outDoc = generatePrintedOutputResultDoc.value ; 
        //Save the encrypted file as a PDF file
        byte[] encryptedDocument = outDoc.getBinaryData();
        
        //Create a File object
        File outFile = new File("C:\\Adobe\\myOutputlog.xml");
        
        //Create a FileOutputStream object.
        FileOutputStream myFileW = new FileOutputStream(outFile);
        
        //Call the FileOutputStream object's write method and pass the pdf data
        myFileW.write(encryptedDocument);
        
        //Close the FileOutputStream object
        myFileW.close();
          
    }catch (Exception ee)
        {
            ee.printStackTrace();
        }
    }
    
    
    public static byte[] convertToDDX(org.w3c.dom.Document w3cDOM) throws Exception {
		byte[] mybytes = null;

		try {
			// Create a Java Transformer object
			TransformerFactory transFact = TransformerFactory.newInstance();
			Transformer transForm = transFact.newTransformer();

			// Create a Java ByteArrayOutputStream object
			ByteArrayOutputStream myOutStream = new ByteArrayOutputStream();

			// Create a Java Source object
			javax.xml.transform.dom.DOMSource myInput = new DOMSource(w3cDOM);

			// Create a Java Result object
			javax.xml.transform.stream.StreamResult myOutput = new StreamResult(myOutStream);

			// Populate the Java ByteArrayOutputStream object
			transForm.transform(myInput, myOutput);

			// Get the size of the ByteArrayOutputStream buffer
			int myByteSize = myOutStream.size();

			// Allocate myByteSize to the byte array
			mybytes = new byte[myByteSize];

			// Copy the content to the byte array
			mybytes = myOutStream.toByteArray();
			
		} catch (Exception e) {
			System.out.println("ERROR converting a w3c DOM to a DDX: " + e.getMessage());
			throw e;
		}

		// Create a com.adobe.idp.Document object and copy the
		// contents of the byte array
		return mybytes;

	}
}

Note:

CreatePDFDocument is the method that is called from the client web page that is developed later in this article. All of the string parameters are entered into the web page and passed to the OSGi bundle that wraps this Java class. Notice that these string values are used to create an XML document that is passed to the Output service. Also, change the setFileURI parameter so that the Output service writes the PDF/A to a web application. This location is referenced by the client application. Finally ensure that you retrieved the Loan.xdp file (instructions on how to get this file are located at the start of this article) and place it in C:\Adobe. If you place this XDP file in another directory, then change the parameter of the generatePDFOutput method. 

Perform the following tasks:

1. Create an Eclipse project.

2. Add the LiveCycle third-party JAR files to the project's class path.

3. Add the LiveCycleProxy.jar file (created in the previous step) to your project's class path.

4. Create a Java package named com.cq.test.pdfa.

5. Create a Java class named CreatePDFA and add the Java code specified earlier in this section.

6. Build your project.

7. Export the project as a JAR file named LiveCycleClient.jar.

Note:

Both the LiveCycleProxy.jar and LiveCycleClient.jar files are added to the OSGi bundle that is uploaded to the Experience Manager service container. 

Create the OSGi bundle that contains the Java proxy classes

Create an OSGi bundle that contains the LiveCycleProxy.jar and LiveCycleClient.jar files. After you upload the OSGi bundle to Experience Manager, you can call the CreatePDFDocument method that invokes LiveCycle ES. 

To create the OSGi bundle, you can use another Eclipse project. An OSGi bundle is essentially a collection of Java files and a MANIFEST.MF file. To create an OSGi bundle that contains Java proxy classes using Eclipse, perform the following tasks:

1. Start Eclipse (Indigo). The steps below have been tested on Eclipse Java EE IDE for Web Developers version Indigo Service Release 1.

2. Select File, New, Other.

3. Under the “Plug-in Development” folder, choose “Plug-in from Existing JAR Archives”.

4. In the “JAR selection” dialog, click the ‘Add external’ button, and browse to the LiveCycleProxy.jar and LiveCycleClient.jar files that you created.

5. Click Next.

6. In the “Plug-in Project properties” dialog, ensure that you check the checkbox for “Analyze library contents and add dependencies”.

7. Make sure that the “Target Platform” is the “standard” OSGi framework.

8. Ensure the checkboxes for “Unzip the JAR archives into the project” and “Update references to the JAR files” are both checked.

9. Click Next, and then Finish.

10. Click on the Runtime tab.

11. Make sure that the Exported Packages list is populated.

12. Make sure these have been added under the Export-Package header in MANIFEST.MF. Remove the version information in the MANIFEST.MF file. Version numbers can cause conflicts when you upload the OSGi bundle.

13. Also make sure that the Import-Package header in MANIFEST.MF is also populated. The following represents the MANIFEST.MF file.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LiveCycleOSGISoapBoth
Bundle-SymbolicName: LiveCycleOSGISoapBoth
Bundle-Version: 1.0.0
Bundle-ClassPath: .
Export-Package: com.adobe.idp.services,
 com.cq.test.pdfa,
 org.apache.xml.xml_soap
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: javax.xml.namespace,
 javax.xml.ws,
 javax.xml.transform,
 javax.xml.parsers,
 javax.xml.transform.stream,
 org.w3c.dom,
 javax.xml.transform.dom,
 javax.xml.bind

14. Save the project.

15. Build the OSGi bundle by right clicking the project in the left pane, choose Export->Plug-in Development->Deployable plug-ins and fragments and click Next.

16. Select a location for the export (C:\TEMP) and click Finish. (Ignore any error messages).

17. In C:\TEMP\plugins, you should now find the OSGi bundle.

18. Login to Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).

19. Sort the bundle list by “Id” and note the Id of the last bundle.

20. Click the “Install/Update” button.

21. Check the “Start Bundle” checkbox.

22. Browse to the bundle JAR file you just built. (C:\TEMP\plugins).

23. Click “Install or Update”.

24. Click the ‘Refresh Packages’ button.

25. Check the bundle with the highest Id.

26. Your new bundle should now be listed with the status ‘Active’.

27. If the status is not “Active”, check the CQ error.log for exceptions. If you get “org.osgi.framework.BundleException: Unresolved constraint” errors, check the MANIFEST.MF for strict version requirements which might look as follows: javax.xml.namespace; version=”3.1.0”.

28. If the version requirement causes problems, remove it so that the entry looks like this: javax.xml.namespace.

29. If the entry is not required, remove it entirely.

30. Rebuild the bundle.

31. Delete the previous bundle and deploy the new one.

32. If all goes well, the CQ error.log should have log entries such as follows:

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent INSTALLED

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent RESOLVED

*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent STARTED

*INFO* [FelixDispatchQueue] org.apache.felix.framework FrameworkEvent PACKAGES REFRESHED

Note:

Now the Java proxy classes that know how to invoke operations exposed by the WSDL are part of the OSGI service container. You can call their methods from a JSP.

Add CSS and JQuery files to a cq:ClientLibraryFolder node

You add two CSS files and JQuery framework files to a cq:ClientLibraryFolder node to define the style of the client JSP. The two JQuery framework files that are required are: jquery-1.6.3.min.js and jquery.loadmask.min.js.

Note:

For more information about using JQuery within Experience Manager and how to get JQuery library files, see http://scottsdigitalcommunity.blogspot.ca/2012/02/integrating-jquery-framework-into-day.html.

To add CSS files and the JQuery framework to your component, add a cq:ClientLibraryFolder node to your component. After you create this node, set properties that allow the script to find the CSS files and the JQuery library files.

To add CSS files and the JQuery framework, add a new node named clientlibs to your component (as discussed below). You have to add two properties to this node, as shown in the following table.

Name
Type Value
dependencies
String[]
cq.jquery
categories
String[]
jquerysamples

The dependencies property informs CQ to make sure that the CSS files and JQuery library files are included in the page. The categories property is very important and informs CQ which clientlibs must be included with the JSP that is generated.

CSS Files

The CSS files define the display style for the JSP file that lets the user enter data that is placed into a PDF/A document. The following code represents the site.css file that is used in this development article. The following code represents the site.css file.

/* reset */
html, body, div, span, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
 margin: 0;
 padding: 0;
 border: 0;
 font-size: 100%;
 font: inherit;
 vertical-align: baseline;
}
html , body{
 line-height: 1;
 background-color: #334873;
 background-image: url(../_images/bg-page2.png);
}

ol, ul {
 list-style: none;
}


table {
 border-collapse: collapse;
 border-spacing: 0;
}
/* end reset*/



h1, h2, h3 {
 font-family: 'ColaborateRegular', Arial, sans-serif; 
}


strong {
 font-family: 'ColaborateMediumRegular', Arial, sans-serif; 
}

em {
 font-family: 'ColaborateThinRegular', Arial, sans-serif; 
}

.content {
 max-width: 760px;
 margin: 20px 0 0 100px;
}

.clear:after { 
content: "."; display: block; height: 0; clear: both; visibility: hidden; 
}

.clear {
 min-height: 1px;
}

* html .clear {
 height: 1px;
}

.header {
 position: relative;
 border-top: solid 6px white;
 padding: 10px 0 10px 0;
 margin-bottom: 20px;
}


.main {
 xxposition: relative;
 padding-bottom: 1em;
 border-bottom: solid 1px rgba(255,255,255,.5);
 xxoverflow:hidden;
 xxmin-height: 300px;
}

.main h1 {
 font-size: 32px;
 color: white;
 text-shadow: 1px 1px 1px rgba(0,0,0,.75);
 border-bottom: solid 1px rgba(255,255,255,.5);
 margin-bottom: 0.75em;
}


p , li, legend , form{
 font-size: 18px;
 color: white;
 font-family: 'ColaborateLightRegular', Arial, sans-serif;
 line-height: 125%;
 margin-bottom: 10px;
}

fieldset {
 padding: 10px;
 border: 1px solid white;
 margin: 25px 0; 
}

.nav {
 margin: 10px 0 0 100px; 
}

.nav li {
 display: inline-block; 
}

.nav a:hover, .example:hover{
 background-color: rgba(255,255,255,.85);
 color: rgb(0,0,0);
}

h3 {
 font-size: 18px;
 color: rgb(227,198,133);;
}

.results h2 {
 color: rgba(255,255,255,1);
}
.results div {
 padding-bottom: 10px;
}
.results div code {
 float: right;
 width: 60%;
}

input {
 font-size: 20px;
}
.form .wide {
 font-size: 18px;
 width: 100%;
}
.resultSection {
 float: right;
 width: 45%;
 margin-left: 20px;
}
#regexTester {
 margin-right: 55%;
}
.sideBySide li {
 float: left;
 overflow: hidden;
 width: 220px;
}
.clickable {
 cursor:pointer;
 margin-bottom: 5px;
}

.clickable:hover {
background-color:#FFC;
}


.col1 {
 float: left;
 width: 75%; 
}
.col2 {
 float: right;
 width: 20%; 
}

.col2 ul {
 margin-left: 20px;
 list-style: square;
}
.col2 li {
 font-size: 90%; 
}


#selectorList {
 overflow: hidden; 
}
#selector {
 width: 275px;
}


form#signup .label {
 width: 200px; 
}

Jquery.loadmask.css file

The other CSS file that is used in this development article is used for the JQuery mask effect. The mask effect is used when a user submits data from the web page to the OSGi bundle. The following code represents the jquery.loadmask.css file.

.loadmask {
    z-index: 100;
    position: absolute;
    top:0;
    left:0;
    -moz-opacity: 0.5;
    opacity: .50;
    filter: alpha(opacity=50);
    background-color: #CCC;
    width: 100%;
    height: 100%;
    zoom: 1;
}
.loadmask-msg {
    z-index: 20001;
    position: absolute;
    top: 0;
    left: 0;
    border:1px solid #6593cf;
    background: #c3daf9;
    padding:2px;
}
.loadmask-msg div {
    padding:5px 10px 5px 25px;
    background: #fbfbfb url('images/loading.gif') no-repeat 5px 5px;
    line-height: 16px;
    border:1px solid #a3bad9;
    color:#222;
    font:normal 11px tahoma, arial, helvetica, sans-serif;
    cursor:wait;
}
.masked {
    overflow: hidden !important;
}
.masked-relative {
    position: relative !important;
}
.masked-hidden {
    visibility: hidden !important;
}

Text files

You have to add two text files to the Clientlibs folder. These text files map to the JS files and the CSS files. The names of the text files are: css.txt and js.txt.

The content of the css.txt file are the names of the two CSS files:

  • site.css
  • jquery.loadmask.css

Likewise, the content of the js.text file are the names of the two JS files:

  • jquery-1.6.3.min.js
  • jquery.loadmask.min.js


Add required files to the ClientLibs folder

1. Right-click /apps/applicationlc/components then select New, Node.

2. Make sure the node type is cq:ClientLibraryFolder and name the node clientlibs.

3. Right click on clientlibs and select Properties. Add the two properties specified in the previous table to the node.

4. On your file system, navigate to the folder where the JQuery JS files are located. Drag and drop the jquery-1.6.3.min.js and jquery.loadmask.min.js files to the clientlibs node by using CRXDE.

5. On your file system, navigate where you placed the CSS files. Drag and drop the jquery.loadmask.css and site.css files to the clientlibs folder by using CRXDE.

6. Add a TXT file to the clientlibs folder named js.txt. The content of the js.txt file are the JQuery JS file names (the content of this file is shown earlier).

7. Add a TXT file to the clientlibs node named css.txt. The content of the css.txt file are the CSS file names (the content of this file is shown earlier).


Modify the lctemplate JSP to call a Java method defined in the OSGi bundle

To create the client web page by using JQuery, create these two files:

  • pdf.json.jsp: contains application logic that calls the OSGI bundle’s CreatePDFDocument operation. This file is the connection between a JSP front end and the back end OSGi bundle.
  • lctemplate.jsp: contains application logic that defines the JSP that lets a user enter information. Once the user is done entering information, the user can click the button and the data is sent to the OSGi bundle that invokes LiveCycle ES.

Note:

The  lctemplate.jsp file was created in an earlier step; however, in this step, you use new JavaScript code.

Create the pdf.json.jsp file

Add a new JSP file named pdf.json.jsp to the following path:

/apps/applicationlc/components/page/lctemplate

In the pdf.json.jsp, create a com.cq.test.pdfa.CreatePDFA iinstance that invokes operations of the OSGi bundle. To create a com.cq.test.pdfa.CreatePDFA instance, specify these page import statements:

page import="org.apache.sling.commons.json.io.*,com.cq.test.pdfa.*"

Data types defined in the com.cq.test.pdfa.* package allows you to invoke operations exposed by the OSGi bundle.

The following code shows the application logic in the pdf.json.jsp file that invokes the CreatePDFDocument operation located in the OSGi bundle:

<%@ page import="org.apache.sling.commons.json.io.*,com.cq.test.pdfa.*" %><%

//Get all of the values passed from the JQuery form
String mortgage = request.getParameter("mortgage");
String last = request.getParameter("last");
String first = request.getParameter("first");
String ssn = request.getParameter("ssn");
String positiontitle = request.getParameter("positiontitle");
String address = request.getParameter("address");
String city = request.getParameter("city");
String state = request.getParameter("state");
String zip = request.getParameter("zip");
String email = request.getParameter("email");
String phone = request.getParameter("phone");
String fax = request.getParameter("fax");
String message = request.getParameter("message");

//String message = "message";
com.cq.test.pdfa.CreatePDFA lcCreatePDFA = new com.cq.test.pdfa.CreatePDFA();

lcCreatePDFA.CreatePDFDocument(mortgage,last,first, ssn,positiontitle,address, city,state,zip, email, phone,fax,message); 

%>

To add the pdf.json.jsp file

1. To view the CQ welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/applicationlc/components/lctemplate, then select Create, File.

4. Enter pdf.json.jsp in the Name field and click OK.

5. Enter the JSP code shown in this section.

6. Click Save All.

Modifying the lctemplate.jsp file

Modify the lctemplate.jsp file to call the com.cq.test.pdfa.CreatePDFA object. To use the com.cq.test.pdfa.CreatePDFA instance defined in the pdf.json.jsp file, define an url variable, as shown in the following line of code:

var url = location.pathname.replace(".html", "/_jcr_content.pdf.json") + "?mortgage="+ mortgage + "&last="+ last&nbsp;&nbsp; &nbsp; + "&first="+ first + "&ssn="+ ssn + "&positiontitle="+ positiontitle + "&address="+ address + "&city="+ city + "&state="&nbsp; &nbsp; + state &nbsp;+ "&zip="+ zip + "&email="+ email + "&phone="+ phone + "&fax="+ fax + "&message="+ message;

The following code represents the entire lctemplate.jsp file.

<%@include file="/libs/foundation/global.jsp"%>
<cq:includeClientLib categories="jquerysamples" />
<html>
<head>
<meta charset="UTF-8">
<title>Adobe CQ PDFA Client</title>
<style>
#signup .indent label.error {
  margin-left: 0;
}
#signup label.error {
  font-size: 0.8em;
  color: #F00;
  font-weight: bold;
  display: block;
  margin-left: 215px;
}
#signup  input.error, #signup select.error  {
  background: #FFA9B8;
  border: 1px solid red;
}
</style>
<script>
$(document).ready(function() {
    
 $('body').hide().fadeIn(5000);
    
$('#submit').click(function() {
    var failure = function(err) {
        $(".main").unmask();
        alert("Unable to retrive data "+err);
      
    };
    
    //Get the Field values to pass to the LiveCycle Output Service that creates the PDF/A document
    var mortgage = $('#mortgage').val() ; 
    var last = $('#last').val() ; 
    var first = $('#first').val() ; 
    var ssn = $('#SSN').val() ; 
    var positiontitle = $('#PositionTitle').val() ; 
    var address = $('#Address').val() ; 
    var city = $('#City').val() ;
    var state = $('#StateProv').val() ;
    var zip = $('#ZipCode').val() ;
    var email = $('#Email').val() ;
    var phone = $('#PhoneNum').val() ;
    var fax = $('#FaxNum').val() ;
    var message = $('#message').val() ;
    
    var url = location.pathname.replace(".html", "/_jcr_content.pdf2.json") + "?mortgage="+ mortgage + "&last="+ last 
    + "&first="+ first + "&ssn="+ ssn + "&positiontitle="+ positiontitle + "&address="+ address + "&city="+ city + "&state="
    + state  + "&zip="+ zip + "&email="+ email + "&phone="+ phone + "&fax="+ fax + "&message="+ message; 
    
    $(".main").mask("Sending...");  

    $.ajax(url, {
        dataType: "text",
        success: function(rawData, status, xhr) {
            
            try {
            
                $(".main").unmask();
                $('#mortgage').val("") ; 
                $('#last').val("") ; 
                $('#first').val("") ; 
                $('#SSN').val("") ; 
                $('#PositionTitle').val("") ; 
                $('#Address').val("") ; 
                $('#City').val("") ;
                 $('#StateProv').val("") ;
                $('#ZipCode').val("") ;
                 $('#Email').val("") ;
                 $('#PhoneNum').val("") ;
                 $('#FaxNum').val("") ;
                 $('#message').val("") 
                $('#popup').show("");
               $('#popup').fadeOut(20000);
                   

                
            } catch(err) {
                failure(err);
            }
        },
        error: function(xhr, status, err) {
            failure(err);
        } 
    });
  });

}); // end ready
</script>
</head>
<body>
<div class="wrapper">
    <div class="header">
        <p class="logo">Adobe CQ PDF/A Client</p>
    </div>
    <div class="content">
    <div class="main">
    <h1>Adobe CQ & LiveCycle PDF/A Application</h1>
        <form name="signup" id="signup">
           <div>
                <label for="mortgage" class="label">Mortgage:</label>
                <input name="host" type="text" id="mortgage" value="350000" >
            </div>
            <div>
                <label for="last" class="label">Last Name:</label>
                <input name="last" type="text" id="last" value="Blue">
            </div>
            <div>
                <label for="first" class="label">First Name:</label>
                <input name="first" type="text" id="first" value="Tom">
            </div>
             <div>
                <label for="SSN" class="label">SSN:</label>
                <input name="SSN" type="text" id="SSN" value="7654321" >
            </div>
              <div>
                <label for="PositionTitle" class="label">Job:</label>
                <input name="PositionTitle" type="text" id="PositionTitle" value="Guard">
            </div>
            <div>
                <label for="Address" class="label">Address:</label>
                <input name="Address" type="text" id="Address" value="63 No Where St">
            </div>
             <div>
                <label for="City" class="label">City:</label>
                <input name="City" type="text" id="City" value="San Jose" >
            </div>
              <div>
                <label for="StateProv" class="label">State/Prov:</label>
                <input name="StateProv" type="text" id="StateProv" value="CA">
            </div>
              <div>
                <label for="ZipCode" class="label">ZIP:</label>
                <input name="ZipCode" value="95101" type="text" id="ZipCode" >
            </div>
              <div>
                <label for="Email" class="label">Email:</label>
                <input name="Email" value="tblue@noserver.com" type="text" id="Email" >
            </div>
               <div>
                <label for="PhoneNum" class="label">Phone:</label>
                <input name="PhoneNum" value="555-5555" type="text" id="PhoneNum" >
            </div>
               <div>
                <label for="FaxNum" class="label">Fax:</label>
                <input name="FaxNum" type="text" value="555-6666" id="FaxNum" >
            </div>
            
            
            <div>
                <label for="message" class="label">Message:</label>
                <textarea rows="3" cols="40" id="message" value="Want to purchase a home">
                </textarea>
                
          </div>
            
            <div>
                <input type="button" value="Click me!"  name="submit" id="submit" value="Submit">
            </div>
            <div  style="display:none" id="popup">
            <p>Click the following PDF Image to open the PDF/A document:</p>
             <a href="http://[IP of a web application]:8400/PDFA/LoanArchive.pdf">
                <img src="http://[IP of a web application]:8400/PDFA/pdf.jpg" />
            </a>
          </div>
        </form>
        </div>
    </div>
    </div>
</body>
</html>

Note:

Change [IP of a web application] to the IP address where the Output service placed the PDF/A document.

To modify the lctemplate.jsp file

1. To view the CQ welcome page, enter the URL: http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Double-click apps/applicatonlc/components/page/lctemplate/lctemplate.jsp.

4. Replace the JSP code with the new code shown in this section.

5. Click Save All.

Create a CQ web page that invokes LiveCycle ES

The final task is to create a site that contains a page that is based on the lctemplate (the template created earlier in this development article).


Client


After this data is submiitted, it is sent to the OSGi bundle that invokes the Output service. A PDF/A document is created that contains the submitted data.

pdf

Create a web page that invokes LiveCycle ES:

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.

2. Select Websites.

3. From the left hand pane, select Websites.

4. Select New, New Page.

5. Specify the title of the page in the Title field.

6. Specify the name of the page in the Name field.

7. Select lctemplate from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information when creating the template, the template will not show up in the New Page dialog box.

8. Open the new page that you created by double-clicking it in the right pane. The new page opens in a web browser. You should see a page displaying data similar to the previous illustration.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy