Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  1/2006
suche: 
Dieser Artikel richtet sich an Java-Entwickler, die auf der Suche nach einer flexiblen Reporting Engine sind.

Glossar

Java Data Base Connectivity (JDBC)
Standard für den Zugriff auf relationale Datenbanken mit Java.
Java-Bean
Java-Klasse mit genau festgelegten Konventionen für die Schnittstellen.
Application Programming Interface (API)
Sammlung von Klassen, welche eine Schnittstelle zu einer Hardware oder Anwendung definieren.
Framework
Sammlung von Tools oder Kombination von Klassenbibliotheken.
Collection
Datenstrukturen in Java. Objekte, die mehrere Elemente zu einer Einheit gruppieren. Collections sind in Listen (List), Mengen (Set) und Abbildungen (Map) kategorisiert.

Weiterführende Links

Links


JasperReports – Java Reporting Engine

Eine sehr häufige Anforderung in Entwicklungsprojekten ist die Erstellung von Reports in verschiedene Dateiformate. Eine Java Reporting Engine, die genau für diesen Sachverhalt entwickelt wurde, ist das Open Source Produkt JasperReports [1]. Wir stellen diese Engine und einige ihrer Funktionalitäten vor.

Designvorlage

In der Designvorlage (*.jrxml) wird das Layout des Reports definiert und dient als Basis für den späteren Report. Diese wird als einfache XML-Datei realisiert und ist dementsprechend einfach zu handhaben. Die Vorlage ist allgemein in sieben Bereiche strukturiert und setzt sich aus den folgenden Elementen zusammen:

Eine fertige Vorlage wird, bevor sie verwendet werden kann, in ein so genanntes JasperDesign (*.jasper) kompiliert. Dabei wird die XML-Struktur in Java-Code gewandelt und gleichzeitig serialisiert. Durch die Methode compileReportToFile(String) der Klasse JasperCompileManager wird dieser Prozess durchgeführt.

Um die Performance zu steigern, ist es sinnvoll, den Report vor dem Einsatz zu kompilieren und nur die JasperDesign-Datei zu verwenden, da das Kompilieren doch einige Zeit beansprucht.

Füllen und Exportieren des Reports

Die fertige Jasper-Datei wird durch eine Methode fillReport(...) der Klasse JasperFillManager mit den gewünschten Daten ergänzt.

Das daraus resultierende JasperPrint-Objekt wird nun durch die Klasse JasperExportManager in die Dateiformate XLS, RTF, CSV, XML, HTML oder PDF konvertiert oder direkt mit Hilfe der Klasse JasperPrintManager auf dem Drucker oder Bildschirm ausgegeben.

Die Funktionsweise von JasperReports wird in der Abbildung 1 schematisch aufgezeigt.

Abb.1 Jasper Reports
Abb. 1: Schematische Funktionsweise von JasperReports (vergrößern!).

Datenquellen

Für die Erstellung der Reports besteht die Möglichkeit, diverse Datenquellen heranzuziehen. Dabei werden folgende Datenquellen standardmäßig unterstützt:

Die Empty Data Source wird in der Regel nur für kurze Tests der Reports genutzt. Dabei wird der Report mit mehreren Zeilen gefüllt, die jeweils nur null-Werte besitzen.

Neben der Database Data Source, die normale JDBC-Statements verarbeitet, stellt JasperReports auch eine XML Data Source zur Verfügung, welche ausschließlich XML-Dateien als Datenquelle akzeptiert.

Um weitere Quellen anzubinden, die Jasper-Reports nicht direkt unterstützt, wird die Custom Data Source angeboten. Hierfür ist es nötig, die passende Java-Schnittstelle selbst zu implementieren und dem Report zu übergeben. Dabei sind gerade die Interfaces JRBeanArrayDataSource und JRBeanCollection-DataSource von großer Bedeutung.

Hierbei ruft JasperReports immer die zugehörige get-Methode eines deklarierten Feldes auf. Die Anwendung ruft beispielsweise bei dem Feld mit der Bezeichnung "projectno" die Methode get-Projectno() der zugehörigen Java-Bean auf.

Felder

Um die gewünschten Daten in den Report zu transferieren, werden Felder benötigt, welche die jeweiligen Daten aufnehmen. In der Regel definiert der Entwickler pro Datenfeld ein Feld in der XML-Vorlage. Dieses Feld kann anschließend die Daten in dem gewünschten Format aufnehmen und in den Report schreiben.

JasperReports unterstützt hierfür einige Java-Datentypen. Neben den Wrapper-Klassen für primitive Datentypen (java.lang.Boolean, java.lang.Integer, etc.) können hier noch Objekte der folgenden Typen benutzt werden:

Falls als Quelle ein anderer Datentyp vorliegt, wird dieser vom Typ java.lang.Object übergeben und anschließend in eines der oben genannten Formate gecastet. Neben diesen dynamischen Feldern gibt es auch die Möglichkeit, statische Felder zu definieren. Diese enthalten einen einfachen Text und dienen somit z. B. als Spaltenüberschrift.

