XMLMill - convert xml to pdf with java. Generate PDF from xml/xsl.

XMLMill User Guide

Version: 3.00 Date: January 2nd, 2008
This tutorial is opened in a separate window in order to maximize the legibility of this tutorial.
To return to XMLMill, close this browser window

This page as PDFPrinter friendly pageThis guide (!) as PDF

Multi-threading

XMLMill is multi-threading ready, meaning that multiple threads can at the same time use an instance of the JAXPTransformer class (see previous chapter). This makes XMLMill ideally suited to be used in heavily loaded server-processing, where a lot of .pdf documents need to be generated simultaneously.

If you want to test the multi-threading capabilities of XMLMill, the TestThreads.java class in the samples/threads/ directory can be used.

Example: Test_Threads.java

This .java class will generate 30 threads each generating the phonelist.pdf document based on the phonelist.xml and phonelist.xsl in the samples/xmlxsl directory. The speed of the threads will depend largely on the machine the tests are performed on (mainly depending on the available RAM and the number of processors).

  • Do not forget to change the code so the java.io.File instances contain the correct references to the phonelist.xml and phonelist.xsl files.
  • The TestThreads program is intended to be used with a JAXP 1.3 implementation of the xml-parser and xslt-transformer.
[001] 
[002] package com.xmlmilltest;
[003] 
[004] 
[005] import com.xmlmill.*;
[006] import com.xmlmill.config.Configurator;
[007] import com.xmlmill.log.FileLogger;
[008] 
[009] import java.io.*;
[010] import java.util.Date;
[011] 
[012] // JAXP 1.3 imports  
[013] import javax.xml.transform.Templates;
[014] import javax.xml.transform.TransformerFactory;
[015] import javax.xml.transform.stream.StreamSource;
[016] 
[017] public class TestThreads extends Thread{
[018] 
[019]   private String outputnumber;
[020]   private static File xmlfile = new 
        File("C:\\XMLMill\\samples\\xmlxsl\\phonelist.xml"); 
[022]   private static File xslfile = new 
        File("C:\\XMLMill\\samples\\xmlxsl\\phonelist.xsl");
[024]        
[025]   public TestThreads(String outputnumber){
[026]     this.outputnumber = outputnumber;  
[027] 
[028]   }
[029] 
[030]   public void run(){
[031]     JAXPErrorHandler ehandler = new 
          JAXPErrorHandler(JAXPErrorHandler.ABORT_ON_ERROR ); 
[033]     File output =  new 
          File("C:\\XMLMill3.00\\samples\\xmlxsl\\output\\test_"+outputnumber+".pdf")
          ;   
[036]                 
[037]     OutputStream os = null;
[038]     JAXPTransformer tranform ;
[039] 
[040]     try {
[041]       os = new FileOutputStream(output);  
[042]       tranform = new JAXPTransformer();       
[043]       tranform.setErrorHandler(ehandler);         
[044] 
[045]       tranform.setXMLDocument(xmlfile); 
[046]       transform.setTemplates(templates); 
[047]       
[048]       tranform.setOutputStream(os); 
[049]       tranform.transform(); 
[050]     } catch(Exception e){
[051]       System.out.println("error: "+e);
[052]     } finally {   
[053]       if (os != null) {
[054]         try {
[055]           os.flush();
[056]           os.close();
[057]         } catch (Exception e) {}
[058]       }
[059]       os = null;
[060]       transform = null;   
[061]     }
[062]   }
[063] 
[064]   public static void main(String[] args) {
[065]     TestThreads[]  t  = new TestThreads[30];
[066]                  
[067]     try {
[068]       ////////////////////////////////////////////////////
[069]       // DEFINE FIRST THE LOGGER INSTANCE TO USE        //
[070]       // HERE DEFAULT com.xmlmill.log.FileLogger        //
[071]       // (you can use any class which implements the    //
[072]       // org.apache.commons.logging.Log interface)      //
[073]       ////////////////////////////////////////////////////
[074] 
[075]       // Use the default FileLogger class 
[076]       FileLogger logger = new FileLogger("xmlmill");
[077] 
[078]       // Set logfile
[079]       logger.setFileName("file:/C:/xmlmill3.00/testtransform.txt", 
            false);
[081] 
[082]       // Set the loglevel 
[083]       logger.setLevel("DEBUG");
[084] 
[085]       // Pass the logger to the XMLMill Configurator, so XMLMill can use 
            it.
[087]       Configurator.setLogger(logger);
[088] 
[089]       //////////////////////////////////////////////
[090]       // INITIALIZE THE CONFIGURATOR              //
[091]       //////////////////////////////////////////////    
[092] 
[093]       // Set Configurator  
[094]       Configurator.configure(Configurator.JAXP_13);
[095] 
[096]       //////////////////////////////////////////////
[097]       // CONTINUE                                 //
[098]       //////////////////////////////////////////////
[099] 
[100] 
[101]       // Define templates object (= compiled stylesheet)  
[102]       StreamSource xslsource = new StreamSource( xslfile );
[103]       templates              = 
            TransformerFactory.newInstance().newTemplates( xslsource );          
[105] 
[106]       // Run the threads
[107]       for(int i=0; i<30; i++) {             
[108]         t[i] = new TestThreads(Integer.toString(i)); 
[109]         t[i].start();
[110]         Thread.currentThread().sleep(65);
[111]       }
[112]     } catch (Exception e) {
[113]       System.err.println(e.toString());
[114]     } 
[115]     
[116]     
[117]     
[118]              
[119]              
[120]   }
[121] }                
[122]         

In the main(String[] args) method are following activities performed:

1

Be sure to import the com.xmlmill package.

2

Be sure to import the necessary JAXP packages.

3

In this example the data comes from java.io.File objects, but in real-life java.io.InputStream objects could also be used (generated by another sub-system).

4

Each thread will generate a .pdf document. To make the generation of these documents unique, the filename of each document will contain a unique number.

5

Define the log file to write the logging statements. We use only one log file where log statements of more than one thread are logged.

6

Tell the Configurator we will use a JAXP 1.3 implementation.

7

Compile the stylesheet being used to generate the PDF documents.

8

The main method will generate 30 threads, each generating the phonelist.pdf document.

In each thread run() following must be done:

9

Define an errorhandler that will handle all warnings, errors, fatalErrors.

10

Define a java.io.FileOutputStream where the generated .pdf document should be sent to.

11

Define an instance of the JAXPTransformer class.

12

Set the errorhandler.

13

Define the xml document to be processed using the setXMLDocument(java.io.InputStream) method.

14

Define the templates document (= compiled stylesheet) to be used.

15

Define where the result should be sent to.

16

Do the transformation.

17

Finally close the outputstream and dereference any objects.

  • Although the trial version of XMLMill will only display two pages, it can be used to measure XMLMill's 'thread' performance, as XMLMill will completely generate and write the content to a .pdf file. This way you can check the time XMLMill needs to generate the .pdf document and the size of it.

Please note that the logging will contain with each log statement the threadnumber of the corresponding thread that has written this statement to the log.

images/log_threads.gif
Select to enlarge

Copyright © 2001 - 2012. All rights reserved. XMLMill and XMLMill logo are trademarks of Pecunia Data Systems, bvba.
Powered by Apache CocoonPowered by XMLMill