Apache::AxKit::Language::FOP - generate PDF using Apache FOP


Apache::AxKit::Language::FOP - generate PDF using Apache FOP


    AxAddStyleMap text/xslfo +Apache::AxKit::Language::FOP
    PerlSetVar AxFOPConfigFile /path/to/my/userconfig.xml
    PerlSetVar AxFOPPath       /usr/bin/fop

If you want to use JavaServer, specify one or more of:

    PerlSetVar AxFOPJavaServerPort      2000
    PerlSetVar AxFOPJavaServerAuthFile  /path/to/my/authfile
    PerlSetVar AxFOPJavaServerDirectory /my/special/directory

If you want to cache when PDF is generated dynamically with XSP:

    PerlSetVar AxFOPCache IfNoCache

When running under JavaServer, this module will reset FOP's image cache when needed. If you are using an older FOP that does not support this feature, then specify the following to leave the image cache alone:

    PerlSetVar AxFOPImageCache On


This module uses Apache FOP to generate PDF by processing XSL-FO files. It can either call the command line tool ``fop'', or for better performance, it can use the XML::ApacheFOP package (which uses the Java.pm Perl package and JavaServer software).

For running FOP via the command line, you can specify the path to your FOP executable with the directive AxFOPPath. The default value is simply ``fop'' which will get resolved by your shell using whatever PATH is currently in effect.

To enable use of XML::ApacheFOP, specify one or more AxFOPJavaServer directives as shown above. Unspecified directives will fall back to their default values defined in XML::ApacheFOP.

If you need FOP to run with an external configuration file, specify the location using the AxFOPConfigFile directive. See http://xmlgraphics.apache.org/fop/configuration.html for options you can specify in an external configuration file. For example, you can specify a baseDir to be used when resolving a relative URL from the src attribute of an fo:external-graphic.

Multiple output render types are supported by FOP, to varying degrees:

    pdf: application/pdf
    mif: application/vnd.mif
    pcl: application/vnd.hp-PCL
    ps:  application/postscript
    txt: text/plain
    svg: image/svg+xml
    at:  text/xml

If the AxKit PreferredStyle matches one of the above styles, then that style will be the render type output by this module. If the PreferredStyle does not match, then the output type will be pdf.


The standard AxKit caching mechanism automatically caches the output in most cases (unless disabled with AxNoCache). However, if your content is being generated dynamically from an XSP script, then AxKit will not cache the output.

To enable caching for XSP-generated content, set the configuration directive AxFOPCache to ``IfNoCache''. When this directive is set (and caching is not disabled with AxNoCache), the output will be cached separately by this module whenever AxKit has turned off its caching (that is, when $AxKit::Cache->no_cache returns a true value). The cache file is managed using Apache::AxKit::Cache with a key generated using Digest::MD5 from the input content and the output style.

To turn off separate caching by this module you can set ``AxFOPCache Off'' (this is the default).

The AxKit cache is not automatically cleaned. If space is an issue, such as when you are caching pages that are customized for individual users, then you need to run a cron job or something similar to delete stale files from the cache. For example, see Apache::AxKit::CacheCleaner.

Notes about fo:external-graphic

You can use relative links to external graphics. They will be resolved relative to the directory of your source file. If the resulting file does not exist, then the relative link will be resolved relative to the definition of baseDir in the FOP configuration file. This behavior mimics that of FOP when called from the command line--it resolves relative links first with respect to the current directory and second with respect to baseDir, which is set to the location of your source file unless otherwise defined in the FOP configuration file.

When using JavaServer be sure it has permission to locate and access the external graphic file.

If you have not defined a baseDir in a FOP configuration file, then this module will create one with baseDir set to the source directory, in case FOP needs to resolve a relative link on its own. (This feature may be redundant since the link to the external graphic will have already been resolved by this module, but the feature remains just in case FOP uses baseDir for other reasons.)

