I have recently been trying to do some printing from a Java application. The Java printing API appears to be extremely powerful but it has, in my opinion, two significant problems. First, it doesn't seem to have a default set of bits to plug together and produce printout. Instead you get some useful components and a set of interfaces. The second problem is that you effectively paint every component yourself, something that I really didn't fancy doing for the rather complex layouts that I had to work with.

I began to think about how easy the output would be in something like HTML which led to me deciding to unearth my memories of XSL-FO. By digging around it seemed like it was possible to use Fop (a Java XSL-FO toolkit) to render data straight to the printer utilising some of the support classes from the Java print API. Sadly I struggled to find any documentation of how to do it so I pieced together the scraps I could find and the result is shown below.

The code below borrows heavily from the example on the FOP site but I have made the changes that were needed to use a print selection dialog and to allow the xml source to be passed as a parameter.


package uk.co.artran.print;

import java.awt.print.PrinterJob;

import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.*;
import org.apache.fop.render.print.PrintRenderer;
import org.w3c.dom.Document;

public class FopPrint {
    private FopFactory fopFactory;

    public FopPrint() {
        // Step 1: Construct a FopFactory
        fopFactory = FopFactory.newInstance();
    }
    
    public void printXML(Document xml){
        // Step 2: Set up the PrinterJob using its dialog
        PrinterJob printerJob = PrinterJob.getPrinterJob();
        
        try {
            if (printerJob.printDialog()) {
                // Create a PrintRenderer from our PrinterJob and use it to override the default renderer
                PrintRenderer printRenderer = new PrintRenderer(printerJob);
                FOUserAgent userAgent = fopFactory.newFOUserAgent();
                userAgent.setRendererOverride(printRenderer);
                
                // Step 3: Construct fop with desired output format
                Fop fop = fopFactory.newFop(MimeConstants.MIME_POSTSCRIPT, userAgent);
    
                // Step 4: Setup JAXP using transformer
                TransformerFactory factory = TransformerFactory.newInstance();
                Source xslt = new StreamSource(this.getClass().getResourceAsStream("test.xsl"));
                Transformer transformer = factory.newTransformer(xslt);
    
                // Step 5: Setup input and output for XSLT transformation
                // Setup input document
                Source src = new DOMSource(xml);
    
                // Resulting SAX events (the generated FO) must be piped through to FOP
                Result res = new SAXResult(fop.getDefaultHandler());
    
                // Step 6: Start XSLT transformation and FOP processing
                transformer.transform(src, res);
            }
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }
}


My references for the article were the Java API documentation, the FOP API documentation and the FOP embedding documentation.

contact us

Note: This information will only be used to reply to your feedback. We respect your privacy and will never abuse your email address or other personal information.

bottom corner