Reporting tools

JasperReport Studio

Since all the development in this tutorial will be made using Eclipse IDE (Integrated Development Environment) we shall utilize JasperReport Studio plugin for report design and creation. First create new Maven project, File>New>Maven project. Check Create simple project option and click Next. For Group Id, Artifact Id and Name enter georeports-cmd. Click Finish.

Report creation

Report creation is pretty straightforward. After JasperReport Studio plugin is installed Eclipse offers Report Design perspective. Open Report Design perspective. Select File>New>Jasper Report. Select Blank A4 template. Click Next. Enter file name: HelloWorld.jxml. Click Finish. Take some time to get familiar with tools and features for report creation. Take a look at the blank report and section placeholder. Since JasperReport is very comprehensive reporting tool a huge amount of documentation is publicly available for free. iReport Ultimate Guide is recommended reading.

Planning a Report

There are numerous elements we can use in our report. So let’s make a plan what we would like to produce.

  1. For the beginning,  we should produce something simple, so as the most introductory tutorials suggests, first we shall create a HelloWorld report. In most simple form it would write out message “Hello World”, but since we are working on georeport we will include image with map of the world.
  2. To show some more usable, the real world scenario,  will produce “Catalog of the Europe”. Report should contain image of each European country together with some basic facts about country.
  3. As this tutorial is intentioned for international audience we shall produce a map excerpt with user name and image of his/her homeland country. We shall  display a message “Hello World” “My name is Krunoslav. I come from Croatia”. In your case name and country will probably differ.
Creating a Report

Let’s start with first case. In Title band add new Static text label. Expand it over whole Title band. Enter text “Hello World”. Center it, and set font size to 48. Take a look into .jrxml file, it should contain following:

	<title>
		<band height="79" splitType="Stretch">
			<staticText>
				<reportElement x="0" y="0" width="555" height="79" uuid="50da001c-aadf-4401-ae16-e5a9ec82f689"/>
				<textElement textAlignment="Center">
					<font size="48"/>
				</textElement>
				<text><![CDATA[Hello World]]></text>
			</staticText>
		</band>
	</title>

We can delete all bands except Title and Detail 1. Expand Detail 1 band over the rest of the report by entering Band Height property to 720 px. Drag the image into Detail 1, select URL for Image creation option and enter world map address: http://localhost:8080/geoserver/wms/reflect?layers=opengeo:countries&width=2048 Fit image size to the container size.

	<detail>
		<band height="720" splitType="Stretch">
			<property name="local_mesure_unitheight" value="pixel"/>
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<image>
				<reportElement x="0" y="0" width="555" height="720" uuid="2839c940-dd9f-470b-a09f-5d3f4a0feeef"/>
				<imageExpression><![CDATA["http://localhost:8080/geoserver/wms/reflect?layers=opengeo:countries&width=2048"]]></imageExpression>
			</image>
		</band>
	</detail>

Save changes made to the report and select preview tab. Voila. We just created our first georeport based on free and open source software. Now it is time to explore how to create some more complex report.

Selecting Records

For our second goal, producing “Catalog of Europe” we have to grab some data about each European country and also to produce map image.Save file under name “CatalogOfEurope.jrxml“. In .jrxml file change report name by setting <jasperReport> attribute name=”CatalogOfEurope.jrxml”. WFS service will be used to grab the data – we shall represent it as a remote XML file to JasperReport data source and map some basic data to JaspeReport fields. In Repository Explorer create Data Adapter select XML document (remote). Click Next. Enter Name: DigMap, XML URL:

http://localhost:8080/geoserver/wfs?request=GetFeature&version=2.0.0&typeName=opengeo:countries&cql_filter=continent='Europe'

Click Finish.

Now we need to pair source data and report Fields. In Outline window, make a right click over report name and click Dataset and Query. For the sake of simplicity do a changes as suggested on picture below or try to figure out some other way how to map data using JasperReport GUI dialog and let me know. More effective way is to copy source into .jrxml file.