Parameter

Weiterhin besteht die Möglichkeit, Parameter – genau wie Felder – innerhalb der XML-Vorlage zu definieren. Diese werden aber nicht während des Füllprozesses von der Datenquelle geholt, sondern schon beim Aufruf der Methode fillReport(...) der Klasse JasperFillManager mit übergeben. Diese wurden zuvor in der Java-Anwendung als Collection vom Typ HashMap angelegt.

Variablen

JasperReports verarbeiten zudem auch Java-Variablen. Standardmäßig stehen folgende Variablen zur Verfügung:

PAGE_NUMBER Die aktuelle Seitenzahl
COLUMN_NUMBER Die aktuelle Spaltennummer
REPORT_COUNT Anzahl der verarbeiteten Einträge
PAGE_COUNT Anzahl der Seiten
COLUMN_COUNT Anzahl der Spalten
GroupName_COUNT Anzahl der Datensätze innerhalb einer spezifischen Gruppe

Auch eigene Variablen, die auch während des Füllprozesses verwendet werden sollen, können definiert werden.

Expressions

Um dynamisch in den Füllprozess eingreifen zu können, bietet JasperReports so genannte Expressions an. Dafür stehen dem Entwickler unter anderem folgende Elemente zur Verfügung:

Expressions erlauben den Zugriff auf Parameter, Felder und Variablen. Eine einfache Ausgabe dieser Typen innerhalb einer Expression hat folgende Syntax:

$P{ParameterName}
$F{FeldName}
$V{VariablenName}


<pageFooter>
 <band height="15">
 <textField>
 <reportElement x="0" y="20" width="170" height="15"/>
 <textElement textAlignment="Left"/>
 <textFieldExpression class="java.lang.String">
 new java.text.SimpleDateFormat("dd.MM.yyy HH:mm").format(new java.util.Date())
 </textFieldExpression>
 </textField>
 </band>
</pageFooter>
Abb. 2: Beispiel-Ausdruck innerhalb einer XML-Vorlage (vergrößern!).

Darüber hinaus gibt es die Möglichkeit, innerhalb der Expressions einfachen Java Code zu implementieren um z. B. die Ausgabe in einem bestimmten Format zu realisieren oder auch um auf null- Werte zu überprüfen. So lässt sich z. B. mit dem Ausdruck in der Abbildung 2 ganz einfach das aktuelle Datum mit Uhrzeit in der Fußzeile eines Reports erzeugen.

Scriptlets

Zwar ermöglichen Variablen und Expressions es, direkt in den Prozess der Reporterstellung einzugreifen, aber komplexe Logik kann man mit ihnen nicht abbilden.

Genau an diesem Punkt setzen Scriptlets an. Die jeweiligen Methoden der Scriptlet-Klasse werden zur gegebenen Zeit, während des Füllprozesses des Reports, aufgerufen.

Die Scriptlet-Klasse erbt dabei alle Methoden und Attribute von der Klasse JRDefaultScriptlet. Innerhalb der neuen Scriptlet-Klasse stehen anschließend u. a. folgende Methoden zur Verfügung:

In der Vorlage muss darüber hinaus der Name und das Package des Scriptlets mit Hilfe des Attributs scriptletClass im Element <jasperReport> angegeben werden.

Diagramme und Grafiken

Die Möglichkeit, eigene Diagramme oder andere Grafiken in den Report einzubinden, ist eine weitere, nützliche Funktion von JasperReports. Der Anwender hat dabei die Auswahl zwischen den gängigsten Diagrammtypen, wie Säulen-, Balken-, Kreisdiagramme etc.

Auch Grafiken und andere Bilder lassen sich einfach in einen Report einarbeiten. Dabei ist es wichtig, darauf zu achten, dass die Skalierung der Bilder oder Grafiken nicht innerhalb des Reports geschieht. Denn bei dieser findet keine neue Berechnung statt, sondern nur die reine Größenanpassung. Daher ist es von Vorteil, wenn die Grafiken bereits in der nativen Auflösung vorliegen, um den Füllprozess zu beschleunigen und die Dateigröße des späteren Reports nicht unnötig in die Höhe zu treiben.

Gruppen

Die Gruppierung von Datensätzen ist eine weitere Möglichkeit, den Report zu organisieren. Dabei wird die XML-Vorlage um ein Element <group> erweitert. Zu einer Gruppe gehören dann <groupExpression>, <groupHeader> und <groupFooter>. Der Gruppenwechsel wird über die <groupExpression> gesteuert. Ändert sich der Ausdruckswert (z. B. der Wert einer Variablen oder eines Feldes) während der Iteration der Datensätze, werden die Elemente <groupFooter> und <groupHeader> erneut aufgerufen und durchlaufen, bis eine weitere Änderung des Wertes erfolgt.

