| By Anatole Tartakovsky | Article Rating: |
|
| January 22, 2009 11:00 AM EST | Reads: |
25,997 |
There are three ways of creating PDF documents from Adobe Flex applications: (1) by using the forms/LiveCycle designer - this process is well documented and requires someone to create XDP form (an Acrobat XML Data Package file), the data model and establish a process of synchronizing Flex application with LiveCycle, (2) by treating PDF printing as one of the features of your Flex application, seamlessly providing printing functionality (with or without LiveCycle Designer), and (3) by using Snapshots available in LCDS, which uses bitmaps to represent Flash content
While the first process provides guaranteed quality and predictable results, it also requires a double effort of developing XDP and Flex forms and introduces the model and communications that can be foreign to the application domain.
The third type of printing is good for screen-only PDFs due to low DPI used by the screen snapshots. Flex 3 should provide control over the DPI resolution.
The second process is more applicable when the document structure is dynamic (like the end-user customizable report or form). It often produces better printing quality with the current version of LiveCycle Data Services ES (formerly Flex Data Services) Flex. The idea is to send the server not the data for merging with the form, but already merged compressed document in XDP format containing both data and formatting. In this case LCDS layer just needs to process it with XDPXFAHelper class and returns it as a PDF stream to the browser for displaying.
The next code sample is the server side part written as JavaServer Page (createPDF.jsp). Note, that you need to have a commercial license of LCDS as its Express version does not support PDF generation.
<%@ page language="java"
import="java.io.IOException,
javax.servlet.http.HttpServletRequest,
flex.acrobat.pdf.XDPXFAHelper,
java.util.zip.Inflater,
java.util.zip.InflaterInputStream"
%>
<jsp:directive.page import="java.io.InputStream"/>
<jsp:directive.page import="java.io.ByteArrayInputStream"/>
<jsp:directive.page import="java.io.FileInputStream"/>
<jsp:directive.page import="java.io.FileOutputStream"/>
<%
//Load compressed XDP stream (received from client)
//into a byte array
byte[] result = new byte[5000000];
int resultLength =0 ;
try {
Inflater decompresser = new Inflater( );
byte[] ba = new byte[500000];
ServletInputStream si = request.getInputStream();
int k = 0;
int i = 0;
while (true ) {
k = si.read(ba, i, 500000);
i +=k;
if (k<=0) break;
}
try {//Uncompress data into result
decompresser.setInput(ba);
resultLength = decompresser.inflate(result);
} catch (Exception e) {
System.out.println(e.getMessage());
}
} catch (IOException e) {
throw new ServletException(e);
}
//The next line won’t work unless you have a commercial
// LCDS. It’s not available in Express edition
XDPXFAHelper helper = new XDPXFAHelper();
try { //load the input into PDF convertor
helper.openFromByteArray( result );
} catch (Exception e) {
e.printStackTrace();
}
// Save new PDF as a byte array
byte[] bytes = helper.saveToByteArray();
//Send PDF to the client(GZIP compression can be
// provided by an external filter)
ServletOutputStream out2 = response.getOutputStream();
response.setContentType("application/pdf");
response.setContentLength(bytes.length);
out2.write(bytes);
out2.flush();
out2.close();
%>
On the client (Flex) side, you need a few simple classes. First you would need an ActionScript class that sends generated XDP to the server and opens the browser page for displaying the incoming PDF:
import flash.net.*;
import flash.utils.ByteArray;
public class FormRenderer
{
public static function openPdf(xdp:String,
target:String="_blank"):void
{
var req:URLRequest = new URLRequest("/createPDF.jsp"); req.method = URLRequestMethod.POST;
var ba :ByteArray = new ByteArray();;
ba.compress();
ba.position = 0;
req.data = ba;
navigateToURL(req, target);
}
}
}
Now all we need is an XDP file with the data and presentation. While it is feasible to make an XDP file programmatically we usually recommend to start with blank templates made in LiveCycle Designer (comes with Acrobat Professional) matching the printer’s paper size/corporate stationary. XDP documents are XML objects, and EcmaScript for XML (e4x) makes the XDP building process in Flex a breeze. For example:
1. Declare a variable of type XML, and using e4x syntax read the XDP template that matches the document and the paper size. A fragment of XDP template may look like this:
<?xml version="1.0" encoding="UTF-8"?>
<?xfa generator="AdobeLiveCycleDesigner_V8.0" APIVersion="2.5.6290.0"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2007-01-25T10:40:38Z" uuid="784f469b-2fd0-4555-a905-6a2d173d0ee1">
<template xmlns="http://www.xfa.org/schema/xfa-template/2.5/">
<subform name="form1" layout="tb" restoreState="auto" locale="en_US">
<pageSet>
<pageArea name="Page1" id="Page1">
<contentArea x="0.25in" y="0.25in" w="8in" h="10.5in"/>
<medium stock="letter" short="8.5in" long="11in"/>
<?templateDesigner expand 1?></pageArea>
<?templateDesigner expand 1?></pageSet>
<subform w="8in" h="10.5in" name="YourPageAttachedHere"/>
<proto/>
<desc>
<text name="version">8.0.1291.1.339988.308172</text>
</desc>
</subform>
</template>
…
2. Select a Flex container or control that you are going to print, i.e. a Panel, a DataGrid et al.
3. Query the object from step 2, get its attributes and children and create the XML preparing this object for printing. Attach the XML to the template as a page. If you have your own presentation framework, all components can implement your own interface (the code below shows IXdpContent with the only getter function xmlContent) that allows to traverse the list of elements on the screen for their XDP content. You can also have a processor that would provide the XML for standard classes. Here is implementation of generic DataGridItemRenderer to illustrate how you can prepare for printing just one datagrid cell:
package printing
{
import com.theriabook.controls.superGridClasses.DataGridItemRenderer;
public class DataGridItemRendererXdp extends DataGridItemRenderer
implements IXdpElement
{
public function get xmlContent():Object
{
var o:XML = <draw x={convert(x)} w={convert(width)}
h={convert(height)}>
<ui>
<textEdit>
</textEdit>
</ui>
<value><text>{text}</text></value>
<font typeface={getStyle("fontFamily")}
size={(getStyle("fontSize")*4/5)+"pt"}
weight={getStyle("fontWeight")}
posture={getStyle("fontStyle")}
underline={getStyle("textDecoration")=="normal"?1:0}
>
<fill>
<color value={rgb(getStyle("color"))}/>
</fill>
</font>
<margin topInset="0.5mm" bottomInset="0.5mm" leftInset="0.5mm" rightInset="0.5mm"/>
<border>
<edge presence="hidden"/>
<edge presence="visible"/>
<edge presence="hidden"/>
<edge presence="hidden"/>
</border>
</draw>;
return o;
}
private function convert(val:Number) : String {
return val/96 + "in"; //convert 96 dpi to inches
}
private function rgb(val:Number) : String {
return (val >> 16 & 255) + "," + (val >> 8 & 255) + "," + (val & 255);
}
}
}
4. Repeat the process of attaching XML to the XDP template using E4X until all print pages are ready.
In my opinion, this method of printing from Flex requires less efforts for reporting. It might also provide better printing quality and searchability within printed document.
Published January 22, 2009 Reads 25,997
Copyright © 2009 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Anatole Tartakovsky
Anatole Tartakovsky is a Managing Principal of Farata Systems. He's responsible for creation of frameworks and reusable components. Anatole authored number of books and articles on AJAX, XML, Internet and client-server technologies. He holds an MS in mathematics. You can reach him at atartakovsky@faratasystems.com
- Cloud People: A Who's Who of Cloud Computing
- New Relic Q1 2013 Blazes Past Growth Targets and Reaches 40,000 Active Customer Accounts
- Cloud Business Solutions, Social Media, and Platform Systems of Engagement Market Shares, Strategies, and Forecasts, Worldwide, 2013 to 2019
- ExtraHop Named a Best of Interop 2013 Finalist for Two Awards: Best Cloud and Virtualization Product and Best Monitoring and Management Product
- Kevin Benedict’s What’s New in HTML5 – Week of May 19, 2013
- Interop Las Vegas Previews News Announcements from over 60 Exhibitors & Sponsors
- BrightScope Releases Top 25 Technology Companies With the Best 401k Plans
- Research and Markets: Cloud Business Solutions, Social Media, and Platform Systems of Engagement
- Mobile Commerce News Weekly – Week of May 5, 2013
- This Week in Cloud, May 9, 2013: U.K. issues cloud-first policy, Dell acquires Enstratius, OpenStack’s growing pains. And more…
- TeamDrive Partners with SmartOffice to Offer First Office Productivity Solution with End-to-End Encryption
- Les plateformes de serveurs de Supermicro® utilisent la technologie NVIDIA GRID™ pour fournir les performances graphiques accélérées aux bureaux virtuels
- Cloud People: A Who's Who of Cloud Computing
- AMD and Adobe Collaborate on Upcoming Version of Adobe Premiere Pro Software to Enable Breakthrough Video Editing Performance Through Open Standards
- New Relic Q1 2013 Blazes Past Growth Targets and Reaches 40,000 Active Customer Accounts
- Cloud Business Solutions, Social Media, and Platform Systems of Engagement Market Shares, Strategies, and Forecasts, Worldwide, 2013 to 2019
- Apple Makes Highly Eccentric Hire
- ExtraHop Named a Best of Interop 2013 Finalist for Two Awards: Best Cloud and Virtualization Product and Best Monitoring and Management Product
- Kevin Benedict’s What’s New in HTML5 – Week of May 19, 2013
- Interop Las Vegas Previews News Announcements from over 60 Exhibitors & Sponsors
- BrightScope Releases Top 25 Technology Companies With the Best 401k Plans
- Adobe Drives Innovation With New Video Workflows at NAB 2013
- Research and Markets: Cloud Business Solutions, Social Media, and Platform Systems of Engagement
- Mobile Commerce News Weekly – Week of May 5, 2013
- Where Are RIA Technologies Headed in 2008?
- Cover Story: How to Increase the Frame Rates of Your Flash Movies
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Your First Adobe Flex Application with a ColdFusion Backend
- Adobe Flex 2: Advanced DataGrid
- How To Create a Photo Slide Show ...
- i-Technology Blog: Death-Knell For "Rich Media? Hardly!
- Personal Branding Checklist
- Adobe Flex Interface Customization - Themes, Styles, Skins
- Adobe/Macromedia - Microsoft, Look Out!
- Has the Technology Bounceback Begun?
- "Real-World Flex" by Adobe's Christophe Coenraets






















