BIRT-rapportering med vårstøvel

1. Introduksjon

I denne opplæringen skal vi integrere BIRT (Business Intelligence and Reporting Tools) med Spring Boot MVC, for å servere statiske og dynamiske rapporter i HTML- og PDF-format.

2. Hva er? BIRT?

BIRT er en open source-motor for å lage datavisualiseringer som kan integreres i Java-webapplikasjoner.

Det er et programvareprosjekt på toppnivå innen Eclipse Foundation og utnytter bidrag fra IBM og Innovent Solutions. Det ble startet og sponset av Actuate i slutten av 2004.

Rammeverket tillater å lage rapporter integrert med et bredt spekter av datakilder.

3. Maven-avhengigheter

BIRT har to hovedkomponenter: en visuell rapportdesigner for å lage rapportdesignfiler og en kjøretidskomponent for å tolke og gjengi disse designene.

I vårt eksempel på webapplikasjon skal vi bruke begge på toppen av Spring Boot.

3.1. BIRT Framework Avhengigheter

Som vi er vant til å tenke på avhengighetsstyring, vil førstevalget være å se etter BIRT i Maven Central.

Derimot, den siste offisielle versjonen av kjernebiblioteket som er tilgjengelig, er 4.6 fra 2016, mens vi er på Eclipse-nedlastingssiden, kan vi finne lenker til minst to nyere versjoner (strømmen er 4,8).

Hvis vi velger å gå for den offisielle versjonen, er den enkleste måten å ha koden i gang, å laste ned BIRT Report Engine-pakken, som er en komplett webapplikasjon som også er nyttig for læring. Vi må da kopiere den lib mappen inn i prosjektet vårt (ca. 68 MB i størrelse) og fortell IDE å ta med alle glassene i den.

Det sier seg selv at ved å bruke denne tilnærmingen, vi kan bare kompilere gjennom IDE, ettersom Maven ikke finner disse glassene med mindre vi konfigurerer og installerer dem manuelt (mer enn 100 filer!) i vårt lokale repo.

Heldigvis, Innovent Solutions har bestemt seg for å ta saken i hendene og publiserte sine egne bygg på Maven Central av de siste BIRT-avhengighetene, noe som er flott, da det for oss håndterer alle nødvendige avhengigheter.

Når du leser gjennom kommentarer i nettfora, er det uklart om disse gjenstandene er produksjonsklare, men Innovent Solutions jobbet med prosjektet ved siden av Eclipse-teamet siden starten, så prosjektet vårt er avhengig av dem.

Inkludering av BIRT er nå veldig enkelt:

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

3.2. Avhengighet av vårstøvler

Nå som BIRT er importert til prosjektet vårt, trenger vi bare å legge til standard Spring Boot-avhengigheter i pom-filen.

Det er imidlertid en fallgruve fordi BIRT-krukken inneholder sin egen implementering av Slf4J, som ikke leker bra med Tilbakekobling og kaster et konflikt unntak under oppstart.

Siden vi ikke kan fjerne den fra glasset, for å løse dette problemet, vi må ekskludere Logback:

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

Nå er vi endelig klare til å starte!

4. BIRT-rapporter

I BIRT-rammeverket, en rapport er en lang XML-konfigurasjonsfil, identifisert av utvidelsen rptdesign.

Den forteller motoren hva den skal tegne og hvor, fra stilen til en tittel til de nødvendige egenskapene for å koble til en datakilde.

For en grunnleggende dynamisk rapport må vi konfigurere tre ting:

  1. datakilden (i vårt eksempel bruker vi en lokal CSV-fil, men det kan lett være en databasetabell)
  2. elementene vi vil vise (diagrammer, tabeller osv.)
  3. sideutformingen

Rapporten er strukturert som en HTML-side, med topptekst, brødtekst, bunntekst, skript og stiler.

Rammeverket gir et omfattende sett med komponenter å velge mellom, inkludert integrering til vanlige datakilder, oppsett, diagrammer og tabeller. Og vi kan utvide det for å legge til vårt eget!

