BIRT-rapportage met Spring Boot

1. Inleiding

In deze tutorial gaan we BIRT (Business Intelligence and Reporting Tools) integreren met Spring Boot MVC om statische en dynamische rapporten in HTML- en PDF-indeling te leveren.

2. Wat is VOGEL?

BIRT is een open source-engine om datavisualisaties te maken die kunnen worden geïntegreerd in Java-webapplicaties.

Het is een softwareproject van het hoogste niveau binnen de Eclipse Foundation en maakt gebruik van bijdragen van IBM en Innovent Solutions. Het is eind 2004 gestart en gesponsord door Actuate.

Het framework maakt het mogelijk om rapporten te maken die zijn geïntegreerd met een breed scala aan gegevensbronnen.

3. Maven afhankelijkheden

BIRT heeft twee hoofdcomponenten: een visuele rapportontwerper om rapportontwerpbestanden te maken, en een runtime-component voor het interpreteren en weergeven van die ontwerpen.

In onze voorbeeldwebtoepassing gaan we beide gebruiken bovenop Spring Boot.

3.1. Afhankelijkheden van het BIRT-raamwerk

Zoals we gewend zijn te denken in termen van afhankelijkheidsbeheer, zou de eerste keuze zijn om te zoeken naar BIRT in Maven Central.

Echter, de nieuwste officiële versie van de kernbibliotheek die beschikbaar is, is 4.6 uit 2016, terwijl we op de Eclipse-downloadpagina links kunnen vinden voor ten minste twee nieuwere versies (de stroom is 4,8).

Als we ervoor kiezen om voor de officiële build te gaan, is de gemakkelijkste manier om de code aan de praat te krijgen, het downloaden van het BIRT Report Engine-pakket, een complete webtoepassing die ook handig is om te leren. We moeten dan het lib map in ons project (ongeveer 68 MB groot) en vertel de IDE om alle potten erin op te nemen.

Het spreekt voor zich dat met deze aanpak we kunnen alleen compileren via de IDE, aangezien Maven die potten niet zal vinden tenzij we ze handmatig configureren en installeren (meer dan 100 bestanden!) in onze lokale opslagplaats.

Gelukkig, Innovent Solutions heeft besloten het heft in handen te nemen en heeft op Maven Central zijn eigen builds gepubliceerd van de nieuwste BIRT-afhankelijkheden, wat geweldig is, omdat het voor ons alle benodigde afhankelijkheden beheert.

Bij het lezen van commentaren op online forums is het onduidelijk of deze artefacten productieklaar zijn, maar Innovent Solutions heeft sinds het begin naast het Eclipse-team aan het project gewerkt, dus ons project vertrouwt erop.

BIRT opnemen is nu heel eenvoudig:

 com.innoventsolutions.birt.runtime org.eclipse.birt.runtime_4.8.0-20180626 4.8.0 

3.2. Afhankelijkheden van Spring Boot

Nu BIRT in ons project is geïmporteerd, hoeven we alleen de standaard Spring Boot-afhankelijkheden in ons pom-bestand toe te voegen.

Er is echter een valkuil, want de BIRT-pot bevat zijn eigen implementatie van Slf4J, wat niet leuk is met Log terug en genereert een conflictuitzondering tijdens het opstarten.

Omdat we het niet uit de pot kunnen verwijderen, om dit probleem op te lossen, we moeten Logback uitsluiten:

 org.springframework.boot spring-boot-starter-logging ch.qos.logback logback-classic 

Nu zijn we eindelijk klaar om te beginnen!

4. BIRT-rapporten

In het BIRT-kader, een rapport is een lang XML-configuratiebestand, geïdentificeerd door de extensie rptdesign.

Het vertelt de Engine wat hij moet tekenen en waar, van de stijl van een titel tot de vereiste eigenschappen om verbinding te maken met een gegevensbron.

Voor een eenvoudig dynamisch rapport moeten we drie dingen configureren:

  1. de gegevensbron (in ons voorbeeld gebruiken we een lokaal CSV-bestand, maar het kan gemakkelijk een databasetabel zijn)
  2. de elementen die we willen weergeven (grafieken, tabellen, enz.)
  3. het pagina-ontwerp

Het rapport is gestructureerd als een HTML-pagina, met koptekst, hoofdtekst, voettekst, scripts en stijlen.

Het framework biedt een uitgebreide set componenten waaruit u kant-en-klaar kunt kiezen, inclusief integratie met reguliere gegevensbronnen, lay-outs, grafieken en tabellen. En we kunnen het uitbreiden om onze eigen toe te voegen!

Er zijn twee manieren om een ​​rapportbestand te genereren: visueel of programmatisch.

