• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
PDF Generation within WebObjects
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PDF Generation within WebObjects


  • Subject: PDF Generation within WebObjects
  • From: Zac Konopa <email@hidden>
  • Date: Thu, 23 Mar 2006 12:11:02 -0800

Hey everyone,

I wrote to the list a few days ago about generating pdf files for download from a WebObjects application. Well I've figured out a solution and I thought I would post it along with some notes about the process to help those who follow and perhaps get some feedback on how to improve the process. Okay so here goes...

First you need to get a java library that will generate PDF's from xsl-fo (this is an xml file in the "fo" format, fo stands for Formatt Object or some such, it's simply xml description of a document that will be parsed into PDF). I choose the Apache FOP 0.20.5 library. There is also the Apache .90 library, and iText, but I don't know anything about either of those librarys. Just follow the instructions in from Apache on how to install these libraries. Ultimately you need to make sure that all the .jar files are in you classpath.

Once you've got everything installed you can look at the application itself. Now the approach I took was that when the user requested a certain thing (ie a pdf report) instead of vending html from a WOComponent we wanted to vend a PDF. To this end the WOComponent will contain xml that will describe the document then we will override the appendToResponse method of WOComponent to parse the content of the response from xml into PDF using the librarys from Apache's FOP, then substitute the PDF content for the xml, then change the response header to PDF. The approach I took was to factor out all this functionality into a separate class that extends WOComponent, then make all my components that hold the actual xml subclasses of this class. I called the superclass FO2PDFSerializer, and here is it's content...

//
// FO2PDFSerializer.java: Class file
//
// Created by zac on 3/20/06
//

import com.webobjects.foundation.*;
import com.webobjects.appserver.*;
import com.webobjects.eocontrol.*;
import com.webobjects.eoaccess.*;
import org.apache.fop.apps.*;
import org.xml.sax.*;
import com.webobjects.appserver.*;
import java.io.*;


public class FO2PDFSerializer extends WOComponent {

private String _contentType = "text/fo-xml";//all subclasses need to contain this type of content

    public FO2PDFSerializer(WOContext context) {
        super(context);
    }

    public void setContentType(String aType) {
        _contentType = aType;
    }

//this function will be used by the initializing component to determine wether we want to see the actual xml or get the pdf
public String contentType() {
return _contentType;
}


//this function is the meat of the class
public void appendToResponse(WOResponse response, WOContext context) {


        super.appendToResponse(response, context);

        // vend as PDF to response
        if (contentType().equals("application/pdf")) {

response.setHeader("text/xml", "Content-Type");//set the Content Type to xml
InputSource foInput = new InputSource(new ByteArrayInputStream(response.contentString().getBytes()));//get the content of the Component as bytes and convert to a ByteArray
ByteArrayOutputStream out = new ByteArrayOutputStream ();//initialize an output stream for the FOP driver
Driver driver = new Driver(foInput, out);//initialize a Driver (member of the ApacheFOP) with input and output from above
driver.setLogger(null);//this can be used when tracking down errors, but you'll have to figure out how to use it for yourself
driver.setRenderer(Driver.RENDER_PDF);//set the type of document that you want from the Driver


	    //now run the driver
            try {
                driver.run();
            } catch (Exception e) {
                NSLog.out.appendln(e.getMessage());
            }

	    //Convert the output to a class that can be used by WOResponse
            NSData outData = new NSData(out.toByteArray());

//if you've actually got data, substitute it for the response data and change the response Content Type
if(outData != null) {
response.setContent(outData);
response.setHeader("application/pdf", "Content-Type");
response.setHeader("attachement;filename=\"" + "Test.pdf" + "\"", "Content-Disposition");//you can use this line to set the filename if you want but it's not required
}
}
}


}

Okay that's the superclass. All your subclasses have to hold is the actual xml data in the .wo source. This can be confusing because the WebObjects builder won't inerperet the xml, it will only show you the static text so most of the manipulation you do will have to be in the source files. It is doable though.

And with that you're good! Any document that you want to vend as PDF simply have the class extend this one, and when you call that component from elsewhere in your app remember to set the content type as "application/pdf".

It's good to keep in mind that the Apache FOP library can parse xml into several different files and with minimal modification this class could be modified to vend any of them.

Well good luck all.  I'm outa here.

Zac
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Prev by Date: Re: Google Maps WOComponent anyone?
  • Next by Date: Re: Thanks and Comments
  • Previous by thread: Re: Google Maps WOComponent anyone?
  • Next by thread: MySQL JDBC connection
  • Index(es):
    • Date
    • Thread