Det er to måter å generere en rapportfil på: visuell eller programmatisk.

5. Formørkelsesrapportdesigneren

For å gjøre det lettere å lage rapporter, Eclipse-teamet bygget et rapportdesignverktøy plugin for sin populære IDE.

Dette verktøyet har et enkelt dra-og-slipp-grensesnitt fra Palett til venstre, som automatisk åpner oppsettvinduet for den nye komponenten vi legger til på siden. Vi kan også se alle tilgjengelige tilpasninger for hver komponent ved å klikke på den på siden og deretter på Eiendomsredaktør -knappen (fremhevet i bildet nedenfor).

For å visualisere hele sidestrukturen i en trevisning, trenger vi bare å klikke på Disposisjon knapp.

De Data Explorer fanen inneholder også datakildene som er definert for vår rapport:

Eksempelrapporten som vises på bildet, finner du på stien /reports/csv_data_report.rptdesign

En annen fordel med å gå for den visuelle designeren er den elektroniske dokumentasjonen, som fokuserer mer på dette verktøyet i stedet for den programmatiske tilnærmingen.

Hvis vi allerede bruker Eclipse, trenger vi bare å installere pluginet BIRT Report Design, som inkluderer et forhåndsdefinert perspektiv og den visuelle redaktøren.

For de utviklerne som for øyeblikket ikke bruker Eclipse og ikke vil bytte, det er en Eclipse Report Designer-pakke, som består av en bærbar formørkelsesinstallasjon med BIRT-plugin forhåndsinstallert.

Når rapportfilen er ferdig, kan vi lagre den i prosjektet vårt og gå tilbake til koding i vårt foretrukne miljø.

6. Den programmatiske tilnærmingen

Vi kan også utforme en rapport med kun kode, men denne tilnærmingen er mye vanskeligere på grunn av den dårlige dokumentasjonen som er tilgjengelig, så vær forberedt på å grave i kildekoden og nettfora.

Også verdt å vurdere er at alle kjedelige designdetaljer som størrelse, lengde og rutenettposisjon er mye lettere å håndtere med designeren.

For å bevise dette punktet, her er et eksempel på hvordan du definerer en enkel statisk side med et bilde og en tekst:

DesignElementHandle element = fabrikk.newSimpleMasterPage ("Page Master"); design.getMasterPages (). legg til (element); GridHandle grid = fabrikk.newGridItem (null, 2, 1); design.getBody (). legg til (rutenett); grid.setWidth ("100%"); RowHandle row0 = (RowHandle) grid.getRows (). Get (0); ImageHandle image = factory.newImage (null); CellHandle cell = (CellHandle) row0.getCells (). Get (0); cell.getContent (). legg til (bilde); image.setURL ("\" // www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png \ ""); LabelHandle label = factory.newLabel (null); celle = (CellHandle) rad0.getCells (). få (1); cell.getContent (). legg til (etikett); label.setText ("Hei, Baeldung verden!");

Denne koden vil generere en enkel (og stygg) rapport:

Eksempelrapporten som vises i bildet ovenfor, finner du på denne banen: /rapporter/statisk_rapport.rptdesign.

Når vi har kodet hvordan rapporten skal se ut og hvilke data den skal vises, kan vi generere XML-filen ved å kjøre vår ReportDesignApplication klasse.

7. Feste en datakilde

Vi nevnte tidligere at BIRT støtter mange forskjellige datakilder.

For vårt eksempelprosjekt brukte vi en enkel CSV-fil med tre oppføringer. Det finnes i rapporter mappen og består av tre enkle rader med data, pluss overskrifter:

Student, matematikk, geografi, historieutkast, 10,3,8 Tom, 5,6,5 Anne, 7, 4,9

7.1. Konfigurere datakilden

For å la BIRT bruke filen vår (eller andre kilder), vi må konfigurere en Datakilde.

For filen vår opprettet vi en Flat fildatakilde med rapportdesigneren, alt i bare noen få trinn:

  1. Åpne designerperspektivet og se på disposisjon til høyre.
  2. Høyreklikk på Datakilder ikon.
  3. Velg ønsket kildetype (i vårt tilfelle den flate filkilden).
  4. Vi kan nå velge å laste inn en hel mappe eller bare en fil. Vi brukte det andre alternativet (hvis datafilen vår er i CSV-format, vil vi sørge for å bruke den første linjen som kolonnenavnindikator).
  5. Test tilkoblingen for å sikre at stien er riktig.

Vi la ved noen bilder for å vise hvert trinn:

7.2. Datasettet

Datakilden er klar, men vi må fortsatt definere vår Datasett, som er de faktiske dataene som vises i vår rapport:

  1. Åpne designerperspektivet og se på disposisjon til høyre.
  2. Høyreklikk på Datasett ikon.
  3. Velg ønsket Datakilde og typen (i vårt tilfelle er det bare en type).
  4. Det neste skjermbildet avhenger av typen datakilde og datasett vi har valgt: i vårt tilfelle ser vi en side der vi kan velge kolonnene som skal inkluderes.
  5. Når installasjonen er fullført, kan vi når som helst åpne konfigurasjonen ved å dobbeltklikke på datasettet vårt.
  6. I Utdatakolonner, kan vi angi riktig type data som vises.
  7. Vi kan deretter se på en forhåndsvisning ved å klikke på Forhåndsvisning av resultater.

Igjen, noen bilder for å avklare disse trinnene:

7.3. Andre datakildetyper

Som nevnt i trinn 4 i Datasett konfigurasjon, kan alternativene som er tilgjengelige, endres avhengig av Datakilde henvist.

For CSV-filen vår gir BIRT alternativer relatert til hvilke kolonner som skal vises, datatypen og om vi vil laste hele filen. På den annen side, hvis vi hadde en JDBC-datakilde, kan det hende vi må skrive et SQL-spørsmål eller en lagret prosedyre.

Fra Datasett Meny, vi kan også bli med i to eller flere datasett i et nytt datasett.

8. Gjengivelse av rapporten

Når rapportfilen er klar, må vi sende den til motoren for gjengivelse. For å gjøre dette er det noen få ting å implementere.

8.1. Initialiserer motoren

De ReportEngine klasse, som tolker designfilene og genererer det endelige resultatet, er en del av BIRT runtime-biblioteket.

Den bruker en rekke hjelpere og oppgaver for å gjøre jobben, noe som gjør den ganske ressurskrevende:

Bildekilde: Eclipse BIRT-dokumentasjon

Det er en betydelig kostnad forbundet med å lage en motorforekomst, hovedsakelig på grunn av kostnadene ved lasting av utvidelser. Derfor, vi burde lage bare en ReportEngine forekomst og bruk den til å kjøre flere rapporter.

Rapportmotoren opprettes gjennom en fabrikk levert av Plattform. Før vi lager motoren, må vi starte Plattform, som vil laste inn de aktuelle plugin-modulene:

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

Når vi ikke trenger det lenger, kan vi ødelegge det:

@ Overstyr offentlig tomrom ødelegge () {birtEngine.destroy (); Platform.shutdown (); }

8.2. Implementering av utdataformat

BIRT støtter allerede flere utdataformater:HTML, PDF, PPT og ODT, for å nevne noen.

For prøveprosjektet implementerte vi to av dem med metodene genererePDFReport og generer HTMLRapport.

De varierer litt avhengig av de spesifikke egenskapene som trengs, for eksempel utdataformat og bildebehandlere.

Faktisk legger PDF-filer inn bilder sammen med tekst, mens HTML-rapporter må generere dem og / eller koble dem.

Og dermed, PDF-gjengivelsesfunksjonen er ganske grei:

privat tomrom genererePDFReport (IReportRunnable rapport, HttpServletResponse respons, HttpServletRequest forespørsel) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); respons.setContentType (birtEngine.getMIMEType ("pdf")); IRenderOption-alternativer = ny RenderOption (); PDFRenderOption pdfRenderOption = ny PDFRenderOption (opsjoner); pdfRenderOption.setOutputFormat ("pdf"); runAndRenderTask.setRenderOption (pdfRenderOption); runAndRenderTask.getAppContext (). put (EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, forespørsel); prøv {pdfRenderOption.setOutputStream (respons.getOutputStream ()); runAndRenderTask.run (); } fange (Unntak e) {kaste ny RuntimeException (e.getMessage (), e); } til slutt {runAndRenderTask.close (); }}

