BIRT-rapportering med Spring Boot

1. Introduktion

I denne vejledning vil vi integrere BIRT (Business Intelligence and Reporting Tools) med Spring Boot MVC for at servere statiske og dynamiske rapporter i HTML- og PDF-format.

2. Hvad er? BIRT?

BIRT er en open source-motor til at oprette datavisualiseringer der kan integreres i Java-webapplikationer.

Det er et softwareprojekt på højeste niveau inden for Eclipse Foundation og udnytter bidrag fra IBM og Innovent Solutions. Det blev startet og sponsoreret af Actuate i slutningen af ​​2004.

Rammen tillader oprettelse af rapporter integreret med en bred vifte af datakilder.

3. Maven-afhængigheder

BIRT har to hovedkomponenter: en visuel rapportdesigner til oprettelse af rapportdesignfiler og en runtime-komponent til fortolkning og gengivelse af disse designs.

I vores eksempel på webapplikation skal vi bruge begge oven på Spring Boot.

3.1. BIRT Framework-afhængigheder

Da vi er vant til at tænke i afhængighedsstyring, ville det første valg være at kigge efter BIRT i Maven Central.

Imidlertid, den seneste officielle version af det tilgængelige kernebibliotek er 4.6 fra 2016, mens vi på Eclipse-download-siden kan finde links til mindst to nyere versioner (strømmen er 4,8).

Hvis vi vælger at gå til den officielle build, er den nemmeste måde at få koden på at køre ved at downloade BIRT Report Engine-pakken, som er en komplet webapplikation, der også er nyttig til læring. Vi skal derefter kopiere dens lib mappe ind i vores projekt (ca. 68 MB i størrelse) og fortæl IDE at inkludere alle krukkerne i det.

Det siger sig selv, at ved hjælp af denne tilgang vi kan kun kompilere gennem IDE, da Maven ikke finder disse krukker, medmindre vi konfigurerer og installerer dem manuelt (mere end 100 filer!) i vores lokale repo.

Heldigvis, Innovent Solutions har besluttet at tage sagen i hænderne og offentliggjort sine egne builds på Maven Central af de nyeste BIRT-afhængigheder, hvilket er fantastisk, da det for os styrer alle de nødvendige afhængigheder.

Når man læser gennem kommentarer i onlinefora, er det uklart, om disse artefakter er produktionsklare, men Innovent Solutions arbejdede på projektet ved siden af ​​Eclipse-teamet siden starten, så vores projekt er afhængig af dem.

Inkludering af BIRT er nu meget let:

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

3.2. Spring Boot afhængigheder

Nu hvor BIRT er importeret til vores projekt, skal vi bare tilføje standard Spring Boot-afhængigheder i vores pom-fil.

Der er dog en faldgrube, fordi BIRT-krukken indeholder sin egen implementering af Slf4J, som ikke spiller godt med Logback og kaster en konfliktundtagelse under opstart.

Da vi ikke kan fjerne det fra krukken for at løse dette problem, vi er nødt til at udelukke Logback:

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

Nu er vi endelig klar til at starte!

4. BIRT-rapporter

I BIRT-rammen en rapport er en lang XML-konfigurationsfil, identificeret ved udvidelsen rptdesign.

Den fortæller motoren, hvad den skal tegne, og hvor, fra stilen på en titel op til de krævede egenskaber for at oprette forbindelse til en datakilde.

For en grundlæggende dynamisk rapport skal vi konfigurere tre ting:

  1. datakilden (i vores eksempel bruger vi en lokal CSV-fil, men det kan let være en databasetabel)
  2. de elementer, vi vil vise (diagrammer, tabeller osv.)
  3. sidedesignet

Rapporten er struktureret som en HTML-side med overskrift, brødtekst, sidefod, scripts og typografier.

Rammen giver et omfattende sæt komponenter at vælge imellem, inklusive integration til mainstream datakilder, layout, diagrammer og tabeller. Og vi kan udvide det til at tilføje vores egne!

Der er to måder at generere en rapportfil på: visuel eller programmatisk.

5. Formørkelsesrapportdesigneren

