Developer’s Corner: Advanced usage of Geoserver Print Plugin

Dear all,
recently we used the Geoserver Printing Module to implement a pdf printing service for a customer application that had some compelling requirements such as:

  • the map should be printed at the higher resolution possible, also with big paper size formats, in a resonable amount of time
  • the printing should include both static content (frames, text, logos) and dynamic content (title and other parameters entered by the user or depending on the current application status)
  • the printing should include a custom legend whose content is driven by the application
What we discovered is that the Geoserver printing module (thanks to the underlying MapFish print module) is a perfect tool to get all these requirements accomplished with little effort.
Now, we would like to share what we did, to show you some techniques you could not be aware of in using the Geoserver printing module.

High resolution printing

First of all, the requirement of having the map printed in high resolution was possible due to:
  • the map was composed only by vector layers
  • Geoserver supports pdf output directly, and in the case of vector layers it produces a vector map in the pdf, not a raster one
  • The  MapFish print module can ask Geoserver for a pdf map and include that in its layout mantaining the map vector format
As you can imagine a map in vector format can be zoomed indefinitely without loosing detail, so it’s perfect to be printed on big size paper sheets up to A0.
If you want to test this yourself you can:
You can try zooming the produced pdf and see that no detail is lost zooming in indefinitely.
  • Download the Geoserver printing module for the 2.3.x version here, install it using the instructions here 
  • use curl to invoke printing for the states layer through the printing module, here an example:

As before, you can try zooming the produced pdf and see that no detail is lost in the map zooming in indefinitely.

Include static content

For sure, you can include many static content types (text, logos, tables) customizing the config.yaml file, but this is not the easiest way, since it is not too much WYSIWYG.
An easier way is to create a pdf with your favourite tool (either a word processor or any other tool able to produce a pdf) containing all the static parts (the only constraint is that the background pdf should have the same dimension and orientation of the layout it will be used in), save it aside the config.yaml file and including it in the layout using the backgroundPdf directive:

backgroundPdf: ‘${configDir}/background.pdf’

Include dynamic content

We have no choice here, to include contents dynamically we have to:
  • configure a layout to use variables that we will be replaced automatically when printing (the variables have the form ${variable_name}; variables can be used as a placemark for text, but also for image urls so that we can have a different logo for each requested print; you can also include the current date and time, some examples:

text: ‘${projectName}’

url: ‘${projectLogo}’ 

text: ${now FORMAT}

Many more examples and instructions are available here.

  • invoke the print service including all the variables actual values in the call

Include customized legend

The MapFish print module is quite flexible also for legends inclusion, but for our project a little bit of customization was needed to:
  • dynamically create simple icons represented by a colored rectangle, without calling an external service
  • distribute legend items horizontally whether the plugin normally layouts them vertically, allowing multirow when a max number of columns are reached
Since the MapFish print module code is available on github, we agreed that the simplest way to get that was to do a fork of the project and customize it for our needs.
Of course we will be very happy to share the customized code with anyone needing it and give it back to the community if feasible to be included in the official release.
The customization introduces the possibility to specify a simple color (such as #FF0000 for red) instead of an icon in a legend spec. In this case the icon will be automatically rendered by the plugin instead of being loaded from an external url.
To get the horizontal alignment we used a trick: we defined a very small maxHeight (5) in the legends configuration block, to force usage of a new column for each icon. Another customization, the introduction of a maxColumns attribute for the legends block allows us to split icons on different rows when needed.
Here an example of output with a maxColumns value of 3:

This is the json used to get the legend:

Mapfish print module 2.0

Since we needed to customize the module, we chose to start from a more recent version of the code than the one currently distributed with the Geoserver printing module (that is 1.2).
The good news is that the 2.0-SNAPSHOT version seems to work perfectly with the current stable release of Geoserver, and only one jar needs to be updated (together with the inclusion of a Spring application context xml). It’s good news because, of course, the 2.0 version has some new feature that can be useful to Geoserver users.
One of those is the disableScaleLocking flag that permits to print maps at any scale, not only those defined in the layout configuration.
For this reason we are going to push for the inclusion of the new version for the 2.4 series of Geoserver.

If you are interested in learning about how we can help you achieving your goals with our Open Source products and professional services, do not hesitate to contact us!

The GeoSolutions team,