= JasperReports =

Jasper ist ein Reportgenerator in Java. Ein Reportgenerator nimmt Daten aus einer Datenquelle (z.B. einer SQL-Datenbank) und gibt diese z.B. als eine Liste aus. Diese Liste kann weitgehend gestaltet werden, Daten können dabei aggregiert werden und sogar Charts (also graphische Auswertungen der Daten in Form von Digrammen) können eingebunden werden. Nach eigenen Angaben ist JasperReports die meistgenutzte Opensource Report Engine in Java.

Übrigens ist JasperReports nicht nur für Java-Freaks zu benutzen. Wer iReport als Designer benutzt, wird nicht groß bemerken, in welcher Programmiersprache das Fanze geschrieben ist. Das Ausfüllen von Reports kann per Ant-Skript gehen. Als Skriptsprache innerhalb der Reports gibt es mehrere Möglichkeiten (eine Shell-Variante, [Groovy] und natürlich Java). Ich behaupte hier mal einfach, daß es auch in anderen Sprachen nichts vergleichbar ausgereiftes im Open Source Bereich gibt - also auch für nicht-Javaner gilt: nur Mut!


== Vergleich mit [EclipsePlugin.BIRT] ==

Im Gegensatz zu [EclipsePlugin.BIRT] arbeitet JasperReports mit festen Größen der Anzeigefelder und nicht mit dynamischen, HTML-ähnlichen Feldern. Das mag zwar nicht so modern sein, führt aber meistens zu Ergebnissen, die viel näher an dem liegen, was man wirklich gemeint hat. Die festen Größen erschweren es andererseits sicherlich, Reports automatisch zu generieren, aber das werde ich vielleicht später mal ausprobieren.

Auf den ersten Blick scheint JasperReports auch wesenlich schlanker zu sein. Das zeigt sich erstens an der Größe der benötigten Bibliotheken aber zweitens vor allem auch an der Geschwindigkeit: Mein erster Beispiel-Report benötigte auf meinem Laptop mit BIRT ca. 15 Sekunden, mit Jasper 4 Sekunden und vorkompiliert nur 1,5 Sekunden.

JasperReports ist weit stärker mit dem Desktop-Benutzer bzw. der Erzeugung von Ausdrucken im Hinterkopf entwickelt worden, während BIRT seine Stärke eher im Erzeugen von HTML-Reports hat. Hier hat BIRT auch Eigenschaften wie Reports, die beim Anklicken aufklappen oder mit anklickbaren Inhaltsverzeichnissen, die in Jasper nicht zu finden sind.



== Vergleich mit JodReports ==

JodReports kann man auch ganz gut für Reporte aus Java heraus benutzen. Es hat einen ganz anderen Ansatz. Es erlaubt, OpenOffice-Dokumente als Basis zu nehmen, was einerseits vielen "einfachen Benutzern" sehr entgegenkommen dürfte, andererseits aber bei nur etwas komplexeren Templates schnell sehr schwierig wird. Man kann es schlecht erklären, aber die OpenOffice-Eingabefelder sind nun mal keine Programmierumgebung mit Debugger und qualifizierten Fehlermeldungen. FreeMarker tut sein übriges dazu, indem es sich immer bemüht, Fehlermeldungen so auszudrücken, daß man den Fehler möglichst nicht findet. ;-)

Letztlich erlaubt es iReports aber auch, das sich einfache Benutzer einarbeiten. Es kommt auf einen Versuch an. Die Frage ist daher eher, was für ein Dokument will ich denn erzeugen? Ist es ein Serienbrief? Dann ist vielleicht OpenOffice das bessere Werkzeug. Ist es ein Report? Dann ist wahrscheinlich Jasper das bessere Werkzeug.



== Erste Schritte ==

=== Erstellung eines Report mit iReport ===

Als erstes sollte man die JasperReports-Webseite links liegen lassen, und sich iReport herunterladen und starten. Auf der iReport-Seite gibt es nun ein kleines "Getting Started"-Tutorial. Dieses enthält eigentlich auch nicht viel, weil sich der erste Report fast von ganz alleine erstellt. :-) Man kann den Report aus iReport heraus dann auch anzeigen bzw. in vielen verschiedenen Formaten (z.B. PDF) ausgeben und abspeichern.