Why does this module resolve the relative links instead of letting FOP do it? As explained below, FOP caches images between runs (when called through JavaServer), and unfortunately it caches the image based on the link before it gets resolved, which can lead to the wrong image being used if it has the same name but resides in a different directory. For example, if you have a document in one directory that loads an image ``logo.svg'', and you have another document in another directory that loads a different image ``logo.svg'', then FOP will re-use the first image. An additional reason this module resolves the links is because FOP might not run from the same directory as your source file, especially if it is being run through JavaServer, so FOP could load some random graphic relative to its current directory instead of relative to your source file.

AxKit is informed of any external-graphics from your document so that it can check the timestamp and recreate the output instead of using its cache if a graphic file is newer than the cache file (unless you have AxDependencyChecks Off). This module will also perform these dependency checks when you have turned on separate caching (unless you have AxDependencyChecks Off).

When using XML::ApacheFOP with JavaServer, images are cached by FOP between runs. See http://xmlgraphics.apache.org/fop/0.20.5/graphics.html#caching for more information. If you have not disabled caching with AxNoCache and have not turned off AxDependencyChecks, then this module will keep track of which external-graphics have been used and will reset FOP's image cache whenever a graphic file changes or when FOP has cached 1000 images. You can change the limit, for example:

  AxFOPImageCache 100

This module uses an SDBM file named AxFOPImageTrack located in AxKit's cache directory to keep track of the graphic files. You can specify a different location or file name, for example:

  AxFOPImageTrack /var/cache/axkit_fop_images

If you have disabled caching with AxNoCache, then this module will not keep track of external-graphics, and it will reset FOP's image cache before each run. You can force this behavior by specifying:

  AxFOPImageCache Off

The ability to reset the image cache is available starting with FOP version 0.20.5. If you have an earlier version, you can instruct this module to leave the cache alone so as to avoid error messages in your log:

  AxFOPImageCache On

This module will also leave the cache alone if you have turned off AxDependencyChecks. With an earlier version of FOP or when you instruct this module to leave the cache alone, you should restart JavaServer whenever you change an external-graphic file or whenever you think it is running out of memory from caching too many images. For example:

  /etc/init.d/javaserver restart
  invoke-rc.d javaserver restart # on Debian


A temporary directory with a prefix of ``axkit-fop-'' is created on each request (using File::Temp) to contain the input and output files for FOP. This directory is readable/writable only by the web server process and it is automatically deleted in the mod_perl cleanup phase at the end of each request.

If you are using XML::ApacheFOP and JavaServer, then the JavaServer process needs read/write permission on this temporary directory. One way to allow this permission is to run your JavaServer process under the same user as your web server.

An alternative method, if your JavaServer is running as a different user from your web server, is to run your JavaServer under a group in which the web server belongs, and create a special temporary directory owned by this group with the group sticky bit set so that subdirectories will also be owned by the group. Inform this module of that directory with this directive:

    PerlSetVar AxFOPJavaServerDirectory /my/special/directory

This module will turn on the group read/write permissions on temporary subdirectories created under this special directory.

Here is an example setup using Debian GNU/Linux commands (if someone can generalize this example let me know). Assume your JavaServer process is running under the user ``javaserv'' and the group ``javaserv'', and your web server is running under the user ``www-data'' and the group ``www-data''.

Add your web server user to the JavaServer group:

    adduser www-data javaserv

Create a temporary directory with the group sticky bit set:

    install -m 2770 -o javaserv -g javaserv -d /var/cache/javaserver

Update your Apache configuration with this directive:

    PerlSetVar AxFOPJavaServerDirectory /var/cache/javaserver


AxKit, XML::ApacheFOP, Apache::AxKit::CacheCleaner


Ken Neighbors <ken@nsds.com>

Based on the Apache::AxKit::Language::PassiveTex module, but severely rewritten.


Copyright (c) 2005-2007 Ken Neighbors. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

 Apache::AxKit::Language::FOP - generate PDF using Apache FOP