For at lette oprettelsen af ​​rapporter Eclipse-teamet byggede et værktøj til rapportdesign plugin til dets populære IDE.

Dette værktøj har en let træk-og-slip-grænseflade fra Palette til venstre, som automatisk åbner installationsvinduet for den nye komponent, vi tilføjer til siden. Vi kan også se alle tilgængelige tilpasninger for hver komponent ved at klikke på den på siden og derefter på Ejendomseditor knap (fremhævet på billedet nedenfor).

For at visualisere hele sidestrukturen i en trævisning skal vi bare klikke på Omrids knap.

Det Data Explorer fanen indeholder også de datakilder, der er defineret til vores rapport:

Eksempelrapporten, der vises på billedet, kan findes på stien /rapporter/csv_data_report.rptdesign

En anden fordel ved at gå til den visuelle designer er online-dokumentationen, der fokuserer mere på dette værktøj i stedet for den programmatiske tilgang.

Hvis vi allerede bruger Eclipse, er vi bare nødt til at installere BIRT Report Design-pluginnet, som inkluderer et foruddefineret perspektiv og den visuelle editor.

For de udviklere, der ikke bruger Eclipse i øjeblikket og ikke ønsker at skifte, der er en Eclipse Report Designer-pakke, som består af en bærbar Eclipse-installation med BIRT-plugin forudinstalleret.

Når rapportfilen er afsluttet, kan vi gemme den i vores projekt og gå tilbage til kodning i vores foretrukne miljø.

6. Den programmatiske tilgang

Det kan vi også designe en rapport med kun kode, men denne fremgangsmåde er meget sværere på grund af den dårlige dokumentation, der er tilgængelig, så vær forberedt på at grave i kildekode og onlinefora.

Også værd at overveje er, at alle de kedelige designdetaljer som størrelse, længde og gitterposition er meget lettere at håndtere ved hjælp af designeren.

For at bevise dette punkt er her et eksempel på, hvordan man definerer en simpel statisk side med et billede og en tekst:

DesignElementHandle element = fabrik.newSimpleMasterPage ("Page Master"); design.getMasterPages (). tilføj (element); GridHandle gitter = fabrik.newGridItem (null, 2, 1); design.getBody (). tilføj (gitter); grid.setWidth ("100%"); RowHandle row0 = (RowHandle) grid.getRows (). Get (0); ImageHandle image = factory.newImage (null); CellHandle celle = (CellHandle) række0.getCells (). Get (0); cell.getContent (). tilføj (billede); image.setURL ("\" // www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png \ ""); LabelHandle label = factory.newLabel (null); celle = (CellHandle) række0.getCells (). get (1); cell.getContent (). tilføj (label); label.setText ("Hej, Baeldung verden!");

Denne kode genererer en enkel (og grim) rapport:

Eksempelrapporten, der vises i billedet ovenfor, kan findes på denne sti: /rapporter/statisk_rapport.rptdesign.

Når vi har kodet, hvordan rapporten skal se ud, og hvilke data den skal vises, kan vi generere XML-filen ved at køre vores ReportDesignApplication klasse.

7. Tilslutning af en datakilde

Vi nævnte tidligere, at BIRT understøtter mange forskellige datakilder.

Til vores eksempelprojekt brugte vi en simpel CSV-fil med tre poster. Det kan findes i rapporter mappe og består af tre enkle datarækker plus overskrifter:

Studerende, matematik, geografi, historieregning, 10,3,8 Tom, 5,6,5 Anne, 7, 4,9

7.1. Konfiguration af datakilden

For at lade BIRT bruge vores fil (eller enhver anden type kilde), vi er nødt til at konfigurere en Datakilde.

Til vores fil oprettede vi en Flad fil datakilde med rapportdesigneren, alt sammen i få trin:

  1. Åbn designerperspektivet og se på omrids til højre.
  2. Højreklik på Data kilder ikon.
  3. Vælg den ønskede kildetype (i vores tilfælde den flade filkilde).
  4. Vi kan nu vælge enten at indlæse en hel mappe eller kun en fil. Vi brugte den anden mulighed (hvis vores datafil er i CSV-format, vil vi sørge for at bruge den første linje som kolonnenavnindikator).
  5. Test forbindelsen for at sikre, at stien er korrekt.

Vi vedhæftede nogle billeder for at vise hvert trin:

7.2. Datasættet

Datakilden er klar, men vi skal stadig definere vores Datasæt, som er de faktiske data, der vises i vores rapport:

  1. Åbn designerperspektivet og se på omrids til højre.
  2. Højreklik på Datasæt ikon.
  3. Vælg den ønskede Datakilde og typen (i vores tilfælde er der kun én type).
  4. Den næste skærm afhænger af typen af ​​datakilde og datasæt, vi er valgt: i vores tilfælde ser vi en side, hvor vi kan vælge de kolonner, der skal medtages.
  5. Når opsætningen er afsluttet, kan vi til enhver tid åbne konfigurationen ved at dobbeltklikke på vores datasæt.
  6. I Outputkolonner, kan vi indstille den rigtige type af de viste data.
  7. Vi kan derefter se på en forhåndsvisning ved at klikke på Vis resultater.

Igen nogle billeder for at afklare disse trin:

7.3. Andre datakildetyper

Som nævnt i trin 4 i Datasæt konfiguration, kan de tilgængelige indstillinger ændre sig afhængigt af Datakilde henvist.

For vores CSV-fil giver BIRT muligheder relateret til hvilke kolonner, der skal vises, datatypen, og hvis vi vil indlæse hele filen. På den anden side, hvis vi havde en JDBC-datakilde, er vi muligvis nødt til at skrive en SQL-forespørgsel eller en lagret procedure.

Fra Datasæt menu, Vi kan også deltage i to eller flere datasæt i et nyt datasæt.

8. Afgivelse af rapporten

Når rapportfilen er klar, skal vi sende den til motoren til gengivelse. For at gøre dette er der et par ting at implementere.

8.1. Initialisering af motoren

Det ReportEngine klasse, som fortolker designfilerne og genererer det endelige resultat, er en del af BIRT runtime-biblioteket.

Det bruger en masse hjælpere og opgaver til at udføre jobbet, hvilket gør det ret ressourceintensivt:

Billedkilde: Eclipse BIRT-dokumentation

Der er en betydelig omkostning forbundet med at oprette en motorinstans, primært på grund af omkostningerne ved indlæsning af udvidelser. Derfor, vi skulle bare oprette en ReportEngine forekomst og brug den til at køre flere rapporter.

Rapportmotoren oprettes via en fabrik leveret af Platform. Før vi opretter motoren, skal vi starte Platform, der indlæser de relevante plug-ins:

@PostConstruct beskyttet ugyld initialiseret () kaster BirtException {EngineConfig config = ny EngineConfig (); config.getAppContext (). put ("spring", this.context); Platform.startup (config); IReportEngineFactory fabrik = (IReportEngineFactory) Platform .createFactoryObject (IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY); birtEngine = factory.createReportEngine (config); imageFolder = System.getProperty ("user.dir") + File.separatorChar + rapporterPath + imagesPath; loadReports (); }

Når vi ikke har brug for det mere, kan vi ødelægge det:

@ Overstyr offentlig tomrum ødelægge () {birtEngine.destroy (); Platform.shutdown (); }

8.2. Implementering af outputformatet

BIRT understøtter allerede flere outputformater:HTML, PDF, PPT og ODT, for at nævne et par stykker.

Til prøveprojektet implementerede vi to af dem med metoderne genererePDFReport og generereHTMLReport.

De adskiller sig lidt afhængigt af de specifikke behov, der kræves, såsom outputformat og billedhåndterere.

Faktisk integrerer PDF-filer billeder sammen med tekst, mens HTML-rapporter skal generere dem og / eller linke dem.

Dermed, PDF-gengivelsesfunktionen er ret ligetil:

privat tomrum generererPDFReport (IReportRunnable rapport, HttpServletResponse svar, HttpServletRequest anmodning) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); respons.setContentType (birtEngine.getMIMEType ("pdf")); IRenderOption muligheder = ny RenderOption (); PDFRenderOption pdfRenderOption = ny PDFRenderOption (valgmuligheder); pdfRenderOption.setOutputFormat ("pdf"); runAndRenderTask.setRenderOption (pdfRenderOption); runAndRenderTask.getAppContext (). put (EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, anmodning); prøv {pdfRenderOption.setOutputStream (respons.getOutputStream ()); runAndRenderTask.run (); } fange (Undtagelse e) {smide ny RuntimeException (e.getMessage (), e); } endelig {runAndRenderTask.close (); }}