Weitere Änderungen und Anpassungen gehen recht intuitiv mittels Drag & Drop sowie recht übersichtlichen Properties-Dialogen. Mein anfängliches Problem, daß die von mir per Hand positionierten Felder nie genau neben- oder untereinander standen, erledigte sich nach einem Blick in die Toolbar, wo man Felder auf alle Arten aneinander ausrichten kann. Alles in allem hatte ich ohne einen Blick in die Anleitung nach zwei Stunden einen recht komplexen Bericht mit Formatierungen, Variablen und geschachtelten Formeln (allerdings ohne Charts). Letzlich ist die Berichterstellung nicht schwieriger als mit BIRT, nur etwas anders. Man sollte sich von Anfang an überlegen, was man will, weil z.B. das nachträgliche Einfügen einer Spalte mehr Arbeit macht als in BIRT.

== Ausgabe des Reports im Programm ==

Auch das ist im Tutorial recht anschaulich erklärt. Im Grunde geht es aber so einfach, daß ich hier direkt ein Beispiel angebe, weil das mehr sagt als tausend Worte:

{{{
	public static void executeReportJrxml(String name) throws JRException,
			ClassNotFoundException, SQLException {
		// Datenbank
		Class.forName("org.hsqldb.jdbcDriver");
		Connection conn = DriverManager.getConnection(
				"jdbc:hsqldb:file:/home/tbayen/.Applikation/datenbank", "sa", "");
		// compilierten Report erzeugen
		InputStream strm = ReportDepotUebersicht.class.getClassLoader()
				.getResourceAsStream(name + ".jrxml");
		JasperReport report = JasperCompileManager.compileReport(strm);
		// Parameter festlegen und den Report ausfüllen
		JasperPrint printout = JasperFillManager.fillReport(report, null, conn);
		// und ausgeben
		JasperViewer.viewReport(printout);
	}
}}}


== Tips und Tricks ==

Zwei Besonderheiten sind mir aufgefallen. Zum einen bedarf es eines besonderen Tricks, um einen Text der Art "Seite 3 von 5" auf einen Report zu schreiben. Zum anderen störte mich am Anfang, daß man in Ausdrücken Werte in Java-Grundtypen immer in Java-Objekte wandeln musste. Beide Probleme sind in der FAQ auf der Webseite beschrieben. Auch das spricht für die Qualität der Dokumentation.

===  Entwicklung der Tools zum Erstellen von Berichtstemplates / Jaspersoft Studio ===

Für einige Jahre war Jasperreports vor allem eine Bibliothek. Um Berichts-Templates zu erstellen, gab es zu Anfang verschiedene Programme, die mehr oder weniger komfortabel waren. Es stellte sich dann recht schnell heraus, das iReports das Mittel der Wahl war, das dann auch von Jaspersoft unterstützt wurde. Im Laufe der Zeit wurde dann aus dessen Code ein Eclipse-Plugin erstellt. Heutzutage ist iReport nicht mehr offiziell unterstützt, stattdessen kann man das Jaspersoft Studio herunterladen, das eine fertige Distribution eines Programmes ist, mit dem man sehr komfortabel und immer auf dem akteullen Stand der Möglichkeiten der Bibliothek Berichte erstellen kann. Es basiert auf der Eclipse-Plattform und enthält entsprechende Plugins für die Bearbeitung von Templates, Kommunikation mit dem JasperServer, etc. Ein Plugin, das man in ein Standard-Eclipse einfügen kann, gibt es meines Wissens nach nicht mehr (Obwohl es denkbar erscheint, das man die im Studio verwendeten Plugins einfach benutzen kann).

=== Integration in die EclipseIDE / iReport ===

''Dieser Absatz ist veraltet, er beschäftigt sich mit dem älteren iReport. Ich habe ihn hier aber als Referenz stehen gelassen:''

Obwohl in unten genanntem Link steht, daß es eine Eclipse-Integration für iReport geben sollte, konnte ich diese nicht finden. Es gobt jedoch entsprechende Plugins von anderen Anbietern. Da iReport mir sehr gut gefallen hat und von den JasperReport-Machern offiziell mitgepflegt wird, habe ich mir die Alternativen jedoch nicht angeschaut.

Man kann in Eclipse in den Preferences unter ''General -> Editors -> File Associations'' auch externe Programme einer Dateiendung zuordnen, so daß ich auch aus Eclipse heraus iReport starten kann. Dazu habe ich iReport in seinen Einstellungen so konfiguriert, daß es keine Cache-Dateien mehr in dem Verzeichnis erstellt, in dem die Report-Beschreibung liegt, sondern das alles in ''/tmp'' macht. Damit kann ich gut leben.

=== Zusammenarbeit mit HSQLDB ===

