Java JasperReports Schnittstelle mit REST

Nero1

Captain
Registriert
Nov. 2009
Beiträge
3.730
Hi,

ich bin derzeit damit beschäftigt, über REST abgerufene Inhalte (JSON Format) in einen Report von JasperReports zu knallen. Ziel is dafür eine Userschnittstelle, die es mir ermöglicht diese Daten über bestimmte Parameter in den Report einzufügen. So wie ich das bisher verstanden habe definiere ich mir quasi diese Parameter mit den entsprechenden Werten/der Verbindung, wo diese Daten abgerufen werden, und binde das dann als .jar in iReport/JasperSoft Studio ein. Eigentlich sollte ja ein Großteil dann über iReport/JSS laufen können was Queries, Auswahl der Daten usw. betrifft.

Kleines Beispiel:
Ich bekomme von der Webseite per REST und HTTP Request einen Datensatz im JSON Format, wie z. B. einen Hostnamen, dessen IP-Adresse und ein paar weitere Variablen mit den entsprechenden Werten im Stil "param" : "value". In iReport/JSS möchte ich nun z. B. auwählen können ich möchte den Parameter Hostname und IP-Adresse von einem Objekt mit dem Hostnamen "Host 1".

Soweit ich das bisher sagen kann muss ich dazu ein paar Interfaces von Jasper implementieren und entsprechend anpassen/nutzen. Darunter sowas wie JasperFillManager.fillReport(...) usw.

Hat jemand von euch schon mal etwas ähnliches gemacht und ne JAR geschrieben, die dann Daten bereitstellt? Ich finde zwar zig Tutorials, aber meist nur mit iwelchen Datenbanken oder nicht genau das was ich brauche.
Ich würde gerne verstehen was genau ich tun muss, um das zu erreichen. Sprich, welche Schnittstellen benutzen, wie hängt das intern zusammen und wie spricht Jasper das an. Ich brauch dafür keinen fertigen Code, mir würde es schon reichen wenn jemand diese Kommunikation mal näher erläutern könnte. Gerne auch mal per Skype oder so, falls sich jemand dazu bereit erklärt. Muss aber nicht.

Vielen Dank!
LG
 
Mit den Report-Parametern bist du glaube ich auf dem Holzweg. Parameter sind die Report-Konfiguration. Das sind starre Werte eher technischer Natur. Es sind keine Report-Inhalte. Implementieren/Anpassen musst du die Datenquelle - eine Klasse, die JRDataSource implementiert, und eine zugehörige Klasse mit statischer Fabrikmethode, die die Datenquelle erzeugt.

Für den Anfang reicht es aus, die letztgenannte Fabrikklasse zu schreiben, die entweder ein Array oder eine Collection von Objekten liefert. Das Ganze so einfach wie möglich, ohne REST. Im Report-Designer definierst du die (Test)Datenquelle dann als JRBeanArrayDataSource oder als JRBeanCollectionDataSource. Dabei sollst du den Namen der Fabrikklasse und die statische Methode angeben.

Code:
public class PersonFactory {

    public static class Person {
        public final String name;
        public final int alter;
        public Person(String name, int alter) { this.name = name; this.alter = alter; }
    }

    public static List<Person> createPersonen() {
        List<Person> personen = new ArrayList<>();
        personen.add(new Person("Karl", 22));
        personen.add(new Person("Lisa", 19));
        personen.add(new Person("Tao", 34));
        return personen;
    }
}

Damit würde ich erst einmal rumspielen. Wenn du weisst wie man Daten aus der Datenquelle ausliest und darstellt (Stichwort Bänder und Felder), kannst du deine eigentliche REST-Datenquelle plus Fabrik schreiben und einbinden, was dann nicht mehr so schwierig sein sollte.

Einen Report mit Java-Code generieren sieht vereinfacht so aus:
Code:
JRDataSource dataSource = new JRBeanCollectionDataSource(
    PersonFactory.createPersonen());
		JasperPrint 			document = JasperFillManager.fillReport(
    				getClass().getResourceAsStream("/personen.jasper"), 				null, dataSource);
JasperExportManager.			exportReportToPdfFile(
    document, "personen.pdf");
 
Zuletzt bearbeitet:
wahli schrieb:

Thx, aber wie ich auf REST zugreife hab ich schon ausprobiert ;) Die Schnittstelle steht schon, ich muss die nur benutzen, was nich so schwer is.

fhtagn schrieb:
Code:
public class PersonFactory {

    public static class Person {
        public final String name;
        public final int alter;
        public Person(String name, int alter) { this.name = name; this.alter = alter; }
    }

    public static List<Person> createPersonen() {
        List<Person> personen = new ArrayList<>();
        personen.add(new Person("Karl", 22));
        personen.add(new Person("Lisa", 19));
        personen.add(new Person("Tao", 34));
        return personen;
    }
}