JasperReport Studio Dataset and Query dialog

JasperReport Studio Dataset and Query dialog

	<queryString language="xpath2">
		<![CDATA[/*[local-name()='FeatureCollection']/*[local-name()='member']/*[local-name()='countries']]]>
	</queryString>
	<field name="gml:lowerCorner" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='boundedBy']/*[local-name()='Envelope']/*[local-name()='lowerCorner']]]></fieldDescription>
	</field>
	<field name="gml:upperCorner" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='boundedBy']/*[local-name()='Envelope']/*[local-name()='upperCorner']]]></fieldDescription>
	</field>
	<field name="opengeo:name_long" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='name_long']]]></fieldDescription>
	</field>
	<field name="opengeo:pop_est" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='pop_est']]]></fieldDescription>
	</field>
	<field name="opengeo:continent" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='continent']]]></fieldDescription>
	</field>
	<field name="opengeo:postal" class="java.lang.String">
		<fieldDescription><![CDATA[*[local-name()='postal']]]></fieldDescription>
	</field>

Change title to “Catalog Of Europe”. It is a right time to introduce a JasperReport parameter. We have to  append cover page image link with bound box of Europe, let’s say: &bbox=-25,35,30,72 To create more flexible application, we can split URL into two parts:  geoserver address and wms request. Such approach enables easy shift to some other geoserver with the same setup. In out case address would be split into:  “http://localhost:8080/geoserver&#8221; and “/wms/reflect?layers=opengeo:countries&width=2048&bbox=-25,35,30,72“. Now GeoServer address can be sent to report as parameter.

	<parameter name="gsURL" class="java.lang.String" isForPrompting="false">
		<defaultValueExpression><![CDATA["http://localhost:8080/geoserver"]]></defaultValueExpression>
	</parameter>

Value for image URL should look like

$P{gsURL}+"/wms/reflect?layers=opengeo:countries&width=2048&bbox=-25,35,30,72"

Increase Title band and put move image to Title band below label. Save report file and take a look at preview.

Organizing Data on a Report

Increase details band. Set band height to 800 px. Add basic data about country: name, population and postal code. Add static label for header and drag fields to Detail 1 band. Run report.

Creating Basic Formulas

To be able to display each European country we have to calculate bounding box for each country and also it would be nice to filter out surrounding countries as well. We’ll do this by creating two variables: bbox and cqlFilter.

	<variable name="bbox" class="java.lang.String">
		<variableExpression><![CDATA["bbox="+$F{gml:lowerCorner}.split(" ")[1]+","+$F{gml:lowerCorner}.split(" ")[0]+","+$F{gml:upperCorner}.split(" ")[1]+","+$F{gml:upperCorner}.split(" ")[0]]]></variableExpression>
	</variable>
	<variable name="cqlFilter" class="java.lang.String">
		<variableExpression><![CDATA["CQL_FILTER=name_long='"+URLEncoder.encode($F{opengeo:name_long},"UTF-8")+"'"]]></variableExpression>
	</variable>

Place image below data. Enter image URL:  $P{gsURL}+”/wms/reflect?layers=opengeo:countries”+”&”+$V{bbox}+”&”+$V{cqlFilter}.

	<title>
		<band height="702" splitType="Stretch">
			<property name="local_mesure_unitheight" value="pixel"/>
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<staticText>
				<reportElement x="0" y="0" width="555" height="85" uuid="b4f76db1-c519-40a7-a3b5-5cee9766d258"/>
				<textElement textAlignment="Center">
					<font size="34"/>
				</textElement>
				<text><![CDATA[Countries of the Europe]]></text>
			</staticText>
			<image hAlign="Center">
				<reportElement x="0" y="85" width="554" height="400" uuid="c36ec364-10a6-4e17-a54b-ad48e412e008"/>
				<imageExpression><![CDATA[$P{gsURL}+"/wms/reflect?layers=opengeo:countries&bbox=-25,35,35,70"]]></imageExpression>
			</image>
		</band>
	</title>
	<detail>
		<band height="642">
			<property name="local_mesure_unitheight" value="pixel"/>
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<image hAlign="Center">
				<reportElement x="-1" y="100" width="555" height="470" uuid="43c15586-e262-4899-b587-8c5e413e0602"/>
				<imageExpression><![CDATA[$P{gsURL}+"/wms/reflect?layers=opengeo:countries"+"&"+$V{bbox}+"&"+$V{cqlFilter}]]></imageExpression>
			</image>
			<textField>
				<reportElement x="-1" y="80" width="141" height="20" uuid="1de12aa6-91fc-4440-a128-94fdb0834f5c"/>
				<textFieldExpression><![CDATA[$F{opengeo:name_long}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="140" y="80" width="138" height="20" uuid="2c4ef33f-e9e1-41cc-bcc7-ece98af78054"/>
				<textFieldExpression><![CDATA[$F{opengeo:pop_est}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="278" y="80" width="138" height="20" uuid="6cdd59d5-9584-4ad0-be0d-85db1418017d"/>
				<textFieldExpression><![CDATA[$F{opengeo:continent}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="416" y="80" width="138" height="20" uuid="dcbe6e66-ce95-4e00-a52d-92f139ab11ed"/>
				<textFieldExpression><![CDATA[$F{opengeo:postal}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="-1" y="70" width="141" height="20" uuid="612a6a3a-3989-4c27-a25e-de47591ba0fd"/>
				<text><![CDATA[opengeo:name_long]]></text>
			</staticText>
			<staticText>
				<reportElement x="140" y="70" width="138" height="20" uuid="ad559895-b9ba-4f60-8369-54a91bbaf3a6"/>
				<text><![CDATA[opengeo:pop_est]]></text>
			</staticText>
			<staticText>
				<reportElement x="278" y="70" width="138" height="20" uuid="fd037102-c8f7-41f4-92eb-7643bc07af5b"/>
				<text><![CDATA[opengeo:continent]]></text>
			</staticText>
			<staticText>
				<reportElement x="416" y="70" width="138" height="20" uuid="82e0f39b-834f-4acf-b3de-cab06a5c8cd7"/>
				<text><![CDATA[opengeo:postal]]></text>
			</staticText>
		</band>
	</detail>

Run report. We are now familiar with basic concepts of report data: parameters, fields and variables, report sections: title, details, summary.. and reports elements: label, field, image … let’s move to our third goal, customized report based on input parameter.

Applying Conditional Reporting

Save report as PersonalizedHelloWorld.jrxml and correct report name in .jrxml file. We will introduce two new parameters: userName and countryName in my case defaulting to “Krunoslav” and “Croatia”

	<parameter name="userName" class="java.lang.String" isForPrompting="false">
		<defaultValueExpression><![CDATA["Krunoslav"]]></defaultValueExpression>
	</parameter>
	<parameter name="countryName" class="java.lang.String" isForPrompting="false">
		<parameterDescription><![CDATA[]]></parameterDescription>
		<defaultValueExpression><![CDATA["Croatia"]]></defaultValueExpression>
	</parameter>

Report will produce a “Hello World” message with additional greeting: “My name is Krunoslav. I come from Croatia”, showing country map and basic data. Remove image from Title band, decrease Title band height, and change static label back to “Hello World”. In Detail 1 section add additional text field for greeting. Data filtering should be based on country name. Use expresion $F{opengeo:name_long}.equalsIgnoreCase($P{countryName}) to filter data. Since report should work for any country in the world we have to remove CQL filter from WFS request (open DigMap data source and remove CQL filter part). Some .jrxml code is below for faster setup.

	<filterExpression><![CDATA[$F{opengeo:name_long}.equalsIgnoreCase( $P{countryName} )]]></filterExpression>
	<background>
		<band splitType="Stretch"/>
	</background>
	<title>
		<band height="79" splitType="Stretch">
			<property name="local_mesure_unitheight" value="pixel"/>
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<staticText>
				<reportElement x="0" y="0" width="555" height="79" uuid="b4f76db1-c519-40a7-a3b5-5cee9766d258"/>
				<textElement textAlignment="Center">
					<font size="34"/>
				</textElement>
				<text><![CDATA[Hello World]]></text>
			</staticText>
		</band>
	</title>
	<detail>
		<band height="649">
			<property name="local_mesure_unitheight" value="pixel"/>
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<image hAlign="Center">
				<reportElement x="0" y="40" width="555" height="470" uuid="43c15586-e262-4899-b587-8c5e413e0602"/>
				<imageExpression><![CDATA[$P{gsURL}+"/wms/reflect?layers=opengeo:countries"+"&"+$V{bbox}+"&"+$V{cqlFilter}]]></imageExpression>
			</image>
			<textField>
				<reportElement x="0" y="20" width="141" height="20" uuid="1de12aa6-91fc-4440-a128-94fdb0834f5c"/>
				<textFieldExpression><![CDATA[$F{opengeo:name_long}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="141" y="20" width="138" height="20" uuid="2c4ef33f-e9e1-41cc-bcc7-ece98af78054"/>
				<textFieldExpression><![CDATA[$F{opengeo:pop_est}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="279" y="20" width="138" height="20" uuid="6cdd59d5-9584-4ad0-be0d-85db1418017d"/>
				<textFieldExpression><![CDATA[$F{opengeo:continent}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="417" y="20" width="138" height="20" uuid="dcbe6e66-ce95-4e00-a52d-92f139ab11ed"/>
				<textFieldExpression><![CDATA[$F{opengeo:postal}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="10" width="141" height="20" uuid="612a6a3a-3989-4c27-a25e-de47591ba0fd"/>
				<text><![CDATA[opengeo:name_long]]></text>
			</staticText>
			<staticText>
				<reportElement x="141" y="10" width="138" height="20" uuid="ad559895-b9ba-4f60-8369-54a91bbaf3a6"/>
				<text><![CDATA[opengeo:pop_est]]></text>
			</staticText>
			<staticText>
				<reportElement x="279" y="10" width="138" height="20" uuid="fd037102-c8f7-41f4-92eb-7643bc07af5b"/>
				<text><![CDATA[opengeo:continent]]></text>
			</staticText>
			<staticText>
				<reportElement x="417" y="10" width="138" height="20" uuid="82e0f39b-834f-4acf-b3de-cab06a5c8cd7"/>
				<text><![CDATA[opengeo:postal]]></text>
			</staticText>
			<textField>
				<reportElement mode="Transparent" x="0" y="530" width="555" height="99" forecolor="#000000" backcolor="#FFFFFF" uuid="b35aa40a-8632-44b5-a007-51c0f2846f62"/>
				<box padding="0" topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0"/>
				<textElement textAlignment="Left" verticalAlignment="Top" rotation="None" markup="none">
					<font fontName="SansSerif" size="24" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
					<paragraph lineSpacing="Single" lineSpacingSize="1.0" firstLineIndent="0" leftIndent="0" rightIndent="0" spacingBefore="0" spacingAfter="0" tabStopWidth="40"/>
				</textElement>
				<textFieldExpression><![CDATA["My name is "+$P{userName}+"."+"I come from "+$P{countryName}+"."]]></textFieldExpression>
			</textField>
		</band>
	</detail>
</jasperReport>

If you wish, change labels for country name, population, continent and postal code. Run report. And that’s all folks. Now we know how to produce geo-reports, let’s move on to integration part. Stay tuned, we’ll find out how to embed reports in java desktop application, in java web application and finally how to embed geo-reports in GeoServer.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s