5. De Eclipse Report Designer

Om het maken van rapporten te vergemakkelijken, het Eclipse-team heeft een tool voor het ontwerpen van rapporten gebouwd plug-in voor zijn populaire IDE.

Deze tool heeft een eenvoudige drag & drop-interface van de Palet aan de linkerkant, die automatisch het setup-venster opent voor de nieuwe component die we aan de pagina toevoegen. We kunnen ook alle beschikbare aanpassingen voor elk onderdeel zien door erop te klikken op de pagina en vervolgens op het Eigenschappen-editor knop (gemarkeerd in de afbeelding hieronder).

Om de volledige paginastructuur in een boomweergave te visualiseren, hoeven we alleen maar op de Overzicht knop.

De Gegevensverkenner Het tabblad bevat ook de gegevensbronnen die voor ons rapport zijn gedefinieerd:

Het voorbeeldrapport dat in de afbeelding wordt weergegeven, is te vinden op het pad /reports/csv_data_report.rptdesign

Een ander voordeel van voor de visual designer gaan is de online documentatie, die meer gericht is op deze tool in plaats van op de programmatische aanpak.

Als we Eclipse al gebruiken, hoeven we alleen de BIRT Report Design-plug-in te installeren, die een vooraf gedefinieerd perspectief en de visuele editor bevat.

Voor die ontwikkelaars die momenteel geen gebruik maken van Eclipse en wil niet overschakelen, er is een Eclipse Report Designer-pakket, die bestaat uit een draagbare Eclipse-installatie met de BIRT-plug-in vooraf geïnstalleerd.

Zodra het rapportbestand is voltooid, kunnen we het opslaan in ons project en teruggaan naar codering in onze voorkeursomgeving.

6. De programmatische aanpak

We kunnen ook ontwerp een rapport met alleen code, maar deze benadering is een stuk moeilijker vanwege de slechte documentatie die beschikbaar is, dus wees voorbereid om in de broncode en online forums te duiken.

Ook het overwegen waard is dat alle vervelende ontwerpdetails zoals grootte, lengte en rasterpositie zijn een stuk gemakkelijker om mee om te gaan met behulp van de ontwerper.

Om dit punt te bewijzen, volgt hier een voorbeeld van hoe u een eenvoudige statische pagina met een afbeelding en een tekst definieert:

DesignElementHandle element = factory.newSimpleMasterPage ("Page Master"); design.getMasterPages (). add (element); GridHandle grid = factory.newGridItem (null, 2, 1); design.getBody (). add (grid); grid.setWidth ("100%"); RowHandle row0 = (RowHandle) grid.getRows (). Get (0); ImageHandle afbeelding = factory.newImage (null); CellHandle cell = (CellHandle) row0.getCells (). Get (0); cell.getContent (). add (afbeelding); image.setURL ("\" // www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png \ ""); LabelHandle label = factory.newLabel (null); cell = (CellHandle) row0.getCells (). get (1); cell.getContent (). add (label); label.setText ("Hallo, Baeldung-wereld!");

Deze code genereert een eenvoudig (en lelijk) rapport:

Het voorbeeldrapport dat in de bovenstaande afbeelding wordt weergegeven, is te vinden op dit pad: /reports/static_report.rptdesign.

Zodra we hebben gecodeerd hoe het rapport eruit moet zien en welke gegevens het moet weergeven, kunnen we het XML-bestand genereren door onze ReportDesignApplication klasse.

7. Een gegevensbron bijvoegen

We zeiden eerder dat BIRT veel verschillende gegevensbronnen ondersteunt.

Voor ons voorbeeldproject hebben we een eenvoudig CSV-bestand met drie vermeldingen gebruikt. Het is te vinden in het rapporten map en bestaat uit drie eenvoudige rijen met gegevens, plus kopteksten:

Student, wiskunde, aardrijkskunde, geschiedenisrekening, 10,3,8 Tom, 5,6,5 Anne, 7, 4,9

7.1. De gegevensbron configureren

Om BIRT ons bestand (of een ander type bron) te laten gebruiken, we moeten een Databron.

Voor ons bestand hebben we een Gegevensbron plat bestand met de rapportontwerper, alles in slechts een paar stappen:

  1. Open het ontwerperperspectief en kijk naar het schets aan de rechterkant.
  2. Klik met de rechtermuisknop op het Data bronnen icoon.
  3. Selecteer het gewenste brontype (in ons geval de platte bestandsbron).
  4. We kunnen er nu voor kiezen om een ​​hele map of slechts één bestand te laden. We hebben de tweede optie gebruikt (als ons gegevensbestand in CSV-indeling is, willen we ervoor zorgen dat we de eerste regel gebruiken als kolomnaamindicator).
  5. Test de verbinding om er zeker van te zijn dat het pad correct is.

We hebben enkele foto's bijgevoegd om elke stap te laten zien:

7.2. De dataset

De gegevensbron is klaar, maar we moeten onze Dataset, dat zijn de feitelijke gegevens die in ons rapport worden weergegeven:

  1. Open het ontwerperperspectief en kijk naar het schets aan de rechterkant.
  2. Klik met de rechtermuisknop op het Datasets icoon.
  3. Selecteer het gewenste Databron en het type (in ons geval is er maar één type).
  4. Het volgende scherm hangt af van het type gegevensbron en dataset dat we hebben geselecteerd: in ons geval zien we een pagina waarop we de kolommen kunnen selecteren die we willen opnemen.
  5. Zodra de installatie is voltooid, kunnen we de configuratie op elk moment openen door te dubbelklikken op onze dataset.
  6. In Uitvoerkolommen, kunnen we het juiste type van de weergegeven gegevens instellen.
  7. We kunnen dan een preview bekijken door op te klikken Voorbeeld van resultaten.

Nogmaals, enkele afbeeldingen om deze stappen te verduidelijken:

7.3. Andere typen gegevensbronnen

Zoals vermeld in stap 4 van het Dataset configuratie, kunnen de beschikbare opties veranderen afhankelijk van de Databron verwezen.

Voor ons CSV-bestand geeft BIRT opties met betrekking tot welke kolommen moeten worden weergegeven, het gegevenstype en of we het volledige bestand willen laden. Aan de andere kant, als we een JDBC-gegevensbron hadden, moeten we mogelijk een SQL-query of een opgeslagen procedure schrijven.

Van de Datasets menu, we kunnen ook twee of meer datasets samenvoegen in een nieuwe dataset.

8. Rendering van het rapport

Zodra het rapportbestand klaar is, moeten we het doorgeven aan de engine voor weergave. Om dit te doen, zijn er een paar dingen die u moet implementeren.

8.1. Initialiseren van de engine

De ReportEngine class, die de ontwerpbestanden interpreteert en het eindresultaat genereert, maakt deel uit van de BIRT-runtimebibliotheek.

Het gebruikt een heleboel helpers en taken om het werk te doen, waardoor het behoorlijk arbeidsintensief is:

Afbeeldingsbron: Eclipse BIRT-documentatie

Er zijn aanzienlijke kosten verbonden aan het maken van een engine-instantie, voornamelijk vanwege de kosten van het laden van uitbreidingen. Daarom we zouden er maar één moeten maken ReportEngine instantie en gebruik het om meerdere rapporten uit te voeren.

De rapportengine is gemaakt via een fabriek die wordt geleverd door de Platform. Voordat we de motor maken, moeten we het Platform, die de juiste plug-ins zal laden:

@ PostConstruct protected void initialize () gooit BirtException {EngineConfig config = new EngineConfig (); config.getAppContext (). put ("spring", this.context); Platform.startup (config); IReportEngineFactory factory = (IReportEngineFactory) Platform .createFactoryObject (IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY); birtEngine = factory.createReportEngine (config); imageFolder = System.getProperty ("user.dir") + File.separatorChar + reportsPath + imagesPath; loadReports (); }

Als we het niet meer nodig hebben, kunnen we het vernietigen:

@Override public void destroy () {birtEngine.destroy (); Platform.shutdown (); }

8.2. Implementatie van het uitvoerformaat

BIRT ondersteunt al meerdere uitvoerformaten:HTML, PDF, PPT en ODT, om er een paar te noemen.

Voor het voorbeeldproject hebben we er twee geïmplementeerd met de methoden genereerPDFReport en GenereerHTMLReport.

Ze verschillen enigszins, afhankelijk van de specifieke eigenschappen die nodig zijn, zoals uitvoerformaat en afbeeldingshandlers.

In feite sluiten pdf's afbeeldingen samen met tekst in, terwijl HTML-rapporten ze moeten genereren en / of linken.

Dus, de functie voor het renderen van pdf's is vrij eenvoudig:

privé ongeldig genererenPDFReport (IReportRunnable-rapport, HttpServletResponse-antwoord, HttpServletRequest-verzoek) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); response.setContentType (birtEngine.getMIMEType ("pdf")); IRenderOption-opties = nieuwe RenderOption (); PDFRenderOption pdfRenderOption = nieuwe PDFRenderOption (opties); pdfRenderOption.setOutputFormat ("pdf"); runAndRenderTask.setRenderOption (pdfRenderOption); runAndRenderTask.getAppContext (). put (EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, verzoek); probeer {pdfRenderOption.setOutputStream (response.getOutputStream ()); runAndRenderTask.run (); } catch (uitzondering e) {gooi nieuwe RuntimeException (e.getMessage (), e); } eindelijk {runAndRenderTask.close (); }}