Danke dir auch für dein Beispiel. Ich hab mal was ausprobiert und werde mal versuchen die Jar in iReport zu benutzen. Wenn ich mir da was anzeigen lassen kann geh ich weiter. Ich melde mich wieder bei Fortschritten und Problemen :)
 
Hallöle.

Mittlerweile hat sich einiges getan, mein Code klappt mit iReport und zeigt was an (abhängig vom Code den ich dauernd verändere :D)
Die Struktur ist bisher so:
  • DataSource (Konstruktor, next():boolean, getFieldValue():Object)
  • DataSourceFactory (klassisches Factory Pattern, nur generateDataSource():JRDataSource)
Der Rest im Projekt wird derzeit erstma net gebraucht und wird nur mit kompiliert.

Ich habe zwei Dinge, die mich gerade beschäftigen. Fülle ich in der Factory die DataSource mit Daten als Parameter für den Konstruktor und verarbeite sie dann in der DataSource Klasse geht alles.
Code:
public static JRDataSource generateDataSource(){
	HashMap<String,String> hashMap = new HashMap<String,String>();
	hashMap.put("Key1","Eins");
	hashMap.put("Key2","Zwei");
	return new DataSource(hashMap);
}
------
public DataSource(HashMap<String,String> map){
	this.data = map; 	//data ist private static HashMap nach selben Prinzip
}
Rufe ich in der Factory nur mit einem parameterlosen Standard-Konstruktor auf und füge die Daten dann im Konstruktor der DataSource Klasse hinzu bekomm ich auf einmal ne null Exception.
Code:
public static JRDataSource generateDataSource(){
	return new DataSource();
}
------
public DataSource(){
	data.put("Key1","Eins"); //data ist private static HashMap nach selben Prinzip
	data.put("Key2","Zwei");
}
Versteh ich net :D

Zweitens, gibt es einen Weg über iReport oder Jaspersoft Studio Parameter an die Datenbank zu übergeben, sprich ich habe verschiedene Datenholer definiert und übergebe der Jar quasi
- den Parameter "Datensatz 1" => "Eins", "Zwei", "Drei"
- den Parameter "Datensatz 2" => "Vier", "Fünf", "Sechs"?

Danke schonmal falls ihr mir helfen könnt und wisst was ich hier nicht verstehe.
 
Nicht so vorschnell posten! Einen kurzen Moment lang überlegt und du hättest die Frage nicht gestellt.

Code:
data = new HashMap<String,String>();
data.put("Key1","Eins");
	data.put("Key2","Zwei");
 
Oh...Stimmt ich muss das Ding ja initialisieren -.- Sorry...das hab ich wohl übersehen :stock: Dummer Anfängerfehler...
 
Nach einem brillianten Einfall eines Kollegen bin ich nun soweit, dass ich Retrofit (was ich vorher benutzte) überhaupt nicht mehr brauche und nun wesentlich einfacher an die Daten ran komme. Klappt soweit auch super.

Allerdings möchte ich noch, dass der Nutzer seine Credentials für die Basic Authentifizierung als auch eine Query in iReport angeben kann, die dann von der Jar genutzt werden. Das ist wie gesagt die Parameterübergabe durch Felder/Parameter von iReport/etc. Ich lese zwar dass das irgendwie gehen soll, aber kann nicht wirklich nachvollziehen wie. Weiß einer von euch da zufällig Bescheid?
Zur Query, da bin ich noch nicht ganz sicher ob das easy mit iReports Query Kram geht und ich da per JSON Query alles machen kann. Das hab ich noch nicht wirklich untersuchen können. Wenn von euch allerdings jemand sich da ebenfalls auskennt wären auch hier Ansätze und Beispiele gern gesehen :)

Danke für all die bisherige Hilfe bei meinen Fragen :)

LG
 
So, nachdem ich nun mehrfach diverse Seiten im Netz durchforstet habe denke ich, dass die Modifizierung der Custom JRDataSource durch einen eigenen JRQueryExecuter möglich ist. Ziel dabei ist das Auslesen bestimmter Parameter, daran die Modifizierung der JRDataSource, das entsprechende Anzeigen der zur Verfügung stehenden Felder durch den JRDataSourceProvider (Report Query in iReport) und dann das Anzeigen dieser Daten im Report.

Das Hauptproblem ist derzeit wirklich, wie ich bestimmte Werte zur Laufzeit in iReport angeben kann, die dann in der Bereitstellung der Daten berücksichtigt werden. In SQL wäre das ja nicht weiter tragisch, wenn man einfach nach dem Prinzip sagen würde
SELECT * FROM Datasource WHERE IP=... AND GROUP=... (wobei in iReport IP=... mit $!{IP} usw. ersetzt werden würde)

Da ich aber mit SQL wohl keine Möglichkeit habe weiß ich grad nicht wirklich wie es sonst gehen soll. Wenn einer von euch eine gewinnbringende Idee oder einen Ansatz haben sollte würdet ihr mir unglaublich helfen! Ich steck fest...

LG Nero
 
Zurück
Oben