Subreports

Ein weiterer Vorteil von JasperReports ist die Unterstützung von Subreports. Ein Subreport ist in erster Linie ein "normaler" Report, für den auch eine eigene Designvorlage angelegt wird. Innerhalb der XML-Vorlage des Hauptreports referenziert man auf den Subreport durch die Angabe der Datenfelder, welche in Verbindung zueinander stehen. Auch ein rekursiver Subreport, der auf sich selbst verweist, kann durchgeführt werden. Somit lassen sich auch komplexe Datenstrukturen innerhalb eines Reports abbilden.

Editoren für die Vorlagenerstellung

Um die Erstellung des Reports zu vereinfachen, bieten einige Dritthersteller freie Editoren an, mit denen die XML-Vorlagen komfortabel erstellt werden können.

JasperAssistant

Bei JasperAssistant [2] handelt es sich um ein Eclipse-Plugin. Um dieses in Eclipse zum Laufen zu bringen, wird zusätzlich das "Graphical Editing Framework" benötigt, welches auf der Homepage des Eclipse-Projektes [3] zu finden ist. Der Vorteil hierbei ist natürlich die direkte Implementierung in der Entwicklungsumgebung, wodurch keine weiteren Tools notwendig werden (siehe Abbildung 3).

Jasper Abb. 3
Abb. 3: Screenshot von Eclipse mit JasperAssistant 
(vergrößern!).

JasperAssistant stellt an sich selbst den Anspruch, dass die Anwendung alle Funktionalitäten der letzten JasperReports Version unterstützt. Das ist aber in der Realität nur bedingt der Fall, da die aktuellste Version häufig mit einer ein bis zwei Generationen älteren Version von JasperReports arbeitet.

iReport

Das Problem der Abhängigkeit von der Entwicklungsumgebung umgeht der in Java geschriebene Editor iReport [4]. Hierbei handelt es sich um eine Standalone-Anwendung, die somit unabhängig einsetzbar ist (siehe Abbildung 4).

Screenhot von iReport
Abb. 4: Screenshot von iReport (vergrößern!).

Der iReport-Editor zeichnet sich im Gegensatz zum JasperAssistant durch eine deutlich benutzerfreundlichere Anwendungsumgebung aus. Hier wird einem nicht so versierten Benutzer die Arbeit erheblich erleichtert. Nur werden leider noch nicht alle Funktionalitäten der neuesten Version wie z. B. Crosstabs unterstützt.

Schwachstellen

Die Exportfunktionalitäten von JasperReports leisten einwandfreie Arbeit. Nur der XLS-Exporter lässt noch einige Wünsche offen. Hierbei ist eine Schwäche, dass die Seitenränder eines Reports als eigene Spalten bzw. Zeilen wiedergegeben werden und nicht die eigentlichen Excel-Seitenränder angepasst werden.

Des Weiteren muss gerade bei der Erstellungder XML-Vorlage penibel darauf geachtet werden, dass sich die einzelnen Felder nicht überschneiden. Tritt der Fall dennoch ein, wird das überlappende Feld konsequent ignoriert und nicht in den Report eingebaut.

Das ist vor allem bei doppelzeiligen Reports der Fall. Hierbei kann es passieren, dass die obere Zeile mehr Daten enthält als vorher angenommen und sich dadurch vergrößert. Dabei überschneiden sich sehr häufig die beiden Zeilen, wodurch JasperReports einige Felder im fertigen Report nicht mehr mit Daten füllt.

Daher sollte man doppelzeilige Reports möglichst vermeiden oder die Vergrößerung der Felder durch das Attribut isStretchWith-Overflow innerhalb des Elements <textField> unterbinden, was aber den Nachteil nach sich zieht, dass JasperReports überlange Daten einfach abschneidet.

Ein weiterer Nachteil des XLS- und des RTF-Exporters ist die fehlende Unterstützung von Hyperlinks. Selbst durch Angabe der benötigten HyperlinkExpression verweigern die Hyperlinks ihren Dienst und werden nur als "normaler" Text ausgegeben. Erst durch den Einsatz eines neuen XLS-Exporters, der aber nur als Sample ab der Version 1.1.0 mitgeliefert wird, lässt sich diese Funktionalität realisieren.

Fazit

JasperReports ist eine dynamische und sehr flexible Reporting Engine. Die sehr gute Exportfunktion in diverse Dateiformate arbeitet einwandfrei und mit wenigen Handgriffen. Nicht zuletzt durch den Einsatz von Scriptlets ist JasperReports eine mächtige Reporting Engine, die kaum Wünsche offen lässt. Der sehr erfolgreiche Einsatz in einigen unserer langjährigen Java-Entwicklungsprojekten zeigt, dass JasperReports auch in der Praxis eine ausgezeichnete Wahl für Report- und Druckfunktionalität in Java ist.

Christian Wiesing (info@ordix.de).