Hoewel de HTML-weergavefunctie meer instellingen nodig heeft:

private void generationHTMLReport (IReportRunnable-rapport, HttpServletResponse-reactie, HttpServletRequest-verzoek) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); response.setContentType (birtEngine.getMIMEType ("html")); IRenderOption-opties = nieuwe RenderOption (); HTMLRenderOption htmlOptions = nieuwe HTMLRenderOption (opties); htmlOptions.setOutputFormat ("html"); htmlOptions.setBaseImageURL ("/" + reportsPath + imagesPath); htmlOptions.setImageDirectory (imageFolder); htmlOptions.setImageHandler (htmlImageHandler); runAndRenderTask.setRenderOption (htmlOptions); runAndRenderTask.getAppContext (). put (EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, verzoek); probeer {htmlOptions.setOutputStream (response.getOutputStream ()); runAndRenderTask.run (); } catch (uitzondering e) {gooi nieuwe RuntimeException (e.getMessage (), e); } eindelijk {runAndRenderTask.close (); }}

Het meest opmerkelijk, we stellen de HTMLServerImageHandler in plaats van de standaard handler te verlaten. Dit kleine verschil heeft een grote impact op het gegenereerde img label:

  • de standaard handler koppelt de img tag naar het bestandssysteempad, geblokkeerd voor veiligheid door veel browsers
  • de HTMLServerImageHandler links naar de server-URL

Met de setImageDirectory methode specificeren we waar de engine het gegenereerde afbeeldingsbestand zal opslaan.

Standaard genereert de handler bij elk verzoek een nieuw bestand, dus we zouden een caching-laag of een verwijderingsbeleid kunnen toevoegen.

8.3. Publiceren van de afbeeldingen

In het geval van een HTML-rapport zijn afbeeldingsbestanden extern, dus ze moeten toegankelijk zijn via het serverpad.

In de bovenstaande code, met de setBaseImageURL methode, vertellen we de engine welk relatief pad moet worden gebruikt in de img tag-link, dus we moeten ervoor zorgen dat het pad daadwerkelijk toegankelijk is!

Om deze reden, in onze ReportEngineApplicationhebben we Spring geconfigureerd om het afbeeldingen map:

@SpringBootApplication @EnableWebMvc openbare klasse ReportEngineApplication implementeert WebMvcConfigurer {@Value ("$ {reports.relative.path}") private String reportsPath; @Value ("$ {images.relative.path}") private String imagesPath; ... @Override public void addResourceHandlers (ResourceHandlerRegistry-register) {registry .addResourceHandler (reportsPath + imagesPath + "/ **") .addResourceLocations ("file: ///" + System.getProperty ("user.dir") + " / "+ reportsPath + imagesPath); }}

Welk pad we ook kiezen, we moeten ervoor zorgen dat hetzelfde pad hier en in het htmlOptions van het vorige fragment, anders kan ons rapport geen afbeeldingen weergeven.

9. Het rapport weergeven

Het laatste onderdeel dat nodig is om onze applicatie gereed te maken, is een Controller om het weergegeven resultaat te retourneren:

@RequestMapping (method = RequestMethod.GET, value = "/ report / {name}") @ResponseBody public void generationFullReport (HttpServletResponse response, HttpServletRequest request, @PathVariable ("name") String name, @RequestParam ("output") String output) gooit EngineException, IOException {OutputType format = OutputType.from (output); reportService.generateMainReport (naam, formaat, antwoord, verzoek); }

Met de output parameter, kunnen we de gebruiker het gewenste formaat laten kiezen - HTML of PDF.

10. Testen van het rapport

We kunnen de applicatie starten door het ReportEngineApplication klasse.

Tijdens het opstarten is het BirtReportService class laadt alle rapporten die in het / rapporten map.

Om onze rapporten in actie te zien, hoeven we onze browser alleen maar te richten op:

  • / report / csv_data_report? output = pdf
  • / report / csv_data_report? output = html
  • / report / static_report? output = pdf
  • / report / static_report? output = html

Hier is hoe de csv_data_report rapport ziet eruit:

Om een ​​rapport opnieuw te laden na het wijzigen van het ontwerpbestand, richten we onze browser gewoon op / report / herladen.

11. Conclusie

In dit artikel hebben we BIRT geïntegreerd met Spring Boot, waarbij we de valkuilen en uitdagingen verkenden, maar ook de kracht en flexibiliteit ervan.

De broncode voor het artikel is beschikbaar op GitHub.