Ich hatte einige Probleme beim Zugriff auf HSQLDB-Datenbanken. Zuerst dachte ich, daß läge daran, daß ich die mitgelieferte HSQLDB-Version 7.1 gegen die von mir benutzte, neuere Version 1.8 ausgetauscht hatte. Schliesslich bin ich aber dahintergekommen, daß es wohl an meinen Tabellennamen und Spaltennamen liegt, die nämlich Groß- und Kleinschreibung benutzen. Dadurch funktioniert der Query-Assistent leider gar nicht mehr. Dennoch kann man seinen Query-String von Hand eingeben, wenn man alle Namen in Anführungszeichen setzt. Tabellennamen kann man ohne Anführungszeichen benutzen, wenn man in der FROM-Clause den Namen nochmals als "AS"-Wert angibt. Hier mal am besten ein Beispiel aus meinem Demo-Projekt:

  SELECT "ISIN","name","kursdatum","schlusskurs","datum","anzahl","kurs", "anzahl"*"kurs" AS "preis"
  FROM "Wertpapier" Wertpapier, "Transaktion" Transaktion
  WHERE Wertpapier."id" = Transaktion."wertpapier"
  ORDER BY "ISIN", "datum"


=== JasperReportsMitJavaBeans ===

Die Verwendung von ~JavaBeans als Datenquelle ist relativ unüblich, bietet aber einige Besonderheiten. Deshalb habe ich mich entschlossen, dieses Thema auf der eigenen Seite JasperReportsMitJavaBeans zu behandeln.

=== JasperServer ===

Wer mehr als eine Handvoll Berichte ausgeben will und das einer Schar von Benutzern im Netz ermöglichen will, sollte darüber nachdenken, den JasperServer zu installieren. Das ist ein Webserver (in Java), der Berichte verwaltet und über eine Weboberfläche einfach und komfortabel anzeigen kann (z.B. auch für anonyme Benutzer). Ich habe ihm eine eigene Seite gewidmet: JasperServer.

=== Seite x von y ===

Dieser Trick ist eigentlich nichts besonderes, weil er in der Standard-Bibliothek für vorgefertigte Ausdrücke bereits enthalten ist und mit einem Klick aktiviert werden kann. Dennoch möchte ich ihn hier erklären, weil er ein schönes Beispiel dafür ist, wie man manchmal "die Ecke rum" denken muss.

Man teilt die Ausgabe in zwei verschiedene Text-Felder auf, die man unauffällig direkt nebeneinander positioniert. Dabei wird das erste rechts- und das zweite linksbündig gemacht, so daß sich keine Lücke dazwischen ergibt. In beiden benutzt man die Variable V{PAGE_NUMBER}. Unterschiedlich ist dabei lediglich die Ausführungszeit. Der linke Block bekommt "jetzt", d.h. der Wert der Variablen wird während der Reportgenerierung sofort an der Stelle ermittelt, wo man gerade steht (ergibt also die aktuelle Seitenzahl). Der rechte Block bekommt die Ausführungszeit "Bericht". Dadurch wird die Variable erst am Ende des Berichts ausgewertet und ergibt dann also die Gesamtzahl der Seiten.

==== Zusatzfrage ====

Übrigens fände ich es interessant, wenn man den Text "Seite x von y" weglassen könnte, wenn das Dokument nur eine einzige Seite hat. Fällt da jemandem was ein?



=== Seitenzahlen "x von y" pro Datensatz mit Subreports ===

Ich habe einen Report, der Rechnungen erzeugt. In jeder Rechnung ist ein Subreport, der Umsatzzeilen ausgibt. Nun kann dieser Subreport so lang sein, daß die Rechnung auf mehrere Seiten kommt. Hierzu gibt es mehrere Lösungen:

Die erste ist komplizierter, aber etwas flexibler: Man erzeugt eine Variable (RECHNUNGSSTART), die an jedem Seitenende auf den Wert von PAGE_NUMBER gesetzt wird. Man sollte meinen, das ergibt nur eine Kopie der Seitenzahl, das ist aber weit gefehlt. Diese "Seiten"-Variablenaufrufe werden nämlich nur bei klassischen Seitenwechseln gemacht, aber nicht, wenn der Seitenwechsel durch einen Subreport erfolgt. Somit hat die Variable immer die Seitenzahl der ersten Seite des Reports. Mit ein bisschen Mathematik (PAGE_NUMBER-RECHNUNGSSTART+1) bekommt man dann eine hübsche Seitenzahl. Mit dem Trick oben kann man dann mit der Einführung einer Gruppe, die immer erzeugt wird (z.B. auf den Primärschlüssel) per Ausführungszeit "Gruppe" die Gesamtzahl der Seiten ausgeben.