Mens HTML-gjengivelsesfunksjonen trenger flere innstillinger:

privat tomrom generererHTMLReport (IReportRunnable rapport, HttpServletResponse svar, HttpServletRequest forespørsel) {IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask (rapport); response.setContentType (birtEngine.getMIMEType ("html")); IRenderOption-alternativer = ny RenderOption (); HTMLRenderOption htmlOptions = ny HTMLRenderOption (alternativer); 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, forespørsel); prøv {htmlOptions.setOutputStream (respons.getOutputStream ()); runAndRenderTask.run (); } fange (Unntak e) {kaste ny RuntimeException (e.getMessage (), e); } til slutt {runAndRenderTask.close (); }}

Mest bemerkelsesverdig, vi setter HTMLServerImageHandler i stedet for å forlate standardbehandleren. Denne lille forskjellen har stor innvirkning på den genererte img stikkord:

  • standard handler kobler img tag til filsystembanen, blokkert for sikkerhet av mange nettlesere
  • de HTMLServerImageHandler lenker til serverens URL

Med setImageDirectory metode, spesifiserer vi hvor motoren vil lagre den genererte bildefilen.

Som standard genererer behandleren en ny fil på hver forespørsel, så vi kan legge til et cachelag eller en slettingspolicy.

8.3. Publisering av bildene

I HTML-rapporttilfellet er bildefiler eksterne, så de må være tilgjengelige på serverstien.

I koden ovenfor, med setBaseImageURL metode, forteller vi motoren hvilken relativ bane som skal brukes i img tagkobling, så vi må sørge for at banen faktisk er tilgjengelig!

Av denne grunn, i vår ReportEngineApplication, konfigurerte vi Spring til å publisere Bilder mappe:

@SpringBootApplication @EnableWebMvc public class ReportEngineApplication implementerer WebMvcConfigurer {@Value ("$ {reports.relative.path}") private streng 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); }}

Uansett hvilken vei vi velger, må vi sørge for at den samme stien brukes her og i htmlalternativer av forrige kodebit, ellers kan ikke rapporten vår vise bilder.

9. Vise rapporten

Den siste komponenten som er nødvendig for å gjøre søknaden klar, er en Kontroller for å returnere det gjengitte resultatet:

@RequestMapping (method = RequestMethod.GET, value = "/ report / {name}") @ResponseBody public void generateFullReport (HttpServletResponse response, HttpServletRequest request, @PathVariable ("name") Strengnavn, @RequestParam ("output") String output) kaster EngineException, IOException {OutputType format = OutputType.from (output); reportService.generateMainReport (navn, format, svar, forespørsel); }

Med produksjon parameter, kan vi la brukeren velge ønsket format - HTML eller PDF.

10. Testing av rapporten

Vi kan starte applikasjonen ved å kjøre ReportEngineApplication klasse.

Under oppstart, BirtReportService klasse vil laste inn alle rapportene som finnes i / rapporter mappe.

For å se rapportene våre i handling, trenger vi bare å peke nettleseren vår mot:

  • / 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 ut:

For å laste inn en rapport etter endring av designfilen, peker vi nettleseren vår på / rapport / last inn på nytt.

11. Konklusjon

I denne artikkelen integrerte vi BIRT med Spring Boot, og utforsket fallgruvene og utfordringene, men også dens kraft og fleksibilitet.

Kildekoden for artikkelen er tilgjengelig på GitHub.