Mens HTML-gengivelsesfunktionen har brug for flere indstillinger:

privat tomrum generererHTMLReport (IReportRunnable rapport, HttpServletResponse svar, HttpServletRequest anmodning) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); respons.setContentType (birtEngine.getMIMEType ("html")); IRenderOption muligheder = ny RenderOption (); HTMLRenderOption htmlOptions = ny HTMLRenderOption (valgmuligheder); htmlOptions.setOutputFormat ("html"); htmlOptions.setBaseImageURL ("/" + rapporterPath + imagesPath); htmlOptions.setImageDirectory (imageFolder); htmlOptions.setImageHandler (htmlImageHandler); runAndRenderTask.setRenderOption (htmlOptions); runAndRenderTask.getAppContext (). put (EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, anmodning); prøv {htmlOptions.setOutputStream (respons.getOutputStream ()); runAndRenderTask.run (); } fange (Undtagelse e) {smide ny RuntimeException (e.getMessage (), e); } endelig {runAndRenderTask.close (); }}

Mest bemærkelsesværdige, vi indstiller HTMLServerImageHandler i stedet for at forlade standardhandleren. Denne lille forskel har stor indflydelse på den genererede img tag:

  • standardhandleren forbinder img tag til filsystemets sti, blokeret for sikkerhed af mange browsere
  • det HTMLServerImageHandler links til serverens URL

Med setImageDirectory metode, specificerer vi, hvor motoren vil gemme den genererede billedfil.

Som standard genererer handleren en ny fil ved hver anmodning, så det vi kunne tilføje et cachelag eller en sletningspolitik.

8.3. Udgivelse af billederne

I HTML-rapportsagen er billedfiler eksterne, så de skal være tilgængelige på serverstien.

I ovenstående kode med setBaseImageURL metode, fortæller vi motoren, hvilken relativ sti der skal bruges i img tag-link, så vi skal sørge for, at stien faktisk er tilgængelig!

Af denne grund i vores ReportEngineApplication, vi konfigurerede Spring til at offentliggøre billeder folder:

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

Uanset hvilken vej vi vælger, er vi nødt til at sikre, at den samme sti bruges her og i htmlValg af det forrige uddrag, ellers kan vores rapport ikke vise billeder.

9. Visning af rapporten

Den sidste komponent, der er nødvendig for at gøre vores ansøgning klar, er en Controller for at returnere det gengivne resultat:

@RequestMapping (metode = RequestMethod.GET, værdi = "/ rapport / {navn}") @ResponseBody offentlig tomrum generereFullReport (HttpServletResponse svar, HttpServletRequest anmodning, @PathVariable ("navn") String navn, @RequestParam ("output") String output) kaster EngineException, IOException {OutputType format = OutputType.from (output); reportService.generateMainReport (navn, format, svar, anmodning); }

Med produktion parameter, kan vi lade brugeren vælge det ønskede format - HTML eller PDF.

10. Test af rapporten

Vi kan starte applikationen ved at køre ReportEngineApplication klasse.

Under opstart, BirtReportService klasse vil indlæse alle rapporter, der findes i / rapporter folder.

For at se vores rapporter i aktion skal vi bare pege vores browser på:

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

Her er hvordan csv_data_report rapporten ser ud:

For at genindlæse en rapport efter ændring af designfilen peger vi bare vores browser på / rapport / genindlæs.

11. Konklusion

I denne artikel integrerede vi BIRT med Spring Boot og udforskede faldgruber og udfordringer, men også dens styrke og fleksibilitet.

Kildekoden til artiklen er tilgængelig på GitHub.