Die zweite Alternative ist einfacher: Man erzeugt die oben vorgeschlagene Gruppe nach dem Primärfeld (die übrigens sowieso für alles mögliche ganz praktisch ist, weil Sie einem eine Art zusätzliche Detail-Bänder erzeugt) und setzt dort im Header dann die Property "Reset Page Number". Jetzt kann man die normale Formel (aus der Bibliothek) benutzen und muss dabei lediglich die Ausführungszeit von "Report" auf "Gruppe" setzen. Vorteil ist, daß man sich die Variable und die Rechnerei spart. Nachteil ist, daß man nun keine Gesamt-Seitenzahl mehr hat.



=== Autoboxing in iReport ===

Die hier beschriebene Einstellung sollte man am besten sofort nach der Installation von iReport vornehmen. Die Grundeinstellung verstößt nämlich gegen die Genfer Konvention gegen Programmierer-Folter....

Wer ein wenig mit Formeln in iReports gearbeitet hat, wird feststellen, daß man dort in Java kein autoboxing benutzen kann. D.h. wenn ein Ausdruck den boolean-Wert "true" ergibt, gibt das eine Fehlermeldung, weil Jasper auf einem Rückgabewert Boolean.TRUE besteht. Das selbe gilt u.a. für das Rechnen mit Integer-Werten, das leider nicht so einfach geht, weshalb man Integer zum Rechnen in int wandeln muss, um dann das Endergebnis wieder in Integer zu wandeln.

Alles in allem ist das großer Quark. Das liegt daran, daß iReport - warum auch immer - als Standard einen Java 1.4-Compiler benutzt. Es handelt sich also um gar kein Jasper-Problem, sondern nur um eine "falsche" Einstellung in iReport. Um das zu ändern, kann man entweder diesen Compiler auf Java 1.5 umschalten, indem man eine Properties-Datei in den Classpath einfügt (siehe JasperReports-FAQ unter http://jasperforge.org/uploads/publish//jasperreportswebsite/JR%20Website/jasperreports_faq.html) oder, indem man die "tools.jar" aus dem JDK in den Classpath aufnimmt (im Menü Options/Classpath) und dann im Menü Options/Settings auf der Registerkarte "Compiler" auf den JDK-Compiler umstellt.


=== Grid in iReport ===

In den Settings kann man einstellen, daß ein Gitter über die Seite gelegt wird. Das ist wie Kästchenpapier. Wenn amn z.B. mit einem Zeichensatz der Größe 10 arbeitet und dann ein 10er Gitter (oder ein 12er, wer will) einstellt, kann man sicher sein, daß seine Zeilen immer ordentlich in gleichem Abstand stehen. Eine Besonderheit möchte ich hier aber nicht verschweigen: Wer mit einem Gitter arbeitet, sollte die Vergrößerung immer auf einen ganzzahligen Wert stellen (am besten auf einen der Standard-Werte). Wer als Vergrößerung "Width" benutzt, um die Seitenbreite auszuschöpfen, bekommt Probleme, weil das angezeigte Gitter nicht mehr stimmt.


== Links ==

* [JasperReports Homepage|http://www.jasperforge.org/jaspersoft/opensource/business_intelligence/jasperreports/index.html]
* [iReport Homepage|http://jasperforge.org/jaspersoft/opensource/business_intelligence/ireport/index.php] - Report-Designer
* [EclipsePlugin.BIRT] - Ein alternativer Report-Generator in Java
* [Liste von Eclipse-Plugins für JasperReport|http://www.jasperforge.org/index.php?option=com_mtree&task=listcats&cat_id=101&Itemid=91]
** [iReport-Plugin für Eclipse|http://www.jasperforge.org/index.php?option=com_mtree&task=viewlink&link_id=82&Itemid=91]
** [JasperAssistant Plugin für Eclipse|http://www.jasperassistant.com/]
** [Sunshine-Reports Plugin für Eclipse|http://www.pratocity.com/index.jsp?mod=/sunshine/sunshine.jsp]
* [Vergleich Pentaho, BIRT, JasperReports|http://it-republik.de/jaxenter/artikel/Pentaho-BIRT-und-JasperReports-im-Vergleich-1737.html]

----
[{Tag Java Groovy Eclipse Templates Datenbank}]