1 Reply Latest reply on Jul 2, 2008 2:00 AM by Karl_Sigiscar_1971

    Generating PDF from Flex BarChart

    kxkannan
      Hello,

      I am new to Flex. Have been playing with creating Advanced Data Grid and Bar Charts for our application prototype and would like to explore how to create a PDF file of the BarChart or other charting components.

      The requirement is simple. We show the BarChart and a button to view it as a PDF. When the user presses the button, the PDF viewing dialog should come up and the user can opt to save the PDF or view it (the standard way a browser deals with the PDF).

      Have read blogs, this forum and LiveCycle docs but don't understand clearly how Flex communicates with
      LiveCycle ES (or PDF Generator) to display the PDF. Any ideas or tutorials that does this would be appreciated.

      Thanks,
      Kannan

        • 1. Generating PDF from Flex BarChart
          Karl_Sigiscar_1971 Level 3
          In order to generate a PDF document, you have to call a method on a Java remote object that uses the XFAHelper and pass it some arguments.

          I modified the PDFService example in the documentation so I can:

          1- specify any document as opposed to hardcoding the PDF template name
          2- write the PDF to a file as opposed to writing it in the user's session

          Here is the source:


          package com.mycompany.flex.remoteObjects;

          import java.io.File;
          import java.io.IOException;

          import org.w3c.dom.Document;

          import flex.acrobat.pdf.XFAHelper;
          import flex.messaging.FlexContext;
          import flex.messaging.util.UUIDUtils;

          public class PDFService
          {
          public PDFService()
          {
          }

          public Object generatePDF(Document dataset, String PDFdocument) throws IOException
          {
          // Open shell PDF
          String source = FlexContext.getServletContext().getRealPath("/pdfgen/" + PDFdocument);
          int index = source.indexOf("./");

          if(index != -1 )
          {
          // Remove the ./ added by UNIX
          source = source.substring(0, index) + source.substring(index + 2, source.length());
          }

          XFAHelper helper = new XFAHelper();
          helper.open(source);

          // Import XFA dataset
          helper.importDataset(dataset);

          // Create a unique ID
          String uuid = UUIDUtils.createUUID(false);

          source = FlexContext.getServletContext().getRealPath("/dynamic-pdf/" + uuid + "_" + PDFdocument);
          index = source.indexOf("./");

          if(index != -1 )
          {
          // Remove the ./ added by UNIX
          source = source.substring(0, index) + source.substring(index + 2, source.length());
          }

          // Create the file object
          File file = new File(source);

          // Save the file
          helper.save(file);

          // Close any resources
          helper.close();

          return (uuid + "_" + PDFdocument);
          }
          }

          pdfgen is the folder where my PDF template resides.
          dynamic-pdf is the folder where the generated PDF are saved.
          These two folders are located under flex.war at the first level.

          -------------------------------------------------------------------------------------

          In Flex, I wrote a Cairngorm command that calls this remote object and displays the generated PDF:

          package com.mycompany.core.commands
          {
          import com.adobe.cairngorm.commands.ICommand;
          import com.adobe.cairngorm.control.CairngormEvent;
          import com.adobe.cairngorm.business.Responder;

          import com.mycompany.core.business.GenerateAndOpenPDFDelegate;
          import com.mycompany.core.control.event.GenerateAndOpenPDFEvent;
          import com.mycompany.core.model.ModelLocator;

          import flash.net.navigateToURL;
          import flash.net.URLRequest;

          import mx.rpc.events.ResultEvent;
          import mx.rpc.events.FaultEvent;
          import mx.collections.*;
          import mx.core.Application;
          import mx.controls.Alert;


          public class GenerateAndOpenPDFCommand implements ICommand, Responder
          {
          [Bindable]
          private var model:ModelLocator = ModelLocator.getInstance();

          public function GenerateAndOpenPDFCommand():void
          {
          }

          public function execute(event:CairngormEvent):void
          {
          trace("Executing GenerateAndOpenPDFCommand...");

          var delegate : GenerateAndOpenPDFDelegate = new GenerateAndOpenPDFDelegate( this );
          var generateAndOpenPDFEvent : GenerateAndOpenPDFEvent = event as GenerateAndOpenPDFEvent;
          delegate.generateAndOpenPDF( generateAndOpenPDFEvent.pdfVO );
          }

          public function onResult( event : * = null ) : void
          {
          var item:Object;
          var result:String = (event as ResultEvent).result as String;
          trace("GenerateAndOpenPDFCommand::onResult\n\n" + result);

          if (result)
          {
          // Open the generated PDF in a new window
          navigateToURL(new URLRequest(ModelLocator.FLEX_URL + "dynamic-pdf/" + result), "_blank");
          }

          // Hide the progress bar overlay

          Application.application.requestProgressBar.visible = false;
          Application.application.requestProgressBar.progressBar.source = null;
          Application.application.requestProgressBar.progressBar.label = this.model.languageDictionary["000012"];
          }

          public function onFault( event : * = null ) : void
          {
          // Hide the progress bar overlay

          Application.application.requestProgressBar.visible = false;
          Application.application.requestProgressBar.progressBar.source = null;

          // Debug
          Alert.show("GenerateAndOpenPDFCommand:\n\n" + (event as FaultEvent).message);
          }
          }
          }

          FLEX_URL is created in this way some place else in the application:

          // Get the server URL from the Application's

          var server:String = Application.application.url;
          var index:uint = server.indexOf("Shell"); // Shell is the name of my app folder
          server = server.substring(0, index);

          // This is the flex.war/ URL
          ModelLocator.FLEX_URL = server;


          -------------------------------------------------------------------------------------

          Of course, it would be better to save the PDF in the user's session as Adobe suggests, but I couldn't figure out how they use the PDFResourceServlet. First of all, I had to get its code.

          I had to decompile the java class files in the samples to get the source of the PDFResourceServlet as it is not in the documentation. Here it is:

          package com.mycompany.flex.remoteObjects;

          import java.io.IOException;

          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import javax.servlet.http.HttpSession;

          public class PDFResourceServlet extends HttpServlet
          {

          public PDFResourceServlet()
          {
          }

          protected void doGet(HttpServletRequest req, HttpServletResponse res)
          throws ServletException, IOException
          {
          doPost(req, res);
          }

          protected void doPost(HttpServletRequest req, HttpServletResponse res)
          throws ServletException, IOException
          {
          String id = req.getParameter("id");
          if(id != null)
          {
          HttpSession session = req.getSession(true);
          try
          {
          byte bytes[] = (byte[])(byte[])session.getAttribute(id);
          if(bytes != null)
          {
          res.setContentType("application/pdf");
          res.setContentLength(bytes.length);
          res.getOutputStream().write(bytes);
          } else
          {
          res.setStatus(404);
          }
          }
          catch(Throwable t)
          {
          System.err.println(t.getMessage());
          }
          }
          }

          private static final long serialVersionUID = 0x7180e4383e53d335L;
          }