Alma Mater Studiorum Università degli Studi di Bologna Facoltà di Scienze Matematiche, Fisiche e Naturali Corso di Laurea in Informatica Materia di Tesi: Sistemi di Elaborazione II Reporting tool in ambiente Open Source Tesi di Laurea Specialistica di Giulio Toffoli Relatore Prof. Alessandro Amoroso II Sessione Anno Accademico 2002-2003 Cinque parole chiave: Reporting tool, visual builder, java printing, JasperReports, iReport Reporting tool in ambiente Open Source - Pagina 2 di 84 A mia moglie Caterina Reporting tool in ambiente Open Source - Pagina 3 di 84 Reporting tool in ambiente Open Source - Pagina 4 di 84 Sommario 1. Introduzione ......................................................................................... 7 2. Cos’è un reporting tool ..................................................................... 12 2.1 Struttura di un report ed elementi grafici ............................................ 12 2.2 Collegamento dei dati ........................................................................ 16 2.3 Esportazione della stampa................................................................. 19 2.4 Integrazione dei report all’interno di un’applicazione ......................... 19 2.5 Tipologie di report e strutture complesse ........................................... 20 2.6 Alcune note su performance e produttività......................................... 22 2.7 Linguaggi di programmazione e reporting tool ................................... 23 3. JasperReports.................................................................................... 24 3.1 Funzionamento di JasperReports ...................................................... 26 3.2 Struttura del report secondo jasper ed elementi grafici...................... 30 3.3 Campi, variabili, parametri ed espressioni ......................................... 37 3.4 L’interfaccia JRDataSource ............................................................... 39 3.5 Integrare JasperReports in un progamma java .................................. 43 3.5.1 Compilazione di un report ............................................................. 43 3.5.2 Esempio di creazione di una JRResultSetDataSource ................. 44 3.5.3 Generazione della stampa ............................................................ 45 3.5.4 Visualizzazione di una stampa a video ......................................... 46 3.5.5 Esportazione di una stampa in un file ........................................... 46 4. iReport ................................................................................................ 48 4.1 iReport e JasperReports .................................................................... 56 4.2 L’interfaccia principale ....................................................................... 57 4.3 Bande ed elementi ............................................................................. 60 4.4 Definizione di una fonte dati............................................................... 70 4.4.1 Empty data source (JREmptyDataSource).................................... 71 4.4.2 XML Data source .......................................................................... 71 4.4.3 JavaBean Set Datasource............................................................. 71 4.4.4 Custom Datasource ...................................................................... 72 4.4.5 Impostazione di una connessione JDBC....................................... 73 4.5 Recupero dei campi mediante SQL ................................................... 74 4.6 Gestione di variabili e parametri......................................................... 75 Reporting tool in ambiente Open Source - Pagina 5 di 84 4.7 Compilazione ed esportazione........................................................... 75 4.8 Performance ...................................................................................... 76 4.9 Un caso di studio: Sydran Services LLC............................................ 77 4.9.1 Storia di Cheetah .......................................................................... 77 4.9.2 Obiettivo raggiunto ........................................................................ 79 4.10 Sviluppi futuri ................................................................................... 80 Conclusioni ............................................................................................ 81 Bibliografia ............................................................................................. 83 Reporting tool in ambiente Open Source - Pagina 6 di 84 1. Introduzione A qualunque programmatore è capitato almeno una volta nella vita di dover sviluppare delle funzionalità di stampa per un qualche programma. A differenza di quanto accade per la costruzione delle interfacce grafiche, il supporto alla stampa offerto dai più diffusi ambienti di sviluppo è davvero primitivo. Nella maggior parte dei casi lo sviluppatore ha a disposizione un buffer di memoria (la pagina che dovrà stampare) ed una serie più o meno variegata di primitive che gli permetteranno di tracciare poligoni, scrivere caratteri con i font più congeniali, copiare immagini e, se fortunato, giustificare intere porzioni di testo. È davvero poco; tuttavia un qualsiasi altro strumento di più alto livello offerto al programmatore per costruire le stampe, in un modo o nell’altro limiterà le potenzialità offerte dall’approccio per così dire “rude” delle primitive grafiche. Eppure strumenti per lo sviluppo di stampe ad alto livello esistono, ed al contrario di quanto si potrebbe immaginare, sono molto diffusi, ma poco usati. Si noti che non stiamo parlando di word processor o di programmi creati per stampare documenti, ma di strumenti di sviluppo che affianchino il programmatore nella produzione di funzionalità di stampa. Lo strumento per la creazione dei report fornito con il noto programma Microsoft Access è un diffusissimo esempio di reporting tool (in italiano la traduzione suona un po’ male, ma azzarderemo comunque il nome di “strumento di reportistica”). A differenza degli strumenti che vedremo in questa tesi, Access è un reporting tool un po’ particolare: è possibile utilizzarlo solo all’interno di Access stesso, non nasce come strumento di supporto allo sviluppo di stampe per altri linguaggi (se non in qualche modo per il Visual Basic, per altro unico ambiente di sviluppo a fornire un proprio strumento di reportistica), ma permette all’utente di comporre con Reporting tool in ambiente Open Source - Pagina 7 di 84 la stessa facilità con la quale oggi si crea un’interfaccia grafica, una stampa, con gestione automatizzata di formule, pagine, salti pagina, giustificazione del testo ecc… Il lettore attento si sarà già reso conto che un approccio a così alto livello nella costruzione del report potrà soddisfare le esigenze richieste solo da poche tipologie di stampa, in particolare la stampa di documenti la cui struttura può essere ricondotta ad una sorta di template. In sostanza con uno strumento di reportistica come quello offerto da Access non si potrà mai (se non usando opportuni trucchi) realizzare le stampe prodotte da un CAD o ad esempio da un programma di grafica vettoriale e tanto meno si potrà mai raggiungere la flessibilità di un word processor sufficientemente evoluto. Tuttavia, il nostro obiettivo non è certo quello di inventare un reporting tool universale e adatto a qualsiasi esigenza. Al contrario potremmo in qualche modo limitare in maniera molto più forte il nostro campo d’azione ed affermare che in questa tesi parleremo di reporting tool per lo sviluppo di stampe che visualizzano informazioni organizzate in una struttura tabellare (o in una struttura riconducibile ad una forma tabellare). Gli strumenti di reportistica di questo tipo sono di fatto i più diffusi; dato il loro largo impiego in programmi di tipo gestionale, ovvero in programmi che fino a poco tempo fa avevano poco o nulla a che fare con il mondo open source, la loro natura è quasi esclusivamente commerciale. Forse il software che in assoluto ha maggiormente dettato le regole nel panorama mondiale degli strumenti di reportistica nel corso degli anni è Crystal Report della Crystal Decisions Inc.[5]. La sua popolarità è dovuta in gran parte alla distribuzione di una versione speciale all’interno del Visual Basic di Microsoft, ed ha riscosso negli anni grandissimo successo, godendo di un elevato numero di utenze. Esiste anche una versione java (molto diffusa, ma non altrettanto apprezzata come la versione per Visual Basic). Circa due anni fa, dovendo sviluppare dei report per un applicativo web basato sulla piattaforma J2EE, iniziai ad effettuare una ricerca degli strumenti che potessero in qualche modo velocizzare la creazione delle stampe. L’idea era quella di visualizzare la stampa in formato pdf Reporting tool in ambiente Open Source - Pagina 8 di 84 all’interno del browser stesso, pertanto le primitive di stampa offerta da java non vennero nemmeno mai prese in considerazione. La scelta ricadde su una libreria open source per la generazione di PDF, RTF ed HTML: iText. Oggi iText è la libreria open source per la generazione di pdf più diffusa nel mondo java, ma due anni fa le funzionalità offerte dalla libreria erano decisamente più limitate, tanto che per generare a fondo pagina la scritta “pagina x di n”, era necessario produrre la stampa due volte, una per conoscere il numero di pagine totali, un’altra per produrre la stampa definitiva con il numero n opportunamente sostituito con il valore appena ricavato. Tuttavia le righe di codice necessarie a produrre una stampa discreta era più che accettabile. Non mi occupai più di stampe fino ad un anno fa, quando, ripresentandosi la stessa necessità dell’anno precedente, finii nuovamente sul sito di iText. La strada fatta dalla libreria in meno di un anno mi lasciò gradevolmente stupito. Bruno Lowagie (l’autore di iText), affiancato da Paul Soares avevano ristrutturato la libreria aggiungendo funzionalità davvero potenti, ma dall’utilizzo abbastanza complesse e non immediatamente comprensibile dagli esempi a corredo (per altro molto ben fatti). Qualche mese prima aveva preso il via un altro progetto open source chiamato JasperReports. L’autore Teodor Danciu aveva sviluppato una libreria per la generazione di documenti esportabili in diversi formati (pdf, html, xsl,…) a partire da una definizione in formato XML del layout. In particolare l’esportazione in formato pdf veniva effettuata mediante la libreria iText. Grosso modo nello stesso periodo nacquero almeno altri due strumenti di reportistica open source: JFreeReport e DataVision, il primo utilizzava una logica molto simile a quella di JasperReports, basando la definizione delle stampe su documenti XML, il secondo, invece, rappresenta probabilmente il primo esempio di reporting tool in ambiente open source completamente ispirato a Crystal Report, dotato di un’interfaccia grafica per la composizione visuale dei report. Tuttavia la mia attenzione si focalizzò su JasperReports, in parte, devo ammetterlo, anche colpito dagli esempi a corredo della libreria che ne mettevano in risalto tutte le notevoli funzionalità e qualità. L’assenza di Reporting tool in ambiente Open Source - Pagina 9 di 84 un’interfaccia grafica simile a quella offerta da DataVision per la generazione dei report era sopperita da diversi strumenti rigorosamente open source nati poco dopo la comparsa di Jaspereports: “Designer for Jasper” di Jackie Manning e “JasperEdit” di Erik Swenson, autore anche di “Jeez”, un editor per JasperReports sviluppato come plugin per Eclipse (un diffuso IDE open source nato da un consorzio di “big” del mondo dell’IT e del quale IBM è la punta di diamante). “Designer for Jasper” si rivelò un programma pressochè inutilizzabile date le scarse qualità di editor visuale e l’incredibile lentezza dovuta alla pesantezza dell’interfaccia swing (la libreria standard per le interfacce grafiche di java). JasperEdit, invece, permetteva soltanto l’editing dell’XML in una sorta di modalità assistita (highlighting del codice e completamento automatico dei tag) e la possibilità di ottenere un preview del layout, ma non lo si poteva certo chiamare un editor visuale. Fu così che decisi di iniziare a scriverne uno mio, un nuovo editor per la creazione e la generazione di stampe basato su JasperReports; uno strumento pensato per gli sviluppatori, in grado di svincolarli dalla necessità di dover imparare la non banale sintassi XML di JasperReports. Nacque così iReport, divenuto oggi uno dei più evoluti ed utilizzati reporting tool in ambiente open source. Nato per l’ambiente java, iReport e JasperReports vengono utilizzati anche in progetti web sviluppati in ambienti differenti da J2EE, come PHP e Perl. Prima di entrare nel vivo della discussione, ci terrei a fare alcune precisazioni sulle pagine che seguiranno. Tenterò di essere sempre il più obiettivo possibile dell’esprimere giudizi relativi ai diversi strumenti di reportistica citati nel testo, tuttavia, come sviluppatore di iReport e forte sostenitore di JasperReports, potrei talvolta venire meno a questa obiettività o comunque esprimere giudizi non universalmente condivisi. Essendomi imbattuto in decine di discussioni relative al confronto dei diversi software di reportistica, ho notato come i sostenitori di un particolare prodotto, a causa di una scarsa conoscenza dei prodotti concorrenti, cadono nell’errore di sminuire le funzionalità di quest’ultimi. In Reporting tool in ambiente Open Source - Pagina 10 di 84 realtà questo genere di programmi è mediamente molto complesso, e solo un pesante uso della singola soluzione permette di comprenderne le reali potenzialità e sufficientemente personalmente non ritengo di aver utilizzato prodotti diversi da JasperReports da poter dire con certezza che taluni problemi non siano risolvibili con tali prodotti. D’altro canto, conoscendo fin troppo bene JasperReports, ed in qualità di sviluppatore di uno strumento di reportistica, potrei cadere anche nell’errore opposto, ovvero considerare scontate talune funzionalità che potrebbero essere tutt’altro che accessibili all’utente medio (perché non intuitive o utilizzabili solo grazie ad approfondita conoscenza del funzionamento interno della libreria). Più di una volta, infatti, mi è capitato di dover rinunciare a spiegare la soluzione di un problema ad utenti poco esperti essendo questa fuori dalla loro portata. Infine potrà capitare che i capitoli riguardanti JasperReports e iReport assumano in alcuni passi toni da manuale. La cosa sarà assolutamente intenzionale, volendo cogliere l’occasione di questa tesi per integrare la scarsissima documentazione relativa all’uso ed alle caratteristiche di iReport. Reporting tool in ambiente Open Source - Pagina 11 di 84 2. Cos’è un reporting tool In generale è difficile definire con chiarezza che cosa sia un reporting tool, in quanto questi rappresentato spesso strumenti che completano software più ampi quali ambienti di sviluppo o programmi di gestione di un DBMS, ecc... Tuttavia una buona definizione potrebbe essere la seguente: un reporting tool è un sistema che permette di definire il layout di una stampa, generarla popolando il layout con dei dati dinamici ed esportare il risultato finale in un qualche formato di pubblicazione. Da questa definizione appare chiaro che un reporting tool è costituito da tre componenti separati: il componente per la definizione del layout, il componente in grado di fondere questo layout con i dati da stampare, ed un ultimo componente che permetta l’esportazione della stampa finita nel formato richiesto. 2.1 Struttura di un report ed elementi grafici La descrizione di come debbano essere organizzati i dati sul nostro documento viene realizzata elaborando un layout. Il layout definisce la struttura del nostro report ed è costituito da un insieme di porzioni orizzontali di documento, dette bande (o sezioni), all’interno delle quali vengono inseriti gli elementi grafici che comporranno il contenuto della nostra stampa. Tutti gli strumenti di reportistica prevedono che il layout sia diviso in almeno cinque bande: report header, page header, detail, page footer e report footer. Come si può intuire dal nome, ogni banda si riferisce ad una specifica porzione di una “pagina Reporting tool in ambiente Open Source - Pagina 12 di 84 tipo” del nostro documento. Oltre a queste cinque bande di base, possono essere presenti altre bande che realizzano il raggruppamento delle informazioni: i group header e i group footer. Fig.2.1: Struttura del layout Quando il report viene popolato, il programma che genera la stampa compone il risultato finale “ripetendo” le diverse porzioni definite nel layout in base ai dati da visualizzare e alle regole specificate dallo sviluppatore. In figura 2 è possibile vedere il risultato di un’ipotetica stampa generata a partire dal layout mostrato in figura 1. All’interno delle bande compaiono degli oggetti grafici chiamati elementi. Il set minimo di elementi che un reporting tool dovrebbe mettere a disposizione è molto limitato e si riduce a: - Casella di testo - Immagine - Poligono (linea, rettangolo, ovale) Questi pochi elementi sono sufficienti a definire stampe anche molto complesse. Esiste poi un elemento speciale che permette di incapsulare un report un altro: il sottoreport. Non tutti gli strumenti di reportistica sono in grado di gestire i sottoreport, e pochi sono quelli in grado di gestire i sottoreport ricorsivamente. Questa è una delle caratteristiche che elegge JasperReports al miglior strumento di Reporting tool in ambiente Open Source - Pagina 13 di 84 generazione di report disponibile nel mondo open source, essendo l’unico Fig.2.2: Il risultato della stampa generata mediante il layout in figura 1 strumento di questo tipo a gestire i sottoreport. Ogni strumento di reportistica contempla poi una serie di altri elementi in qualche modo derivabili dai precedenti ed utilizzabili liberamente all’interno di una stampa. Uno dei più diffusi è l’oggetto “chart” o “grafico”. Poiché il grafico può essere banalmente rappresentato come un’immagine, tutti gli strumenti di reportistica open source (a differenza di quanto avviene per prodotti analoghi di tipo commerciale), delegano le funzionalità di “charting” a librerie esterne (tipicamente open source) nate esclusivamente con lo scopo di generare grafici visualizzati nel report come oggetti immagine (molto diffusi sono i pacchetti open source: JFreeChart e JCharts, ma ce ne sono molti altri disponibili anche per linguaggi di programmazione diversi da java). In pratica nessuno strumento open source di reportistica supporta nativamente l’elemento Reporting tool in ambiente Open Source - Pagina 14 di 84 “chart”, ma ciò non impedisce di visualizzare grafici all’interno delle nostre stampe… In generale, l’elemento immagine può essere visto come una sorta di viewport utilizzabile per il rendering di qualsiasi cosa. A sfruttare questo meccanismo sono molti elementi “inconsueti” quali, oltre ai grafici, generatori di codici a barre, strumenti di disegno vettoriale, ecc… I tipi di dati stampabili mediante un sistema di reportistica di questo tipo sono , in definitiva, tutti quelli riconducibili ad un testo (stringhe e numeri) e quelli rappresentabili mediante un’ immagine (foto, grafici, codici a barre,…). Il binding tra i particolari dati da stampare e gli elementi che li contengono viene normalmente effettuato mediante delle formule. Praticamente tutti i sistemi di reportistica definiscono il valore che deve essere rappresentato da un certo elemento sotto forma di un’espressione, che permetterà non solo di specificare il dato da stampare, ma anche di effettuare “al volo” elaborazioni dei dati stessi come somme, medie, ecc… Le funzionalità che permettono di dare dinamicità ai report (per l’appunto sommatorie, medie, raggruppamenti, ecc…) sono pressochè simili per qualsiasi strumento di reportistica sufficientemente potente. Tuttavia la scelta implementativa adottata dai diversi strumenti è tutt’altro che simile. L’idea di base comune è di appoggiarsi ad un linguaggio dotato di una certa espressività e potenza, ma la scelta del linguaggio cambia completamente il modo di scrivere formule e collegare dati ad elementi. Curiosa la scelta adottata dal creatore di DataVision che utilizza come linguaggio di formule Ruby, un diffuso linguaggio di scripting open source. JasperReports si appoggia direttamente alla potenza di java arricchito, come vedremo, di qualche nozione sintattica per realizzare in modo semplice il binding con i dati. Il componente che permette di definire il layout è generalmente costituito da un ambiente visuale tramite il quale è possibile collocare e gestire tutti gli elementi che compongono un report. Nel caso specifico di JasperReports e JFreeReport, il layout viene definito mediante una speciale sintassi XML. Gli sviluppatori, in questi due casi, si sono elegantemente svincolati dall’onere di dover scrivere un complesso e oneroso ambiente visuale per la definizione del layout, concentrandosi Reporting tool in ambiente Open Source - Pagina 15 di 84 sulle funzionalità messe a disposizione delle proprie librerie per la generazione della stampa. In effetti creare strumenti in grado di coprire tutti i possibili aspetti della definizione del layout non è semplice. Molti degli strumenti commerciali che si discostano in parte dal modello reso famoso da Crystal Report risultano essere frustanti e tutt’altro che intuitivi. 2.2 Collegamento dei dati La potenza e la qualità di un reporting tool non è data solo dal numero e dall’utilità degli elementi disponibile per creare una stampa. Come abbiamo visto, con pochissimi elementi siamo già in grado di realizzare stampe molto complesse che soddisferanno il 90% delle capacità espressive normalmente richieste da un software di reportistica. Un nodo cruciale, piuttosto, risulta essere la facilità con cui è possibile “agganciare” al nostro report una fonte dati. Fino a qualche anno fa, l’unica fonte dati realmente utilizzata da un software di reportistica era una query SQL, ovvero, i dati del mio documento erano rappresentati da dei campi risultanti da una selezione effettuata mediante SQL. Oggi il binding dei dati ad un report realizzato mediante una query SQL non solo è dato per scontato, ma è quasi superato. Una fonte dati, infatti, può avere infinite forme come una collezione di oggetti o un documento XML. Per questo tutti gli strumenti di reportistica maggiormente evoluti mettono a disposizione dell’utente una serie di “driver” appositamente studiati per convertire i dati provenienti da sorgenti eterogenee esterne in dati utilizzabili all’interno della nostra stampa. Come per il caso degli elementi “chart”, il mondo open source in qualche modo viene in contro agli sviluppatori dei reporting tool. Questi, infatti, devono semplicemente sviluppare un’interfaccia comune da estendere per la realizzazione di driver di fonti dati. Ci penseranno altri sviluppatori a scrivere e rendere disponibili i driver per le fonti più disparate. È il caso di JasperReports per il quale sono state scritte “data source” davvero Reporting tool in ambiente Open Source - Pagina 16 di 84 particolati come quella per collegare dati provenienti da Hibernate (un potente database ad oggetti open source). Nella maggior parte delle implementazioni, queste fonti dati espongono un’interfaccia simile a quella della classe ResultSet di java, ovvero una sorta di struttura dati organizzata in righe e colonne. Il core del reporting tool, ovvero il componente che si occuperà di popolare il layout attingendo i dati dalla data source, processerà le righe una ad una utilizzando i valori contenuti nelle varie colonne (i campi) per interpretare le espressioni contenute negli elementi del report. Sfortunatamente la rappresentazione dei dati in forma tabellare costituisce un grosso limite qualora i dati siano organizzati in una struttura ad albero, tipica dei documenti XML. Solo una parte di strutture ad albero possono essere ricondotte in maniera semplice ad una forma tabellare. Si consideri ad esempio la struttura ad albero di figura 2.3. Essendo gli elementi 1 e 2 sullo stesso ramo è necessario effettuare un merge dei rami. La tabella in figura 2.4 potrebbe rappresentare una soluzione al nostro problema, ma come si nota, il numero di record cresce molto rapidamente e le performance del nostro strumento di reportistica crollano. Il modo più efficiente per affrontare casi come questo è sempre l’utilizzo dei sottoreport. Root Element 1 Element 1.1 Element 1.2 Element 2 Element 2.2 Element 2.3 Fig.2.3: Esempio di struttura dati ad albero Reporting tool in ambiente Open Source - Pagina 17 di 84 Root Element 1 Element 1.1 Element 2 Element 2.1 Root Element 1 Element 1.1 Element 2 Element 2.2 Root Element 1 Element 1.2 Element 2 Element 2.1 Root Element 1 Element 1.2 Element 2 Element 2.2 Fig.2.4: Rappresentazione tabellare della struttura ad albero di figura 3 Tutti gli strumenti di reportistica processano sempre un record per volta. Questo impedisce di accedere mediante le formule ai valori assunti dai campi del record precedente o successivo a quello in corso di elaborazione: l’accesso ai dati è limitato quindi al record corrente. Un caso limite, ma non poco diffuso, e soprattutto particolarmente penalizzato da questo meccanismo, è il seguente. Supponiamo di registrare ad intervalli regolari il numero di chilometri percorsi da un auto (leggendo il valore dei km totali percorsi sul contachilometri). Supponiamo ora di voler visualizzare in un report tre colonne: nella prima metteremo la data di registrazione del tempo, nella seconda il numero di chilometri progressivi letti dal contachilometri, ed infine, nella terza, il numero di chilometri parziali percorsi dall’auto tra la registrazione corrente e quella precedente. L’ultima colonna descritta non può essere calcolata mediante formule, ma necessita di un dato già calcolo (solitamente dal programma che produce i dati da stampare), infatti siamo in grado di accedere al valore attuale del tempo di registrazione, ma non più a quello precedente!. Esistono tuttavia dei trucchi per poter memorizzare i dati in variabili temporanee, ma non tutti gli strumenti di reportistica permettono di definire variabili o meccanismi di memorizzazione intermedia delle informazioni processate. Reporting tool in ambiente Open Source - Pagina 18 di 84 2.3 Esportazione della stampa Il report appena generato viene solitamente memorizzato in un formato intermedio gestito direttamente dallo specifico reporting tool, che mediante dei meccanismi interni potrà convertirlo o, come si usa dire, esportarlo in un formato di pubblicazione “standard”. I formati più diffusi sono il pdf, l’HTML e l’ XML, oltre al supporto diretto per la stampa e l’anteprima a video. Il modello a driver descritto per l’accesso ai dati si utilizza anche per quel che riguarda l’esportazione del report nei diversi formati. Anche in questo caso JasperReports si rivela la libreria più flessibile, mettendo a disposizione del programmatore un’interfaccia standard da implementare per poter realizzare il proprio driver di esportazione, operazione facilitata grazie anche alla disponibilità del codice sorgente dei driver distribuiti con la libreria stessa, in grado di generare report nei formati più diffusi con un’ottima resa finale (pdf, html, xsl, txt, xml). 2.4 Integrazione dei report all’interno di un’applicazione Tutti i reporting tool mettono a disposizione una libreria (nel caso di java, un archivio jar) che espone una serie di metodi per caricare una stampa, eseguirla ed esportarla o visualizzarla a video. Per facilitare la vita agli sviluppatori, gli autori delle varie librerie di reportistica hanno ridotto al minimo la complessità del codice richiesto per eseguire le operazioni citate. Normalmente un programma deve occuparsi di produrre la fonte dati (in molti casi la fonte dati viene implicitamente creata dallo stesso reporting tool a partire da una connessione ad un database aperta dal programma stesso e passata alla libreria che eseguirà autonomamente una query SQL, precedentemente memorizzata all’interno del report in fase di creazione); creata la fonte dati, l’applicazione dovrà specificare il report da generare (tipicamente memorizzato in un file) ed eseguire la generazione della stampa. Un’ultima chiamata ad un metodo di esportazione completa il codice di stampa. Reporting tool in ambiente Open Source - Pagina 19 di 84 In effetti il numero di righe di codice richiesto per integrare in un programma le funzionalità di stampa messe a disposizione dalla libreria di un reporting tool (esclusa la creazione della fonte dati), no supera mai la decina e le possibilità di estensione delle librerie open source in questo specifico frangente permettono di sopperire anche alle richieste più esigenti di integrazione con l’applicativo (essendone disponibile il codice). 2.5 Tipologie di report e strutture complesse Probabilmente scrivere il codice per produrre una stampa esteticamente molto piacevole e organizzata come una tabella è più che fattibile senza l’ausilio di un reporting tool, anche se poco manutenibile e pratico. Tuttavia nella maggior parte delle situazioni in cui si verifica la necessità di produrre una stampa, devono essere utilizzate delle strutture per organizzare i dati che superano la banale tabella. È in questi frangenti che è possibile apprezzare un reporting tool in tutta la sua capacità espressiva e potenza. In generale i report vengono classificati in tre categorie: i report di tipo columnar, di tipo tabular ed di tipo cross table (o semplicemente crosstab). Fig.2.5: Columnar report Reporting tool in ambiente Open Source - Pagina 20 di 84 I primi due rappresentano il caso di stampa più comune. Talvolta, se i dati da stampare sono molti, si usa raggruppare i record mediante “gruppi” per meglio esporre le informazioni. La caratteristica principale di questi tipi di Fig.2.6: Tabular report report è la staticità di alcuni elementi base come le etichette o il numero di colonne. Fig.2.7: Crosstab report Reporting tool in ambiente Open Source - Pagina 21 di 84 I crosstab report, invece, hanno un numero di colonne che può variare a seconda dei dati stampati. Nessuno degli strumenti di reportistica open source supporta questo tipo di report che introduce un notevole grado di complessita nel codice di generazione e nella descrizione del layout. Solo l’autore di JasperReports ha annunciato un futuro timido supporto per i crosstab report, proponendo la possibilità di definire in maniera dinamica i campi che formano le colonne. Nel caso sia possibile fissare un upper bound al numero di colonne necessarie nel crosstab report, è possibile “simulare” questo tipo di report mediante un tabular report costruendo opportunamente il set di record che andrà ad alimentare la stampa. 2.6 Alcune note su performance e produttività Tutti i reporting tool utilizzano una logica di esecuzione molto simile: tramite un meccanismo di design (visuale o meno), viene generato un prodotto intermedio (nel caso di JasperReports addirittura il codice di una classe java) che viene compilato e serializzato su file. Questo permette al generatore della stampa di minimizzare le risorse in termini di lettura e parsing del layout della stampa. Un certo overhead si ha nel caso di formule interpretate e non compilate direttamente. Tuttavia l’esportazione risulta, nella maggior parte dei casi, il tallone d’achille dei prodotti di reportistica, richiedendo grandi risorse in termini di memoria (in particolare nel caso di report contenenti molte righe) e di potenza di calcolo (tra i più diffusi, il pdf è decisamente il formato che necessita il maggior numero di risorse. Tuttavia difficilmente un report interamente programmato “a mano” supererà in maniera netta le performance di un buon motore di reportistica. Al contrario, per quel che riguarda la produttività, gli strumenti visuali permettono un’imparagonabile abbattimento dei tempi di sviluppo. Le prime versioni di iReport, ancora allo stato embrionale e privo di tutte le funzionalità che possiede oggi, permetteva, secondo le stime di un utente americano, di incrementare di 30 volte la velocità di creazione dei report precedentemente sviluppati scrivendo a mano il codice XML con il quale vengono definite le stampe di JasperReports. Reporting tool in ambiente Open Source - Pagina 22 di 84 2.7 Linguaggi di programmazione e reporting tool A questo punto della trattazione, il lettore si sarà reso conto quanto il linguaggio java faccia la parte del leone nel campo della reportistica. In realtà esistono numerosissime librerie per creare documenti nei formati più diffusi (pdf, html, XML, ecc…) per linguaggi diversi da java, ma non sono reporting tool, bensì API per poter generare in maniera semplice e veloce documenti nei formati citati. In ambiente open source tutti gli strumenti di repostistica più diffusi sono scritti in java. Esiste, inoltre, un software di reportistica sviluppato dall’Apache Group chiamato Cocoon, il cui funzionamento è interamente basato su XML e i fogli di trasformazione XSLT tramite i quali il documento XML iniziale viene convertito in diversi formati tra cui pdf e xls. Da una parte Cocoon rappresenta probabilmente il reporting tool più evoluto al mondo dal punto di vista delle tecnologie utilizzate, ma il suo utilizzo è apparentemente così complesso e macchinoso, o per lo meno così distante dai canonici processi di creazione di un report tramite un’interfaccia visuale, che ho deciso di non trattarlo in questa tesi. Reporting tool in ambiente Open Source - Pagina 23 di 84 3. JasperReports Nato nel settembre del 2001 per opera del rumeno Teodor Daciu, JasperReports rappresenta un valido strumento di reportistica in ambiente open source. Oltre che per le notevoli funzionalità e semplicità d’uso, deve la sua popolarità al noto servlet engine Tomcat, che ha inserito questa libreria all’interno della propria distribuzione. È da oltre un anno uno dei più attivi progetti presenti su Source Forge, ed alla data odierna (ottobre 2003) ha raggiunto la versione 0.5.0. Rispetto a software analoghi presenti nel panorama open source, JasperReports spicca per la sua architettura basata sull’idea di modularità ed estensibilità. Esiste la possibilità, in “jasper”, di personalizzare qualsiasi fase del ciclo di vita del report, dalla compilazione all’esportazione, alla gestione dei dati da stampare. L’integrazione con qualsiasi tipo di applicativo java è estremamente semplice e la dotazione di elementi grafici è sufficiente a soddisfare la maggior parte dei requisiti necessari a creare le stampe più complesse. Il punto di forza, oltre alla facilità di implementazione delle fonti di dati, è la possibilità di utilizzare sottoreport ricorsivi con i quali è possibile generare report con dettaglio costituito virtualmente da un numero illimitato di pagine per ogni singolo record. Si pensi ad esempio ad una stampa molto complessa nella quale si vuole definire contenuti differenti per le prime pagine, inserendo, ad esempio una pagina per il titolo, una per il sommario comprensivo di numeri di pagina, ed una serie di tabelle relative ad informazioni eterogenee, Con JasperReports (ed un po’ di esperienza) è possibile creare stampe di questo tipo, che vanno anche molto oltre il semplice layout visto nel capitolo precedente. Reporting tool in ambiente Open Source - Pagina 24 di 84 La libreria include funzionalità di esportazione per i formati pdf, xsl, html, xml e csv, oltre che una serie di classi per l’anteprima e la stampa diretta. Sfortunatamente non esiste ancora un “driver” per esportare i report in formato rtf. La spiegazione di questa carenza è dovuta alla complessità di scrivere un generatore rtf secondo i canoni con cui sono scritti gli altri “driver”: questi sono tutti basati sul concetto di griglia nella quale vengono inseriti tutti gli elementi che costituiscono il report. In rtf non esiste un’organizzazione degli elementi basata su una griglia (come, invece, accade per pdf, xsl, html, ecc…), e ciò complica notevolmente le cose. Si noti che tecnicamente non c’è nessun impedimento nello scrivere una classe per esportare un documento jasper in rtf, ma evidentemente la mancanza non è percepita come tale dalla nutrita comunità di utenti. Per l’esportazione in pdf e xsl, JasperReports si appoggi a due famose librerie open source: iText e POI. Di iText abbiamo già parlato nel capitolo introduttivo, POI, invece, è un progetto dell’Apache Group, ed è una libreria java creata per la generazione di file Excel in formato biff (meglio conosciuto con la sua extensione XLS). Una seconda carenza di rilievo è l’assenza di una fonte dati XML. In realtà tale tipo di fonte dati esiste, ma è presente come patch al programma e soffre di notevoli limitazioni. Per quel che riguarda la definizione dei report, JasperReports si affida completamente ad una propria sintassi XML con la quale è possibile descrivere interamente il layout della stampa da creare. Inizialmente l’autore Teodor Danciu annunciò l’intenzione di scrivere un tool aggiuntivo per poter creare visualmente le stampe. Con la nascita di altri strumenti con lo stesso fine, questo task venne completamente abbandonato. Rimangono comunque, all’interno della libreria, delle funzionalità per poter visualizzare a video il layout di una stampa come definita mediante l’XML. Il diretto “concorrente“ di JasperReports è un progetto chiamato JFreeReport, ospitato come il primo su Source Forge. Personalmente ritengo JasperReports un prodotto molto più maturo e costruito secondo un’architettura decisamente più flessibile (oltre ad essere decisamente più utilizzato). Su un blog visibile Reporting tool in ambiente Open Source - Pagina 25 di 84 all’indirizzo http://roller.anthonyeden.com/page/chenihsu ho trovato per caso un articolo molto ben scritto relativo al confronto tra i due sistemi di reportistica. L’autore dichiara esplicitamente di essere alla ricerca di un reporting tool open source per il proprio progetto e di aver tra tutti selezionato JasperReports e JFreeReport quali possibili candidati. Questa prima selezione sembra essere basata su una serie di parametri molto semplici quali diffusione, popolarità, qualità della documentazione disponibile sul sito di ciascun progetto, ecc… Segue una più approfondita analisi dei due sistemi di stampa dalla quale si evince come JasperReports sia la soluzione vincente in tutte le scelte implementative. 3.1 Funzionamento di JasperReports Come tutti i software di reportistica, JasperReports è costituito logicamente da tre componenti: uno per la compilazione del layout, uno per la generazione della stampa ed uno per l’esportazione (a volte chiamato anche rendering) del documento. Essendo sprovvisto di uno strumento visuale per la creazione del layout (lacuna che può essere facilmente colmata utilizzando uno dei diversi strumenti sviluppati da terze parti), la definizione del report viene effettuata mediante un documento XML. Questo documento segue la sintassi definita in un apposito DTD e permette di definire la dimensione delle bande, i gruppi, gli elementi e la loro posizione specifica, nonché altre informazioni quali un query SQL da eseguire per popolare la stampa, o le formule da utilizzare per calcolare campi speciali. Scrivere codice XML per definire una stampa, dopo aver preso un po’ di confidenza con la specifica sintassi (per altro molto semplice ed intuitiva), è tutt’altro che complesso o addirittura paragonabile alla difficoltà di stesura di una pagina HTML dotata di un po’ di javascript. Grazie all’uso di nomi immediatamente comprensibili come rectangle o textfield è facile orientarsi nonostante l’elevato numero di tag. Reporting tool in ambiente Open Source - Pagina 26 di 84 Il report così sviluppato viene processato mediante il JasperCompileManager. Questa classe trasforma l’XML opportunamente validato in un file sorgente java che verrà compilato e successivamente serializzato in un file con estensione jasper. La fase di compilazione viene effettuata solo una volta (esattamente come avviene per i normali programmi java). Il codice compilato risulterà, in fase di esecuzione della stampa, particolarmente performante. Qualora sia necessario mediante il proprio programma creare dinamicamente il sorgente del report, questo deve necessariamente essere compilato prima di essere eseguito per dare vita alla stampa. Poiché la compilazione del report assume la presenza di un compilatore, che potrebbe non essere presente in un ambiente di produzione, JasperReports permette di utilizzare come compilatore in alternativa a quello standard di java, un pacchetto chiamato BeanShell (http://www.beanshell.org), in grado di eseguire codice java interpretato! Per la verità JasperReports fa molto di più, mettendo a disposizione un’interfaccia chiamata JRCompiler per poter utilizzare compilatori personalizzati. Ad ogni modo la fase di compilazione produce sempre un file jasper. Da questo file è possibile creare una stampa grazie al JasperFillManager, che si occuperà di popolare con i dati il nostro report. I dati che il JasperFillManager utilizzarà per la stampa possono essere passati secondo due paradigmi completamente differenti. Il più semplice (e limitativo) è quello di delegare alla libreria il compito di recuperare i dati leggendoli mediante una query SQL precedentemente associata al report. L’unico compito dell’applicazione sarà quello di passare al JasperFillManager un oggetto Connection opportunamente inizializzato (ovvero già collegato al database sul quale la query verrà effettuata). Il secondo paradigma, invece, è quello che utilizza un’opportuna struttura dati che implementa l’interfaccia JRDataSource. Parleremo estensivamente di questa interfaccia e di come essa rappresenti uno dei punti di forza di JasperReports in seguito. Per ora diciamo soltanto che è una sorta di enumeratore di righe (o records) dotato di un metodo (getField) per accedere ai campi del record corrente. Reporting tool in ambiente Open Source - Pagina 27 di 84 Ciò che viene generato dal JasperFillManager è una classe chiamata con molta fantasia JasperPrint. Questa può essere salvata su file in formato XML (secondo una sintassi definita da JasperReports) riutilizzabile in seguito nel caso si voglia per esempio posticipare l’esportazione in un formato più diffuso, oppure richiamare una delle classi dedicate all’esportazione che estendono l’interfaccia JRExporter. Nelle prime versioni della libreria, l’esportazione era gestita da una classe chiamata JasperExportManager; fortunatamente questa prima soluzione è stata abbandonata (anche se il JasperExportManager esiste ancora per retrocompatibilità), ed è stato introdotto il modello a “driver” di stampa, costituito appunto dall’interfaccia JRExporter. Attualmente è possibile esportare un report creato con JasperReports nei formati: PDF, HTML, XLS, CSV e XML. Come spiegato all’inizio del capitolo, JasperReports è privo di un exporter per il formato RTF, ma come si intuisce si tratta “solo” di estendere opportunamente l’interfaccia JRExporter… La libreria contiene poi una serie di classi per il design e la visualizzazione Fig. 3.1: Esempio di anteprima mediante JasperReports a video della stampa come anteprima. Queste funzionalità vengono utilizzate da normali programmi java che utilizzano le swing o all’interno di Reporting tool in ambiente Open Source - Pagina 28 di 84 un browser mediante un applet. In figura 3.1 è possibile vedere come si presenta l’anteprima gestita da JasperReport ed integrata in un programma java basato su swing. Fig.3.2: Funzionamento di JasperReports In figura 3.2 e 3.3 è schematizzano il funzionamento completo della libreria. Riassumendo, la definizione del report XML passa attraverso un compilatore che valida il report e genera una versione compilata dello stesso. Mediante il JasperFillManager la stampa viene popolata con i dati provenienti da una connessione JDBC o da una datasource per produrre un documento eventualmente da esportare in uno dei formati supportati. Fig.3.3: Contesti di utilizzo I possibili contesti di utilizzo della libreria sono veramente vari. Essendo scritto in 100% puro java, JasperReports può essere impiegato in qualsiasi applicazione basata sulla piattaforma J2EE comprese le applicazioni Web. Tramite semplici bridge software, è possibile poi Reporting tool in ambiente Open Source - Pagina 29 di 84 utilizzare JasperReports anche in altri contesti, ad esempio in applicazioni basate su PHP o altri linguaggi di scripting lato server. 3.2 Struttura del report secondo jasper ed elementi grafici JasperReports gestisce ben otto bande predefinite e infinite bande di raggruppamento, costituite da un header ed un footer rispettivamente sopra e sotto la banda di detail. Oltre alle bande (che descriveremo in dettaglio tra poco), JasperReports è Fig.3.4: Bande predefinite in JasperReports in grado di dividere la banda di dettaglio e quelle di raggruppamento in colonne (da 1 a n), in modo da poter sfruttare al meglio lo spazio disponibile sulla pagina. È bene non confondere il concetto di colonna appena espresso con quello della colonna che si forma in seguito Reporting tool in ambiente Open Source - Pagina 30 di 84 all’allineamento di campi stampati uno sotto l’altro. La figura 11 evidenzia la differenza tra i due concetti di colonna ed esemplifica l’uso ottimizzato della banda di dettaglio (nel caso specifico spezzato in due colonne). Fig.3.5: Differenza tra una colonna del dettaglio e una colonna di dati In generale, in JasperReports esistono delle regole che determinano l’altezza massima di una banda, mentre la larghezza è sempre uguale alla Reporting tool in ambiente Open Source - Pagina 31 di 84 larghezza della pagina meno i margini laterali. L’altezza di una banda può essere impostata esplicitamente in fase di design (specificando un valore di altezza contenuto nell’intervallo consentito per la specifica banda), tuttavia la reale altezza assunta dalla banda in fase di stampa può variare a seconda del suo contenuto. È il caso in cui all’interno di un dettaglio inseriamo un sottoreport contenente qualche centinaio di righe: il dettaglio risulterà alto addirittura diverse pagine. Tramite un attributo chiamato isSplitAllowed, l’utente può abilitare o meno la possibilità di stampare una banda su più pagine qualora la cosa si renda necessaria. Infine tramite un’espressione booleana è possibile rendere una banda invisibile. Velocemente descriviamo l’utilizzo delle bande principali (nell’ordine in cui vengono tipicamente inserite nel codice XML). Background Questa banda comparve per la prima volta nella versione 0.4.6 di JasperReports e fu introdotta dopo insistenti richieste da parte di diversi utenti per poter creare watermark ed effetti simili (come ad esempio una cornice attorno a tutta la pagina). Può assumere un’altezza massima pari alla dimensione del report. Title Il nome di questa banda rende chiaro il suo utilizzo. Tuttavia gli usi che se ne fanno non si limitano a quelli di spazio in cui inserire banalmente un titolo. Grazie ad una speciale opzione, è possibile forzare la stampa di questa banda su una pagina separata. Con un po’ di astuzia, questa possibilità può essere sfruttata mediante dei sottoreport per simulare un salto pagina. Per quel che riguarda le dimensioni ammesse, non è possibile superare a tempo di design l’altezza del report (margini superiore ed inferiore esclusi). Tuttavia JasperReports in fase di validazione controlla che l’altezza di tutte le bande (background escluso) sia inferiore o uguale all’altezza del report. Nel caso il titolo sia impostato per essere stampato su una nuova pagina, la limitazione rimane costringendo l’utente ad utilizzare sottoreport per sfruttare un’intera pagina per il titolo, che altrimenti consumerebbe tutta l’altezza disponibile per le altre bande producendo un errore di validazione. Reporting tool in ambiente Open Source - Pagina 32 di 84 Page header Questa sezione permette di definire l’intestazione di pagina. L’altezza definita in fase di design solitamente non cambia durante il processo di generazione (salvo l’inserimento di componenti ridimensionabili come campi testo dinamici o sottoreport). Il page Fig.3.6: Page header header compare in tutte le pagina della stampa nella stessa posizione definita in fase di design. Column header È una banda tipica di JasperReports. Viene stampata all’inizio di ogni colonna di dettaglio. Questo permette di Fig.3.7: Column header visualizzare ad esempio le etichette delle colonne del report ad ogni cambio pagina. In altri strumenti di reportistica le etichette delle colonne vengono inserite in un group header, perdendo il vantaggio della ristampa automatica delle intestazioni nei salti pagina o di colonna. Reporting tool in ambiente Open Source - Pagina 33 di 84 Group header Un report può contenere zero o più bande di raggruppamento, ovvero sezioni che permettono di dividere in veri Fig.3.8: Group header e propri gruppi i record del dettaglio. Un group header è sempre accompagnato da un group footer ( entrambi possono essere indipendentemente visibili o meno). Al gruppo sono associati diversi parametri che ne determinano il comportamento dal punto di vista grafico; è possibile imporre la stampa di un group header sempre in una nuova pagina o in una nuova colonna, forzarne la stampa su tutte le pagine (come un page header, ma a livello di gruppo), fissare un’altezza superata la quale la banda del gruppo debba essere stampata in una nuova facciata. L’espressione di raggruppamento può essere rappresentata da un qualsiasi frammento di codice java che restituisca una stringa. La stringa stessa rappresenterà il valore di raggruppamento. Questo meccanismo svincola il concetto di raggruppamento “per campi” tipico di molti sistemi di reportistica ed estremamente limitativo. La caratteristica dei gruppi di spezzare il dettaglio viene spesso utilizzata per ottimizzare (o forse dovremmo dire “gestire correttamente”) la stampa di dettagli suddivisi in più pagine o contenenti molti sottoreport. Reporting tool in ambiente Open Source - Pagina 34 di 84 Detail Ad ogni record letto dalla fonte dati che alimenta la stampa, corrisponde una banda di dettaglio. Con ogni probabilità, la maggior parte degli elementi della stampa verranno posizionati qui. Group footer È la banda che corrisponde al group header, e solitamente contiene campi in cui visualizzare subtotali o elementi grafici di separazione come linee, ecc… Column footer È una banda di comodo che appare alla fine di ogni colonna. La sua dimensione non è in nessun modo modificabile (nemmeno qualora contenesse elementi ridimensionabili come suttoreport o campi testo con un numero di righe variabile). Page footer È il piè di pagina. Compare in tutte le pagine e come il column footer non è ridimensionabile. Summary Questa sezione è quella che in altri sistemi viene chiamato Report footer. Permette di inserire campi relativi a calcoli totali, medie, o quant’altro si voglia inserire alla fine del nostro report. Quando il report viene generato utilizzando una fonte dati vuota, è possibile impostare uno dei tre possibili comportamenti di JasperReports: visualizzare una pagina vuota, non produrre nessuna pagina, visualizzare tutti gli elementi ad eccezione di quelli inseriti nelle bande di dettaglio (groupHeader, detail, groupFooter). Quest’ultima modalità permette di stampare il titolo anche se la stampa non ha record. Si noti che esistono diversi modi di passare dati da stampare a JasperReports (ad esempio usando i parametri), e quindi è possibile senza fonte dati creare un report solo utilizzando la banda del titolo. Gli elementi grafici utilizzabili in una stampa creata con JasperReports sono sette: la linea, il rettangolo, l’ellisse, l’immagine, il testo statico, il campo di testo (simile al testo statico, ma in grado di visualizzare stringhe prodotte mediante un’espressione) e il sottoreport. Reporting tool in ambiente Open Source - Pagina 35 di 84 Un elemento deve essere sempre associato ad una banda. La posizione è definita mediante coordinate x,y. Poiché l’altezza delle bande in generale può cambiare, la coordinata y viene interpretata come valore relativo rispetto alla banda. Le opzioni di valutazione di y sono tre: floating position Significa che l’elemento può essere spinto verso il basso in seguito al ridimensionamento di elementi precedenti; Fixed position relative to the top of the parent band Significa che indipendentemente dalla dimensione della banda, l’elemento deve sempre stare a y punti sotto l’inizio della sezione; Fixed position relative to the bottom of the parent band Significa che indipendentemente dalla dimensione della banda, l’elemento deve sempre stare a y punti sopra la fine della sezione. Non ci soffermeremo sui dettagli di ogni singolo elemento. È utile tuttavia spiegare il concetto di evaluationTime (associato ai campi di testo ed agli elementi immagine). L’evaluationTime (istante di valutazione), si riferisce a quando una specifica espressione debba essere valutata. Infatti il risultato della valutazione di un espressione può cambiare durante la generazione della stampa (si pensi ad esempio all’espressione che rappresenta il numero di pagina: all’inizio della stampa tale espressione assumerà valore uno e crescerà durante la creazione delle pagine successive). Gli evaluationTime possibili sono i seguenti: Now È il valore predefinito. Significa che l’espressione deve essere valutata nell’istante in cui viene incontrata; Report Questo evaluationTime viene usato quanto si vuole posticipare la valutazione di un’espressione al completamento di un report; Page La valutazione viene posticipata al completamento della pagina; Column La valutazione viene posticipata al completamento della colonna; Group La valutazione viene posticipata al completamento del gruppo specificato assieme a questo evaluationTime; Reporting tool in ambiente Open Source - Pagina 36 di 84 Questo meccanismo della valutazione posticipata è decisamente utile in moltissime situazioni, la più diffusa delle quali è forse quella in cui è necessario stampare il numero di pagina corrente e quello totale (es. pagina x di n). La soluzione consiste nel creare due campi di testo, il primo con un espressione del tipo: “Pagina “ + $V{PAGE_NUMBER} + “di “ e tempo di valutazione “now”, il secondo, affiancato, con un’espressione simile “ “ + $V{PAGE_NUMBER} ma tempo di valutazione “report”. Il risultato finale sarà qualcosa di simile a… Pagina 3 di 24 Abbiamo appena visto i primi due piccoli esempi di espressioni. Ne parleremo tra poco, ma si può già notare come esse siano simili al linguaggio java con qualche piccola nuova accortezza sintattica. 3.3 Campi, variabili, parametri ed espressioni Ogni strumento di reportistica definisce un meccanismo per collegare i campi di un dataset (o di una struttura paragonabile, utilizzata come fonte dati) ai i campi del report. Solitamente questo binding è implicito ed è puramente basato sui nomi delle colonne presenti nel dataset. JasperReports impone che i campi della fonte dati vengano preventivamente dichiarati mediante la sintassi XML definita in questo frammento di DTD: <!ELEMENT field (fieldDescription?)> <!ATTLIST field name NMTOKEN #REQUIRED class (java.lang.Object | java.lang.Boolean | java.lang.Byte java.util.Date | java.sql.Timestamp | java.sql.Time java.lang.Double | java.lang.Float | java.lang.Integer java.io.InputStream | java.lang.Long | java.lang.Short java.math.BigDecimal | java.lang.String) "java.lang.String" Reporting tool in ambiente Open Source - Pagina 37 di 84 | | | | > <!ELEMENT fieldDescription (#PCDATA)> Ecco un esempio di dichiarazione dei campi di una query SQL: <queryString><![CDATA[select * from CLIENTI]]></queryString> <field name="COGNOME1" class="java.lang.String"/> <field name="NOME" class="java.lang.String"/> <field name="SESSO" class="java.lang.String"/> <field name="PROVINCIA" class="java.lang.String"/> <field name="TEL1" class="java.lang.String"/> <field name="TEL2" class="java.lang.String"/> L’elemento queryString non è obbligatorio, come non è necessario interrogare un database relazionale per generare una stampa con JasperReports, ma lo abbiamo volutamente inserito per esplicitare il fatto che i campi dichiarati in questa porzione di codice verranno recuperati mediante la query specificata. La necessità di dover dichiarare i nomi e i tipi dei campi, letti dalla fonte dati, ci da un’idea di come il linguaggio usato da JasperReports per le espressioni (nelle quali questi campi verranno utilizzati) sia fortemente tipizzato: si tratta infatti del linguaggio java (arricchito di qualche nuovo dettaglio sintattico). In maniera molto simile ai campi della data source, vengono dichiarate le variabili ed i parametri. Le variabili vengono utilizzate per effettuare i calcoli all’interno del report (come totali, subtotali, medie, ecc…). I parametri, invece, costituiscono una via parallela alla fonte dati per passare sotto forma di oggetti java informazioni dal programma chiamante al report. Le espressioni sono frammenti di codice java il cui risultato è sempre un oggetto. Un esempio di espressione booleana (utilizzabile nei campi che determinano se stampare o meno un elemento o una banda) è la seguente: new Boolean(true) L’espressione in se non è molto utile in quanto produce esattamente l’effetto di default (stampa sempre l’elemento), ma si noti come il risultato non sia il valore primitivo true, ma un oggetto Boolean. Reporting tool in ambiente Open Source - Pagina 38 di 84 Il tipo di ritorno delle espressioni è determinato dal contesto. Per quel che riguarda i campi di testo, i cui valori sono sempre determinati da un’espressione, è necessario specificarne il tipo tramite uno specifico attributo, (che quindi determinerà il tipo di ritorno dell’espressione). Per utilizzare nelle espressioni i campi della fonte dati, le variabili e i parametri, si utilizza la sintassi $F{Nome campo}, $V{Nome variabile} e $P{Nome parametro}. È necessario ricordare che questi sono sempre oggetti e mai tipi primitivi. Questo significa che se dobbiamo sommare due campi di tipo Integer e ritornarne il valore, l’espressione da usare sarà del tipo: new Integer( $F{Campo_intero_1}.intValue() + $F{Campo_intero_2}.intValue() ) Non essendoci in java l’overload degli operatori, è necessario, nella somma, estrapolare i valori primitivi dagli oggetti (in questo caso Integer) con la funzione intValue(), quindi sommarli e restituire nuovamente un oggetto Integer. Il tutto è un po’ macchinoso, ma con un minimo di nozioni di java si supera facilmente ogni ostacolo e se ne apprezza la potenza, essendo ammesso qualsiasi costrutto java. Qualora, infatti, si volesse implementare una forma di validazione dei dati, o calcoli particolari, è sufficiente scrivere una classe java dotata di un metodo statico per raggiungere velocemente il nostro obiettivo ed usare un’espressione del tipo…. MyClass.myMethod( $F{MyField}) L’esempio mostra come sia possibile operare sul campo MyField in qualsiasi modo utilizzando java. 3.4 L’interfaccia JRDataSource I dati da stampare possono essere ottenuti da diverse fonti come un database o un documento XML. Questi dati vengono presentati a JasperReports sempre sotto forma di uno speciale set di record utilizzando un’apposita interfaccia chiamata JRDataSource. Reporting tool in ambiente Open Source - Pagina 39 di 84 JasperReports viene distribuito con un diverse implementazioni di questa interfaccia pronte all’uso e in grado di “wrappare” ResultSet JDBC, TableModel (java swing), Collection di oggetti java, Array e Vector di oggetti, ecc… JasperReports, inoltre, è in grado di generare una stampa attingendo i dati senza l’ausilio di una classe JRDataSource, ma semplicemente utilizzando una query SQL opportunamente associata al report ed eseguita mediante una connessione JDBC procurata dall’applicazione che necessita la stampa. L’intrfaccia JRDataSource è veramente semplice. public interface JRDataSource { public boolean next() throws JRException; public Object getFieldValue(JRField jrField) throws JRException; } Come si vede, richiede l’implementazione di soli due metodi:next() e getFieldValue(), che prende come argomento un oggetto di tipo JRField. Anche ques’ultima classe (in realtà una nuova interfaccia) è veramente semplice: public interface JRField { public String getName(); public String getDescription(); public void setDescription(String description); public Class getValueClass(); } Di fatto l’uso di tale interfaccia si riduce ad un meccanismo semplice per associare il tipo di ritorno atteso al nome del campo richiesto. L’interfaccia JRDataSource permette, dunque, di enumerare dei record, costituiti da una serie di campi a cui è associato un nome ed un tipo. Nel caso più banale una JRDataSource potrebbe essere rappresentata da un Vector i cui record sono gli oggetti del vettore costituiti da un’unica colonna di tipo Object. Il valore del campo è l’oggetto memorizzato alla posizione corrente (ovvero la riga ottenuta mediante la chiamata a next()). Nel caso in cui venga raggiunta la fine del set di record, la chiamata a next restituisce il valore booleano false. Reporting tool in ambiente Open Source - Pagina 40 di 84 La somiglianza di questa interfaccia con quella di un ResultSet java, ci permette di capire perché l’implementazione della classe JRResultSetDataSource si riduca ad una sorta di convertitore di tipi SQL in tipi java. Eccone il codice (la parte in grigio evidenzia il codice relativo alla selezione della corretta classe java di presentazione del dato rispetto al tipo SQL posseduto)… public class JRResultSetDataSource implements JRDataSource { private ResultSet resultSet = null; public JRResultSetDataSource(ResultSet rs) { resultSet = rs; } public boolean next() throws JRException { boolean hasNext = false; if (resultSet != null) { try { hasNext = resultSet.next(); } catch (SQLException e) { throw new JRException("Unable to get next record.", e); } } return hasNext; } public Object getFieldValue(JRField field) throws JRException { Object objValue = null; if (field != null && resultSet != null) { Class clazz = field.getValueClass(); try { if (clazz.equals(java.lang.Object.class)) { objValue = resultSet.getObject(field.getName()); } else if (clazz.equals(java.lang.Boolean.class)) { objValue = new Boolean( resultSet.getBoolean(field.getName()) ); } else if (clazz.equals(java.lang.Byte.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) { objValue = null; } else { objValue = new Byte((String)objValue); } } else if (clazz.equals(java.util.Date.class)) { objValue = resultSet.getDate(field.getName()); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.sql.Timestamp.class)) { objValue = resultSet.getTimestamp(field.getName()); Reporting tool in ambiente Open Source - Pagina 41 di 84 if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.sql.Time.class)) { objValue = resultSet.getTime(field.getName()); if(resultSet.wasNull()) objValue = null; } } else if (clazz.equals(java.lang.Double.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) objValue = null; } else { objValue = new Double((String)objValue); } } else if (clazz.equals(java.lang.Float.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) objValue = null; } else { objValue = new Float((String)objValue); } } else if (clazz.equals(java.lang.Integer.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) objValue = null; } else { objValue = new Integer((String)objValue); } } else if (clazz.equals(java.io.InputStream.class)) { objValue = resultSet.getBinaryStream(field.getName()); if(resultSet.wasNull()) objValue = null; } } else if (clazz.equals(java.lang.Long.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) objValue = null; } else { objValue = new Long((String)objValue); } } else if (clazz.equals(java.lang.Short.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) objValue = null; } else { objValue = new Short((String)objValue); } } else if (clazz.equals(java.math.BigDecimal.class)) { objValue = Reporting tool in ambiente Open Source - Pagina 42 di 84 { { { { { { { resultSet.getString(field.getName()); if(resultSet.wasNull()) { objValue = null; } else { objValue = new BigDecimal((String)objValue); } } else if (clazz.equals(java.lang.String.class)) { objValue = resultSet.getString(field.getName()); if(resultSet.wasNull()) { objValue = null; } } } catch (Exception e) { throw new JRException( "Unable to get value for field '" + field.getName() + "' of class '" + clazz.getName() + "'", e); } } return objValue; } } 3.5 Integrare JasperReports in un progamma java Per concludere questo capitolo su JasperReports, analizziamo il codice necessario ad integrare un programma java con le funzionalità di stampa offerte da JasperReports. 3.5.1 Compilazione di un report Come precedentemente spiegato, una volta scritto il file XML che definisce la stampa, è necessario compilarlo per creare un file jasper. Il codice necessario ad effettuare questa operazione è il seguente: String xmlFileName = “test.xml”; String jasperFileName = “test.jasper”; try { JasperCompileManager.compileReportToFile( xmlFileName, jasperFileName); } catch (JRException jrex) { } Nuovamente ci troviamo di fronte a codice veramente banale. Il nostro file xml (nell’esempio “test.xml”) viene caricato dal CompilerManager, Reporting tool in ambiente Open Source - Pagina 43 di 84 convertito in un file sorgente java e serializzato in un file jasper (nell’esempio “test.jasper”). È tuttavia possibile controllare tutti i passi di questo processo impostando diverse proprietà di sistema, tra le quali ricordiamo: jasper.reports.compile.temp La directory in cui creare il file java temporaneo; jasper.reports.compile.keep.java.file Per evitare che il file java generato venga cancellato ad operazione conclusa jasper.reports.compiler.class Per specificare la classe di tipo JRCompiler da utilizzare per la compilazione È inoltre possibile abilitare o meno la validazione XML del file sorgente ed impostare un classpath personalizzato in fase di compilazione. Il risultato finale sarà comunque sempre un file jasper. Si noti che i file compilati non sono compatibili tra le diverse versioni di JasperReports. Questa scelta ha permesso a JasperReports di svincolarsi dalle complicazioni necessarie al mantenimento di una compatibilità, a livello di binario, verso il basso, ma ha tuttavia spiazzato in molte occasioni gli utenti, costretti a ricompilare le stampe ad ogni upgrade. La compatibilità rimane comunque a livello di codice XML (sempre verso il basso, ma non sempre verso l’alto, nel senso che in alcune versioni sono stati aggiunti alcuni tag non riconosciuti dalle versioni precedenti). 3.5.2 Esempio di creazione di una JRResultSetDataSource Come esempio di creazione di una fonte dati, abbiamo utilizzato una delle più comuni e semplici da utilizzare: la JRResultSetDataSource, che permette di “wrappare” un resultset java ottenuto mediante una query SQL. Class.forName( jdbDriver ); Connection conn = DriverManager.getConnection( jdbcUrl, jdbcUser, jdbcPassword); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); Reporting tool in ambiente Open Source - Pagina 44 di 84 JRDataSource jrds = new JRResultSetDataSource(rs); La semplicità di utilizzo è veramente estrema e non varia molto con altri tipi di JRDataSource. Infatti, il compito più difficile risulta essere l’eventuale sviluppo della fonte dati, ma come già visto, in generale JasperReports è in grado di sopperire alla maggior parte delle esigenze mediante le JRDataSource predefinite. 3.5.3 Generazione della stampa Per la generazione della stampa, sono necessarie due cose: il file jasper e una fonte dati (ovvero un oggetto di tipo JRDataSource o una connessione JDBC aperta verso un database). Quello che produrremo sarà un’istanza dell’oggetto Print, una struttura dati intermedia utilizzata da JasperReports che ci servirà per esportare la stampa in un qualche formato specifico, piuttosto che visualizzarla a video. java.util.HashMap map = new java.util.HashMap(); map.put("MyParam",new Integer( 100 ) ); String jasperFile = "myreport.jasper"; dori.jasper.engine.JasperPrint print=null; dori.jasper.engine.JasperReport report = d ori.jasper.engine.JasperManager.loadReport( cl.getResourceAsStream(jasperFile)); print = dori.jasper.engine.JasperFillManager.fillReport( report , map, new JREmptyDataSource()); Questa volta il codice è stato un po’ arricchito per evidenziare alcune altre possibilità messe a disposizione della libreria. Nella prima riga viene instaziata una HashMap, per passare al motore che genera la stampa un insieme di coppie nome/oggetto: i parametri. Questa volta abbiamo deciso di caricare autonomamente il file jasper. Il risultato è una nuova istanza della classe JasperReport, mediante la quale è possibile accedere a tutta la struttura del report. È possibile, mediante questo oggetto, effettuare al volo piccole modifiche alla stampa senza la necessità di modificare sorgenti e di ricompilarli. Il metodo chiave è fillReport della Reporting tool in ambiente Open Source - Pagina 45 di 84 classe JasperFillManager. Come datasource abbiamo utilizzato la sorgente dati nulla: JREmptyDataSource(), utile in moltissime situazioni. 3.5.4 Visualizzazione di una stampa a video Siamo arrivati così al punto di voler visualizzare la stampa a video. Per farlo utilizzeremo il nostro oggetto Print in questo modo: dori.jasper.view.JasperViewer.viewReport( print ); L’effetto sarà quello di veder aprirsi a video un finestra con l’anteprima della nostra stampa. 3.5.5 Esportazione di una stampa in un file Infine, presentiamo un esempio di codice relativo all’esportazione delle stampe in formati standard come pdf e html. dori.jasper.engine.JRExporter exporter = new dori.jasper.engine.export.JRPdfExporter(); String pdfFileName = “myreport.pdf”; exporter.setParameter( dori.jasper.engine.JRExporterParameter.OUTPUT_FILE_NAME, pdfFileName); exporter.setParameter( dori.jasper.engine.JRExporterParameter.JASPER_PRINT,print); exporter.exportReport(); Come si può notare, per esportare una stampa in un determinato formato, è necessario appoggiarsi ad un “driver” o (nel gergo di JasperReports) ad un exporter specifico. Le direttive di esportazione vengono impostate come parametri sulla classe exporter (nel codice presentato viene impostato il nome del file pdf da creare e viene passato l’oggetto print che dovrà essere trasformato in pdf). Ogni exporter può definire un proprio insieme di nomi di parametri o appoggiarsi (come in questo caso) alle costanti definite nella classe JRExporterParameter. Reporting tool in ambiente Open Source - Pagina 46 di 84 Addentrarci oltre nelle funzionalità e capacità di JasperReports esula dagli scopi di questa tesi. Tuttavia, molti degli argomenti trattavi in questo capitolo verranno ripresi nel capitolo successivo, nel quale parleremo di iReport, in buona sostanza un programma che facilita la maggior parte dei processi di sviluppo per JasperReports visti fino a questo momento. Reporting tool in ambiente Open Source - Pagina 47 di 84 4. iReport iReport nacque ufficialmente il 9 ottobre 2002, quando venne registrato come progetto sul sito Sourceforge.net, la culla della maggior parte dei programmi open source oggi disponibile. In realtà lo sviluppo vero e proprio iniziò circa qualche mese prima. Allora stavo lavorando ad un software web-oriented basato su servlet Java. Il committente aveva espresso insistentemente l’esigenza di un numero sostanzioso di report adatti alla stampa. Le pagine web, infatti, hanno spesso la caratteristica di non rendere le informazioni stampate su carta chiare e leggibili quanto quelle visualizzare a video. Ritenemmo il pdf il formato ideale per produrre i report e iniziai a cercare delle librerie che potessero facilitarmi il lavoro. Finii, come capita a chiunque cerchi con un motore di ricerca le parole chiave “pdf” e “java”, sul sito di iText, la più autorevole libreria java open source per la produzione di documenti pdf. Una ricerca più approfondita permise di evidenziare altri software che facevano al caso mio: si trattava di tre strumenti di reportistica java open source: i già citati DataVision, JasperReports e JFreeReport. Così, dopo una rapido test dei tre strumenti di reportistica, decisi di adottare JasperReports quale motore per le stampe. L’impatto iniziale, in realtà, non fu dei migliori a causa di una documentazione appena sufficiente a capire i meccanismi di funzionamento della libreria (carenza a cui Teodor Danciu, l’autore di JasperReports, rimediò presto con la pubblicazione on line di un manuale dai contenuti essenziali, ma espressi in modo chiaro e diretto, e venduto ad un prezzo più che accettabile). Non furono di grande aiuto nemmeno Reporting tool in ambiente Open Source - Pagina 48 di 84 gli strumenti allora disponibili per la creazione visuale delle stampe, anche se gli sforzi fatti da Jackie Manning, autore di JasperDesign, ed Eric Swenson con JasperEdit ed OpenReports, hanno contribuito in maniera determinante alla diffusione di JasperReports (spingendo anche me ad adottare questa libreria). Così decisi di scrivere iReport, ispirandomi allo stesso JasperDesign. Inizialmente iReport doveva essere utilizzato solo internamente alla società presso cui stavo lavorando. Fu così che decisi di svilupparlo usando Microsoft Visual J++. Questa scelta accese una sorta di guerra di religione quando iReport fu reso pubblico. In realtà la velocità con cui è possibile produrre un programma scritto con il suddetto defunto ambiente Microsoft è tuttora incomparabile a qualsiasi altro sistema di sviluppo (a mio modestissimo avviso). La riprova di questo fu lo stesso iReport, realizzato in versione 0.0.1 in meno di un mese di lavoro a tempo perso! (La versione java sviluppata successivamente ha richiesto un impegno decisamente superiore in termini di ore di lavoro.) La scelta, inoltre, era dettata da questioni prestazionali. Le WFC (Windows Fondation Classes), ovvero le classi java offerte da Microsoft per utilizzare la GUI nativa di Windows (ed in generale tutte le API win32), offrivano prestazioni incredibilmente superiori rispetto ai lenti ed esosi, in termini di memoria, componenti swing. Oggi la mia opinione si è appiattita alla media: fu una scelta scellerata. Tuttavia senza quella scelta, credo che iReport oggi non sarebbe quello che è. Infatti, pur destando diffidenza tra gli utenti di JasperReports, iniziò a guadagnarsi in poco tempo il titolo di miglior editor visuale per i file jasper. Un utente di iReport, Nathan W. Phelps espose così il suo punto di vista: "Let me (a random person) jump in here. While I do think that using J++ is a bit odd, I've been looking for a native Win32 Jasper designer. I have tried JasperEdit, JasperDesigner and the one for Eclipse all unsatisfactory. My company has a "no Java on the client side" policy as well. So the fact that this thing is in J++ could help me out. I just downloaded the source and ran it through the Visual Studio .NET J# upgrade wizard which ran Reporting tool in ambiente Open Source - Pagina 49 di 84 into very few problems. In other words, with a bit of work I can get this thing running on pure .NET using J#. That is pretty cool, and just may get me where I need to go!" [Predi me (una persona a caso). Pur ritenendo che il J++ sia un po’ superato, stavo cercando un designer per Jasper. Ho provato JasperEdit, JasperDesign e quello per Eclipse rimanendo insoddisfatto. La mia società segue una politica del tipo “no Java sulla parte client”. Così il fatto che questa cosa (iReport n.d.t.) sia in J++ potrebbe aiutarmi. Io ho solo scaricato i sorgenti e fatti girare con l’upgrade del Visual Studio .NET J#, che produce pochissimi problemi di compilazione. In altre parole con un po’ di lavoro, si potrebbe far girare questa cosa sotto .NET usando J#. È veramente forte e mi porta nella direzione in cui voglio andare!] Ho rilasciato ben dieci versioni di iReport per win32: dalla 0.0.1 alla 0.1.0, quest’ultima rilasciata il 19 aprile del 2003, riscuotendo un buon successo: complessivamente oltre 13.000 download ad oggi, settembre 2003. Il 5 maggio postai un messaggio sul forum di JasperReports provocatoriamente intitolato: iReport goes to 100% pure java! Al messaggio seguirono diverse risposte di entusiasmo ed incoraggiamento. Una versione java di iReport era quello che tutti gli utenti si aspettavano; iReport aveva guadagnato sufficiente popolarità da rendere il salto di qualità obbligatorio. Iniziai così il porting non senza difficoltà. Cercai di riutilizzare quanto più codice fosse possibile, ma in realtà il vecchio codice Visual J++ era veramente orribile e tutte le routine grafiche avevano prestazioni assai poco confortanti quando adattate al supporto per la grafica di java. Tuttavia il 14 giugno vide la luce la prima versione interamente scritta in java: la 0.2.0, praticamente inutilizzabile (se comparata alla versione 0.1.0 per win32). L’ultima versione ad oggi, la 0.2.2, ha portato quasi a parità in merito a funzionalità la versione per win32 (non più supportata) e la versione java. Ma la strada da compiere è ancora lunga per arrivare ad una versione stabile. Tuttavia già oggi iReport rappresenta una valida alternativa a sistemi di reportistica commerciali; la scelta è dettata in particolare da motivazioni Reporting tool in ambiente Open Source - Pagina 50 di 84 economiche, dato l’elevato costo delle alternative commerciali, spesso vincolate da macchinose licenze basate su numero di client e volumi di stampa. La popolarità di iReport è molto cresciuta con la nascita della versione java. Sfortunatamente durante il periodo esatto di uscita della versione 0.2.0 (per l’appunto la prima versione java di iReport) nel giugno 2003, le Pagine viste e num. di download (fonte SourceForge.net) N. di download/pagine viste 16000 14000 12000 10000 8000 6000 4000 2000 Oc t No obe ve r 20 De mb 02 ce er 2 m 00 b Ja er 2 2 nu 00 Fe ary 2 br 20 ua 03 ry M 20 ar 03 ch 2 Ap 003 ril 2 M 003 ay 2 Ju 003 ne 2 Ju 003 A ly Se ugu 200 pte st 3 m 200 be 3 r2 00 3 0 Mesi (da ottobre 2002 a settembre 2003) Fig. 4.1: Statistiche progetto iReport (fonte SourceForge.net) statistiche relative al download di SourceForge erano fuori uso (si noti la linea rosa dei download nel grafico in figura 4.1 in corrispondenza del mese di giugno). Tuttavia il numero di contatti avuti sulle pagine web del sito del progetto indicato un interesse esploso proprio nello stesso periodo. Reporting tool in ambiente Open Source - Pagina 51 di 84 Sempre relativamente al sito del progetto sono disponibili anche le statistiche registrate mediante un servizio gratuito chiamato CQ Counter. Accessi al sito ireport.sf.net (fonte CQ Counter) 12000 Numero di contatti 10000 8000 6000 4000 2000 Ap ril 20 03 Ju ne 20 03 Au gu st 20 03 Oc tob er 20 02 De ce m be r2 00 2 Fe br ua ry 20 03 0 Mesi (da ottobre 2002 a settembre 2003) Fig. 4.2: Statistiche progetto iReport (fonte CQ Counter) Si noti che i dati di CQCounter si riferiscono alla sola home page del sito http://ireport.sf.net. Ad oggi (settembre 2003) il numero di download ha superato le 20.000 unità destinate ad aumentare velocemente. Per quel che riguarda le statistiche relative al Sistema Operativo utilizzato, allo stato attuale le informazioni ricavate dall’accesso al sito dicono che il 76,10% degli utenti utilizza Windows 2000/XP, seguito da Linux (8,83%), Win 98 (6,18%), Win NT (5,91%), Mac OSX (1,11%) . Il resto degli utenti utilizzano sistemi quali SunOS, FreeBSD, AIX, ecc… È chiaro che il bacino di utenza accumulato nei mesi in cui iReport era disponibile solo per win32 è ancora quello più numeroso, ma sicuramente destinato ad diminuire percentualmente rispetto all’utenza Linux. Reporting tool in ambiente Open Source - Pagina 52 di 84 Curiose, infine, sono le statistiche relative alla lingua del browser utilizzato per collegarsi al sito di iReport: queste cifre danno un’idea di quanto iReport sia diffuso. Lingua Contatti web English 32409 Portuguese 3247 Italian 3176 French 2959 Spanish 2877 Japanese 876 Korean 773 Polish 723 Thai 570 Dutch 526 Russian 473 German 454 Swedish 385 Hungarian 268 Danish 259 Croatian 188 Turkish 178 Finnish 163 Bulgarian 142 Norwegian 142 Greek 125 Slovak 101 Czech 95 Slovenian 75 Icelandic 63 other/unknown 58 Indonesian 52 Hebrew 48 Romanian 46 Estonian 42 Ukrainian 40 Arabic 28 Serbian 26 Interlingue 19 Reporting tool in ambiente Open Source - Pagina 53 di 84 Catalan 17 Lithuanian 17 Malay 17 Hindi 15 Afrikaans 15 Latvian Lettish 12 Persian 10 Macedonian 7 Basque 4 Galician 3 Byelorussian (Belarussian) 2 Telugu 2 Georgian 1 Serbo-Croatian 1 L’8 aprile un utente coreano di nome Yumi Kim scrive questo messaggio sul forum di iReport: iReportPlus, Newly developed web reporting solution, was released. This solution is developed based on JasperReports and iReport that are well-known open-source web reporting solutions. Anybody who want to make web based reports easily and rapidly is able to use this solution as a freeware for non-commercial use. iReportPlus made by iMobile Technology Inc. has some advanced features as follows : - Report Designer with Wizards - Report Export as Jasper, Excel and PDF - Database Explorer - Server Explorer & Preview - Local Data Explorer iReportPlus also provides many functions other than those listed above. You can get more detailed information and download it from http://www.ireportplus.com/ For technical support, please feel free to contact us. L’ingenuità del messaggio ha dell’incredibile. Il software citato nel messaggio, iReportPlus, è in realtà iReport con qualche piccola modifica estetica ed integrato in un sistema più ampio per la pubblicazione dei report utilizzando un database Oracle. Ironica la frase “anybody […] is able to use this solution as a freeware for non-commercial use”. C’è da Reporting tool in ambiente Open Source - Pagina 54 di 84 chiedersi quanti, per scopi non commerciali, necessitino di un sistema distribuito di reportistica basato su Oracle… Passano poche ore e la comunità di iReport si scaglia contro la società coreana con messaggi di condanna contro l’evidente violazione della licenza GPL con cui iReport è distribuito. La violazione viene segnalata alla Free Software Fondation che mi suggerisce di tentare di risolvere la cosa cercando di spiegare la gravità dell’accaduto alla società coreana mediante un’e-mail dai toni contenuti. Il messaggio sortisce solo in parte gli effetti desiderati, strappando la promessa di un tempestivo rilascio di iReportPlus sotto i termini della licenza GPL. Nessun successivo rilascio di iReportPlus (tanto meno in licenza GPL) vedrà mai la luce (tuttavia il sito di iReportPlus è tuttora attivo). Fortunatamente esistono al mondo società commerciali in grado di capire la sottile differenza presente tra il termine free ed il termine open source. Ma soprattutto in grado di sfruttare le altissime potenzialità offerte dal software open source in genere. A tale proposito vorrei aprire una piccola parentesi. Non so per quale paradossale ragione, il denaro ricevuto inaspettatamente (o quello vinto) è più apprezzato di quello guadagnato. Forse perché il primo viene ottenuto senza un vero sforzo apparente che ne controbilanci il valore stesso. Questo è il motivo per il quale un software open source non solo è gratis entro i termini della licenza d’uso con cui è distribuito, ma spesso e volentieri il suo prezzo è estremamente conveniente (dal punto di vista economico) al di fuori di tali termini: infatti qualsiasi offerta inaspettata proposta ad un programmatore per ottenere una licenza non GPL del suo software OpenSource verrà ben considerata, e la trattazione del prezzo sarà mediamente breve e vantaggiosa per entrambe le parti, sempre. Una società milanese, Tecnes Milano, mi chiese di fargli un’offerta per completare in breve tempo la gestione dei font in iReport, modifiche che sarebbero state rilasciate sotto licenza GPL e i cui diritti sarebbero rimasti comunque miei. In pratica l’offerta era una sorta di incentivo allo sviluppo di funzionalità a cui Tecnes era interessata. Le funzionalità in questione furono rilasciate dopo meno di 48 ore, lasciando Tecnes stupita per due ragioni: in primo luogo per il brevissimo tempo intercorso tra la richiesta di Reporting tool in ambiente Open Source - Pagina 55 di 84 un offerta e lo sviluppo delle funzionalità richieste (inaspettata da un programma privo di supporto esplicito, ma soprattutto ineguagliabile da un qualsiasi tipo di supporto commerciale), dall’altra dall’esiguo costo del lavoro (tipico quando lo sviluppo viene realizzato per passione e non solo per denaro). Prima di completare questa lunga introduzione ad iReport, non posso non citare Mark Rhodes di Sydran Services, LLC., che senza avanzare alcuna richiesta specifica, ma solo a titolo di ringraziamento per l’opera svolta (e per i soldi fatti risparmiare alla propria società con l’adozione di iReport e JasperReports quale sistema di reportistica), mi fece una gradita donazione quale incentivo allo sviluppo dell’allora primitivo, ma già promettente, iReport. 4.1 iReport e JasperReports iReport non rappresenta da solo una soluzione di reportistica, si tratta piuttosto di uno strumento molto evoluto per lo sviluppo, il test e l’esportazione di report creati ed utilizzabili mediante la libreria JasperReports. Grazie alla grande quantità di funzionalità di iReport, come la possibilità di Fig.4.3: Integrazione di JasperReports con iReport Reporting tool in ambiente Open Source - Pagina 56 di 84 collegarsi a database relazionali mediante JDBC, e la capacità di generare ed esportare autonomamente i report, questo programma può essere utilizzato, oltre che come strumento di sviluppo, anche come strumento di reportistica standalone. IReport è in grado di leggere report definiti mediante XML e file compilati in formato jasper. Questi documenti possono essere modificati e risalvati in XML o compilati a sua volta in file jasper. Grazie ad un evoluto sistema di gestione degli errori di compilazione, iReport facilita molto la vita allo sviluppatore che non dovrà scorrere centinaia di righe di codice XML per correggere i propri errori, ma sarà sufficiente un colpo di mouse per posizionarsi direttamente sull’espressione o il campo che ha generato l’errore. IReport supporta tutti i tag XML definiti da JasperReports ad eccezione dell’elementGroup, un particolare tag per controllare il ridimensionamento di alcuni elementi rispetto ad altri. 4.2 L’interfaccia principale L’interfaccia di iReport si è evoluta molto nel passaggio tra la versione 0.1.0 e la versione 0.2.0, scritta in puro java utilizzando swing. La finestra principale è suddivisa in quattro parti: la barra dei menu con la toolbar in alto, l’area di navigazione a destra, l’area di lavoro con le finestre dei documenti al centro e la console per la visualizzazione dei messaggi in basso. La gestione delle finestre interne ricalca quella tipica dei programmi Windows, con la possibilità di sfruttare al massimo l’area dell’MDI container (caratteristica non nativa dell’interfaccia swing). Lo strumento di navigazione è utilizzato sia per visualizzare l’elenco dei documenti attualmente aperti, con l’indicazione mediante un’opportuna icona dello stato del documento (salvato o “sporco”, cioè potenzialmente modificato1), sia per visualizzare la struttura ad albero degli elementi che 1 Attualmente IReport (versione 0.2.2) non è ancora in grado di determinare se un documento sia stato o meno modificato, non essendo tenuta traccia di tutte le possibili modifiche apportabili al documento. Reporting tool in ambiente Open Source - Pagina 57 di 84 compongono il report (figura 4.5). Mediante questi strumenti è possibile portare in primo piano il documento da modificare o selezionare in Fig.4.4: Interfaccia principale di iReport Fig.4.5: Struttura del documento maniera rapida uno o più elementi del documento corrente. Reporting tool in ambiente Open Source - Pagina 58 di 84 Le caratteristiche di un nuovo documento (menu File->New document), vengono richieste mediante un’apposita finestra di dialogo (figura 4.6). Fig.4.6: Proprietà del report È possibile specificare le dimensioni della stampa, l’orientamento del foglio, i margini e molte altre informazioni esposte in dettaglio nella tabella seguente. Report name Nome interno della stampa Preset sizes Questa combobox permette di selezionare dimensioni di documento predefinite Width e Height Larghezza e altezza della pagina. Le misure possono essere espresse in divere unità di misura (compreso il pixel con risoluzione fissa a 75dpi) Orientation Orientamento della pagina Page margin In questa scheda vengono specificati i margini superiore, inferiore e laterali. Columns In questa scheda viene specificato il numero di colonne in cui dividere la pagina per visualizzare il dettaglio, la larghezza della singola colonna e la loro distanza. Scriptlet In questa scheda viene specificato il nome dell’eventuale classe scriptlet da utilizzare con il report. La classe deve estendere la classe JRAbstractScriptlet Reporting tool in ambiente Open Source - Pagina 59 di 84 e permette di definire codice java da eseguire all’occorrenza di diversi eventi durante la generazione della stampa quali il cambio di gruppo, il cambio di pagina, il passaggio al successivo record di dettaglio, ecc… More… In questa scheda è possibile definire se la banda del titolo e la banda del sommario debbano essere stampate su una pagina a parte, l’ordine in cui stampare i record (verticale o orizzontale nel caso si abbia più di una colonna di dettaglio a disposizione), il comportamento del report in caso di assenza di dati e l’encoding del file XML (di default UTF8). Appena creato, il nuovo documento si presenta come un foglio bianco diviso nelle sette bande principali di JasperReports. A questo punto è possibile iniziare a lavorare sulla nostra stampa aggiungendo gli elementi, modificando le bande, impostando formule ed espressioni. 4.3 Bande ed elementi Il report vuoto crea le sette bande principali di JasperReports impostate ad un’altezza predefinita compresa tra 30 e 100 pixel. Selezionando il menu View->Bands è possibile accedere alla finestra di gestione della bande Fig.4.7: Gestione delle bande del report Reporting tool in ambiente Open Source - Pagina 60 di 84 (figura 4.7), mediante la quale potremo definirne le caratteristiche di ogni singola sezione: l’altezza esatta (in pixel), la possibilità di spezzare la banda in fase di stampa (Split allowed) e l’espressione booleana che ne determini la visibilità (se l’espressione è nulla, la banda sarà sempre visibile). L’altezza delle bande è inoltre modificabile visualmente trascinando le linee di demarcazione delle stesse. La stessa operazione di trascinamento effettuata tenendo premuto il tasto SHIFT permette di agire sul margine superiore della banda più bassa rispetto alla linea di demarcazione, dando la possibilità di “scoprire” bande di altezza nulla. Per inserire gli elementi nelle bande è necessario selezionare uno dei seguenti strumenti posti sulla toolbar e descrivere un rettangolo nella banda desiderata. Linea Rettangolo Rettangolo con angoli arrotondati Ellisse Immagine Testo statico Campo di testo (definito con un’espressione) Sottoreport Grafico (non ancora implementato nell’attuale versione 0.2.2) L’elemento appena creato viene associato alla banda nella quale si trova il vertice superiore sinistro. Sarà possibile modificare la banda di appartenenza dell’elemento mediante la finestra delle proprietà dell’elemento. È possibile richiamare tale finestra con un doppio click sull’elemento (o gli elementi) da modificare, o selezionando il menu File>Element Properties. Le caratteristiche degli elementi possono essere raggruppate secondo la gerarchia in figura 4.8, che rispecchia la gerarchia delle classi java che implementano gli elementi. Reporting tool in ambiente Open Source - Pagina 61 di 84 Elemento Elemento grafico Rettangolo Linea Immagine Grafico Elemento di testo Testo statico Campo di testo Sottoreport Fig. 4.8: Gerarchia degli elementi grafici gestiti da iReport La finestra delle proprietà degli elementi è organizzata a schede, e ad ognuno dei rettangoli presenti in figura 4.8 corrisponde una scheda. La scheda Common visualizza le caratteristiche comuni a tutti gli Fig.4.9: Scheda “Common” elementi, ovvero: Band: la banda a cui l’elemento è associato; Top: posizione verticale rispetto alla base superiore della banda; Left: posizione orizzontale rispetto il lato sinistro della banda; Reporting tool in ambiente Open Source - Pagina 62 di 84 Width: larghezza dell’elemento; Height: altezza dell’elemento; Foreground: colore primario; nel caso di elementi grafici è il colore con il quale viene disegnata la cornice, mentre nel caso di elementi testuali è il colore usato per il testo; Background: colore di riempimento dell’elemento; ha effetto solo se la proprietà transaparent è disattivata; Transparent: se attivata, rende lo sfondo dell’oggetto trasparente; Remove line when blank: questa proprietà permette di eliminare una porzione di documento qualora nessun oggetto debba essere stampato nella fascia orizzontale che include questo oggetto (qualora l’elemento non debba essere stampato); Print in first whole band: questa proprietà forza la stampa dell’elemento nella prima banda stampata in una nuova pagina (o su una nuova colonna); solitamente si usa quando è stata disabilitata la stampa di valori ripetuti, ma si vuole ripetere il valore su pagine (o colonne) nuove; Print when detail overflows: permette di ristampare un elemento su una nuova pagina (o colonna) qualora la banda a cui appartiene non è stata interamente stampata nella precedente pagina (o colonna). Print repeated values: permette di abilitare o meno la stampa di valori ripetuti del campo; Position type: permette di definire il tipo di posizione dell’elemento rispetto alle variazioni di altezza della banda; le possibili opzioni sono: Float: impone all’elemento di slittare verso il basso se “spinto” da altri elementi che lo precedono; FixRelativeToTop: impone che l’elemento venga stampato sempre alla stessa altezza rispetto alla base superiore della banda; FixRelativeToBottom: impone che l’elemento venga stampato sempre alla stessa altezza rispetto alla base inferiore della banda; Print When Group Changes: questa opzione permette di stampare l’oggetto qualora cambi il valore dell’espressione associata al gruppo specificato; Reporting tool in ambiente Open Source - Pagina 63 di 84 Print When Expression: tramite questa proprietà è possibile impostare un’espressione booleana che determinerà la visibilità dell’elemento; il valore predefinito, nel caso non venga inserita nessuna espressione, è true; Fig.4.10: Scheda “Graphics Element” Gli elementi grafici (scheda Graphics Element) integrano le proprietà comuni con altre tre caratteristiche: Pen: è lo spessore del bordo disegnato attorno all’elemento; StretchType: è il tipo di deformazione che l’elemento subisce in base alla posizione di altri oggetti o alla variazione dell’altezza della banda; i possibili valori sono: NoStretch: nessun tipo di deformazione RelativeToTallestObject: la deformazione è basata sull’oggetto più vicino (si usa, ad esempio, quando si vuole incorniciare un altro elemento di dimensione variabile come un campo di testo, mediante un rettangolo) RelativeToBandHeight: la deformazione è proporzionale all’altezza della banda (usato ad esempio quando si usano delle linee come separatori di colonna); Fill: è il tipo di riempimento da eseguire qualora l’elemento non sia trasparente; attualmente l’unico valore ammesso è Solid. La scheda Line permette di definire la direzione della linea (LineDirection) che può assere di tipo TopDown (\) o BottomUp (/). Le coordinate della linea sono ricavate dalla posizione e dalla dimensione dell’elemento, sufficienti a descrivere anche l’elemento rettangolo. Unica Reporting tool in ambiente Open Source - Pagina 64 di 84 Fig.4.11: Scheda “Line” Fig.4.12: Scheda “Rectangle” caratteristica aggiuntiva di quest’ultimo (scheda Rectangle) è il raggio di curvatura degli angoli qualora li si vuole arrotondati (il Radius). Fig.4.13: Scheda “Image” La scheda Image completa la serie degli elementi grafici. Image Expression: è un’espressione che ritorna il tipo definito in Image Expression Class; se il tipo è String, l’espressione viene trattata come un nome di file; mediante il pulsante “Find…” è possibile caricare un file immagine e produrre l’espressione che ne rappresenta il percorso; Image Expression Class: è la classe di ritorno dell’espressione; Scale Image: definisce come l’immagine debba adattarsi al riquadro nella quale è contenuta; i possibili valori sono: Clip: l’immagine viene tagliata se più piccola dell’elemento nel quale è contenuta; FillFrame: adatta l’immagine alle dimensione dell’elemento Reporting tool in ambiente Open Source - Pagina 65 di 84 RetainShape: adatta l’immagine alle dimensioni dell’elemento mantenendo le proporzioni originali; Using Cache: se selezionato, JasperReports manterrà in memoria l’immagine durante la generazione della stampa evitando di ricaricarla ogni volta venga richiesto; Vertical Alignment: permette di specificare l’allineamento verticale dell’immagine rispetto al rettangolo definito dall’elemento; i possibili valori sono: Left,Center e Right; Horizontal Alignment: permette di specificare l’allineamento orizzontale dell’immagine rispetto al rettangolo definito dall’elemento; i possibili valori sono: Top, Middle e Bottom; Evaluation Time: il concetto di evaluation time è stato spiegato nel capitolo su JasperReports; rappresenta il tempo al quale deve essere valutata un’espressione (in questo caso l’Image Expression); i possibili valori sono sempre: Now la valutazione dell’espressione è immediata; Report: la valutazione dell’espressione viene posticipata al raggiungimento dell’ultimo record; Page: la valutazione dell’espressione viene posticipata al successivo cambio di pagina; Column: la valutazione dell’espressione viene posticipata al successivo cambio di colonna; Group: la valutazione dell’espressione viene posticipata al successivo cambio del valore dell’espressione associata al gruppo definito nella proprietà Evaluation Group. Reporting tool in ambiente Open Source - Pagina 66 di 84 Tutti i campi di testo possiedono le caratteristiche visualizzate nella scheda Font: Fig.4.14: Scheda “Font” Fig.4.15: Scheda “Static Text” Report Font: è il riferimento alla definizione di un font a livello di report; Font Name: è il nome di un font di sistema (o java); la combobox visualizza la lista dei font disponibili sulla particolare macchina; Size: è la dimensione del carattere; PDF Font Name: qualora si intenda stampare i report in PDF, mediante questo campo è possibile specificare un font PDF predefinito o selezionare la voce “External TTF Font” per specificare un font di tipo TTF; TrueType Font: permette di selezionare un font TTF da utilizzare per la stampa del campo in PDF; Bold, italic, underline, Strike Trough: definiscono l’aspetto del font; Line Spacing: l’interlinea da usare per il testo (Single, 1_1_2 o Double); Horizontal Align: permette di definire l’allineamento orizzontale del testo, che potrà essere Left, Center, Right e Justified. Vertical Align: permette di definire l’allineamento verticale del testo, che potrà essere Top, Middle e Bottom; PDF Embedded specifica se il font usato debba essere incorporato nel file pdf; PDF Encoding: specifica il set di caratteri da utilizzare per interpretare la stringa da stampare; Reporting tool in ambiente Open Source - Pagina 67 di 84 Oltre a queste caratteristiche, il campo di testo statico ha un’unica proprietà aggiuntiva: il testo da stampare. Si noti che in questo caso il testo non è rappresentato da un’espressione java, ma da una semplice stringa di testo. Fig.4.16: Scheda “TextField” I campi di testo dinamici oltre ai già citati Expression Class, Evaluation Time ed Evaluation Group, possiedono le proprietà: StretchWithOverflow: permette la crescita verticale del campo in caso di necessità (come testi molto lunghi); Blank When Null: permette di non stampare il campo se il risultato dell’espressione è null; Pattern: è un metodo molto utile mediante il quale è possibile formattare numeri e date con espressioni del tipo “€#,###,###.00” (es. €1.234.567,00) o del tipo “dd/MM/yyyy” (es. 10/12/2003). Textfield Expression: l’espressione che determina il valore del campo; Fig.4.17: Scheda “Subreport 1” Fig.4.18: Scheda “Subreport 2” Reporting tool in ambiente Open Source - Pagina 68 di 84 deve ritornare il tipo specificato in Textfield Expression Class; Le schede relative al sottoreport sono due. Parameter Map Expression: rappresenta un espressione utilizzabile per indicare una classe di tipo Map contenente parametri da passare al sottoreport. Connection/Datasource Expression: mediante questa combobox è possibile selezionare il criterio di collegamento del report master al sottoreport: il collegamento può avvenire tramite il passaggio di una connessione JDBC aperta (ad esempio quella passata al report master dal programma chiamante e memorizzata nel parametro predefinito $P{REPORT_CONNECTION}), oppure tramite il passaggio di una JRDataSource o ancora si puo non voler esprimere nessun tipo di collegamento; Subreport Expression: specifica il nome del sottoreport o un’istanza della classe JasperReport (in accordo con il valore specificato in Subreport Expression Class); Subreport Parameters: è possibile creare una serie di parametri da passare al sottoreport e valorizzabili in maniera dinamica mediante normali espressioni java (un uso classico è il passaggio del codice del record padre da utilizzare per il recupero di record correlati da stampare nel sottoreport); Esiste, infine, una scheda speciale chiamata Hyper Link utilizzabile per i Fig.4.19: Scheda “Hyper Link” Reporting tool in ambiente Open Source - Pagina 69 di 84 campi di testo e le immagini, mediante la quale è possibile specificare dei link ipertestuali (da utilizzare nei documenti pdf). Anchor Name Expression: attribuisce all’elemento corrente un nome da utilizzare come link per eventuali collegamenti; Hyperlink Type: definisce il tipo di link: None: nessun tipo; Reference: riferimento ad un URL esterno (ad esempio una pagina web); LocalAnchor: riferimento ad un link interno al documento; LocalPage:riferimento ad un numero di pagina del documento corrente; RemoteAnchor: riferimento ad un link in un documento pdf esterno; RemotePage: riferimento ad una pagina di un documento pdf esterno; L’uso dei campi Hyperlink Reference Expression, Hyperlink Anchor Expression e Hyperlink Page Expression è condizionato dalla scelta del tipo di link. In generale Hyperlink Reference Expression contiene sempre il riferimento al file a cui puntare per soddisfare il link. Attualmente è in fase di sviluppo l’elemento “Chart”, che sfrutta l’elemento immagine. In figura è visibile l’interfaccia sperimentale per la gestione delle proprietà del grafico. Fig.4.20: Scheda “Chart” 4.4 Definizione di una fonte dati Come già discusso nel capitolo relativo a JasperReports, i dati da stampare possono essere letti in diversi modi e da sorgenti eterogenee quali database, file XML, file di testo formattato, ecc… Reporting tool in ambiente Open Source - Pagina 70 di 84 IReport supporta qualsiasi tipo si connessione JDBC e quattro tipi di datasource (in grado di gestire qualsiasi altro tipo di sorgente personalizzata). 4.4.1 Empty data source (JREmptyDataSource) Si tratta di una speciale fonte dati che di fatto non contiene nessun record. Può essere utilizzata in diverse situazioni per produrre report non basati in generale su recordset. 4.4.2 XML Data source Questa datasource è in fase di sviluppo e dovrebbe permettere di alimentare una stampa a partire dai contenuti in un documento XML. Fig.4.21: Definizione di una data source per file XML I parametri richiesti da questo tipo di sorgente dati sono semplicemente il nome da assegnare a questa sorgente, ed il nome del file XML. 4.4.3 JavaBean Set Datasource Anche questa datasource, come la precedente, è ancora in fase di sviluppo. L’idea è quella di gestire un insieme di oggetti JavaBean che vengono generati dall’utente mediante una classe java scritta appositamente. L’insieme può essere costituito da una Collection o un Array di JavaBean. La classe che deve essere realizzata a supporto di questa datasource, viene chiamata “factory” e dovrebbe contenere un metodo statico chiamando il quale viene prodotto l’Array o la Collection. Reporting tool in ambiente Open Source - Pagina 71 di 84 I parametri richiesti da questo tipo di sorgente dati sono: il nome da Fig.4.22: Definizione di una JavaBean Set data source assegnare alla sorgente, il nome della classe factory, il metodo statico da invocare su tale classe, ed il tipo di ritorno del metodo specificato. 4.4.4 Custom Datasource Questo tipo si datasource è completamente generico. IReport non conosce come sia implementata la specifica fonte dati, ma delega la creazione della datasource ad una classe esterna, sviluppata dall’utente e dotata di un metodo statico che ritorna un oggetto JRDataSource. I parametri richiesti da questo tipo di sorgente dati sono il solito nome da Fig.4.23: Definizione di una Custom data source assegnare alla sorgente, il nome della classe factory ed il metodo statico da invocare su tale classe (che ritornerà un’istanza della JRDataSource da utilizzare per la generazione della stampa). È previsto lo sviluppo di un meccanismo per poter definire nella finestra di configurazione della custom data source una serie di parametri da passare al metodo di Reporting tool in ambiente Open Source - Pagina 72 di 84 creazione della JRDataSource. In questo modo sarà facile implementare nuove sorgenti parametrizzabili e utilizzabili mediante iReport. 4.4.5 Impostazione di una connessione JDBC È possibile eseguire query SQL per la selezione di dati su un database relazionale usando una connessione JDBC. L’impostazione avviene mediante il gestore di connessioni (menu Datasources- >Connection/Datasources). Premendo il pulsante “New” apparirà la Fig.4.24: Definizione di una fonte dati JDBC finestra in figura 4.24. È necessario assicurarsi che il driver JDBC specificato si trovi nel classpath. A questo proposito si noti che iReport non gestisce, per il momento, classpath dinamici, è quindi opportuno assicurarsi che le classi o il jar del driver siano caricati dallo script di avvio di iReport. Premendo il pulsante “Wizard” è possibile ottenere un suggerimento sulla specifica sintassi del driver JDBC. Premere “Test” per controllare che la connessione sia stata impostata correttamente. “Save” per salvarla. Per utilizzare la connessione appena creata, selezionare il menu build>Set active connection e selezionare la sorgente dati desiderata dall’elenco delle sorgenti configurate. IReport memorizzerà la scelta che verrà riproposta anche ai successivi riavvii. Reporting tool in ambiente Open Source - Pagina 73 di 84 4.5 Recupero dei campi mediante SQL iReport è dotato di un comodo strumento per recuperare i nomi ed i tipi dei campi SQL selezionati da una query e registrarli all’interno del report per poterli utilizzare. L’operazione avviene mediante la stessa finestra nella quale viene definita la query. Per accedervi selezionare il menu view>Report Query. Una volta digitata la query di selezione, è sufficiente premere il pulsante “Read fields” per ottenere i nomi dei campi e relativi Fig.4.25: Recupero dei campi di una query tipi. A questo punto, selezioneremo i campi da “registrare” nel nostro report e premeremo il pulsante “Register fields to report”. Per associare al report la query visualizzata, dovremo premere il pulsante “Save query to report”. Possiamo in qualsiasi momento gestire i nostri campi selezionando il menu View->Report fields. Mediante questa operazione verrà visualizzata la finestra per l’aggiunta, la modifica e l’eliminazione dei campi, del tutto simile a quella che vedremo nel prossimo paragrafo per gestire variabili e parametri. Reporting tool in ambiente Open Source - Pagina 74 di 84 4.6 Gestione di variabili e parametri La gestione dei campi, delle variabili e dei parametri viene effettuata mediante una finestra genericamente definita “finestra dei valori” (fig. Fig.4.26: La finestra dei “valori” 4.26). Mediante tale interfaccia è possibile aggiungere, modificare o cancellare campi, variabili o parametri. 4.7 Compilazione ed esportazione La compilazione permette di trasformare un file XML (scritto secondo la sintassi di JasperReports) in un file jasper. In generale il codice XML generato da iReport non contiene errori sintattici, tuttavia può capitare che la compilazione generi degli errori dovuti ad un posizionamento invalido degli elementi o a qualche errore java in un’espressione. Per semplificare la vita del programmatore, iReport mette a disposizione un sistema che trasforma gli errori generati in fase di compilazione in link che puntano direttamente all’eventuale espressione errata (ovunque essa si trovi), o all’elemento fuori posto. Questa trasformazione avviene analizzando i messaggi di errore ed il file java che JasperReports tenta di compilare per la generazione del file Jasper. In figura 4.27 è possibile vedere i link agli errori visualizzati da iReport durante la compilazione di un documento di prova. Reporting tool in ambiente Open Source - Pagina 75 di 84 Compilata la stampa è possibile testarla incovandone la generazione. Fig.4.27: Link agli errori di compilazione IReport visualizza i risultati esportandoli nel formato richiesto dall’utente, selezionabile dal menu build. Mediante la finestra delle opzioni (menu tools->options) è possibile associare un visualizzatore ad ogni formato di stampa gestito da iReport. 4.8 Performance Pur appoggiandosi a delle librerie grafiche molto pesanti (java swing), l’interfaccia di iReport appare abbastanza fluida (soprattutto dopo gli accorgimenti di Kees Kuip che ha introdotto diverse modifiche per ottimizzare il motore grafico di iReport). Tuttavia la quantità di RAM utilizzata è molto alta (in particolare quando vengono gestiti molti report complessi contemporaneamente. Tuttavia i feedback molto positivi ottenuti dagli utenti che sono passati dalla veloce versione per win32 alla versione java, sono molto incoraggianti. Reporting tool in ambiente Open Source - Pagina 76 di 84 Per quel che riguarda le performance nella generazione delle stampe, non sono mai stati fatti dei seri test comparativi con altri sistemi di reportistica simili (quali DataVision e JFreeReport). Tuttavia i tempi di risposta effettuati stampando in pdf diverse migliaia di record sono del tutto accettabili (poco più lunghi di quelli ottenuti con una stampa scritta direttamente con iText). 4.9 Un caso di studio: Sydran Services LLC Sydran Services LLC. è una società americana nata nel 1992 per opera di Matthew Shoenberg operante nel settore della ristorazione. Attualmente gestisce oltre 264 ristoranti Burger King in otto stati americani; conta oltre 1200 dipendenti e fattura oltre 325 milioni di dollari l’anno. Sotto la guida del responsabile IT della società, Mark Rhodes, Sydran ha sviluppato Cheetah, un sistema di reportistica basato su un software open source per la pubblicazione su web di report: OpenReports, sviluppato da Eric Swenson (per altro coautore per conto di Sydran di Cheetah). Neanche a dirlo, il cuore di OpenReports (e quindi di Cheetah), è JasperReports. Cheetah è utilizzato da una moltitudine di persone all’interno della società: dai restaurant shift coordinator al CEO. Il sistema conta circa 1.400 utenti registrati dei quali almeno 500 si avvalgono delle funzionalità di generazione dei report. 4.9.1 Storia di Cheetah Lo scorso anno Sydran percepisce la necessità di avere uno strumento di generazione di report per rendere accessibili internamente le più disparate informazioni relative ai numerosi esercizi gestiti: dati relativi agli acquisti, alle informazioni fiscali, al costo delle vivande, ecc… Il mondo open source è ancora lontano dagli occhi della società, che inizia a muoversi valutando diversi noti pacchetti commerciali di reportistica: Cognos, IntelliView, Acuate. Insoddisfatta dei software disponibili in commercio (per la difficoltà di utilizzo o per il costo elevato delle licenze), Reporting tool in ambiente Open Source - Pagina 77 di 84 tenta di sviluppare in casa un proprio strumento di reportistica utilizzando pagine ASP sotto windows, ma il tentativo fallisce a causa della complessità di design dei report. Viene così adottato un primo sistema di reportistica basato su Microsoft Access e reso disponibile mediante Windows Terminal Server. L’accesso viene inizialmente aperto ad uno stretto numero di manager operanti nella zona limitrofa all’area di sviluppo, per un totale di circa 60 utenti. Il sistema soffre tuttavia di una serie di limitazioni: - necessita di una licenza Windows 2000 per ogni utente collegato al terminal server (rendendo proibitivi i costi di un impiego di questa soluzione esteso all’intera catena di ristoranti); - è privo di un sistema di autenticazione sufficientemente granulare (di fatto un qualsiasi utente è in grado di effettuare query sui dati di tutti i ristoranti); - è lento, essendo il sistema basato solo su Microsoft Access; - le richieste hardware della terminal server farm per sostenere i soli 60 utenti sono importanti: ben 3 CompaQ Proliant dual processor a 1.6GHz, dotati di 2GB di memoria RAM; Nel dicembre del 2002, Mark scopre JasperReports, OpenReports e iReport, tutti software opensource e liberamente utilizzabili nel contesto richiesto da Sydran. Non conoscendo java, Mark contatta Eric Swenson, chiedendogli di adattare OpenReports alle esigenze di Sydran e inviandogli una serie di specifiche iniziali. Nasce il progetto Cheetah, del quale viene realizzato un primo prototipo in meno di un mese. Verrà reso pubblico a febbraio 2003. Il sistema è dotato solo delle funzionalità di base, inclusa la parte relativa alla sicurezza (autenticazione degli utenti, ecc…), e dispone di circa 40 report sviluppati con iReport. Il progetto cresce e viene sviluppato un modulo di gestione dei permessi e di scheduling delle stampe per l’invio automatico dei report agli utenti via email. Attualmente Cheetah mette a disposizione 85 differenti tipi di report organizzati per categoria. Reporting tool in ambiente Open Source - Pagina 78 di 84 4.9.2 Obiettivo raggiunto Il progetto Cheetah è risultato essere per Sydran vincente su tutti i fronti: - ampia disponibilità del servizio di reportistica mediante l’uso di un’interfaccia web e protocollo SSL; - totale utilizzo di software per la realizzazione del sistema di reportistica privo di costose licenze per l’utente (webworks, tomcat, jasper, iReport, JasperReports, iText, poi, quartz,…); Sydran ha provveduto, tuttavia, a elargire donazioni a molti dei progetti citati (iReport incluso); - dotazione di una infrastruttura per la gestione della sicurezza ad hoc, dotata di notevoli funzioni di auditing e logging delle attività degli utenti; - impiego di query SQL ottimizzate per il database utilizzato (MS SQL Server 2000); - disponibilità di funzioni particolari come lo scheduling dei report (mediante Quartz) e la gestione delle stampe preferite; - economicità delle risorse hardware richieste (attualmente un solo server Linux supporta tutti i 1.500 utenti; sono stati condotti test con 80 utenti concorrenti registrando un minimo calo delle performance del sistema; Grazie ai log registrati da Cheetah, è stato calcolato che il numero di report generati raggiunge il suo picco mediamente il martedì, con oltre 1.200 stampe, mentre la domenica rappresenta il giorno in cui il servizio è meno usato (con una media di circa 300 stampe giornaliere). La velocità di generazione della stampa si aggira normalmente attorno ai 22 secondi (un tempo relativamente basso dato il formato di esportazione dei report: il pdf). Secondo le stime effettuate da Mark, il sistema è in grado di reggere nello stato attuale fino a 200 utenti concorrenti; il sistema è stato comunque progettato per poter essere utilizzato su un cluster di server Linux mediante il quale si potrebbe ottenere un notevole aumento delle prestazioni. L’analisi dei log, relativi a 10 giorni di utilizzo, inviatomi da Mark, permette di evidenziare come il servizio sia rimasto perennemente attivo (7 giorni su 7, 24h su 24h) nel periodo monitorato, producendo un totale di 6.541 report eseguiti alla velocità media di 20,5 secondi per stampa. Reporting tool in ambiente Open Source - Pagina 79 di 84 L’esperienza di Sydran dimostra come un sistema di reportistica basato su JasperReports sia estremamente versatile e scalabile, paragonabile ai più costosi sistemi di reportistica commerciali (le cui licenze, in molti casi, variano di prezzo a seconda del volume di report generati!). 4.10 Sviluppi futuri Il progetto iReport non ha ancora compiuto un anno. La lista delle funzionalità da realizzare e completare è veramente lunga: si tratta di implementare molti suggerimenti proposti dagli utenti, ma in cantiere c’è anche lo sviluppo di diverse funzionalità presenti in altri programmi simili (commerciali e non). L’idea è quella di rilasciare le future release a breve distanza tra loro, per tenere alto l’interesse nel programma ed incoraggiare gli utenti a provare le nuove funzionalità. Diverse sono le richieste di rendere il programma localizzabile, caratteristica che ne favorirebbe la diffusione nei paesi che usano codifiche di caratteri particolari (come quelli arabi e asiatici). Ritengo lo sviluppo della sorgente dati per file XML una funzionaità indispensabile per un software di reportistica al passo con i tempi. Il supporto di elementi speciali quali il grafico, il codice a barre, le immagini vettoriali, ecc… arriveranno con il tempo, ma certamente iReport è destinato a crescere. Molto. Reporting tool in ambiente Open Source - Pagina 80 di 84 Conclusioni In questa tesi, come ci si poteva aspettare, sono stati fatti pochissimi riferimenti alle soluzioni commerciali per lo sviluppo di report. Quanto a funzionalità, iReport è probabilmente ancora molto lontano da molte di queste soluzioni, ma è in grado di rispondere efficacemente ad un buon 80% delle richieste avanzate dagli utenti che necessitano di un software di reportistica. Tuttavia, la diffusione dei reporting tool in ambiente Open Source è osteggiata in maniera decisa dalle software house commerciali, logorate già da una feroce concorrenza [8] nel settore dei reporting tool. In un articolo intitolato “Build Reporting into Applications” [7] , apparso sul numero di novembre 2003 del noto magazine americano JavaPro, Peter Varhol analizza con estrema attenzione gli scenari di utilizzo dei reporting tool ed cita praticamente tutti i prodotti commerciali disponibili sul mercato elencandone caratteristiche e funzionalità; l’autore trae alcune conclusioni sull’utilità di questi pacchetti, considerandoli indispensabili in un progetto che necessiti di funzionalità di reportistca, e giustifica il costo di queste soluzioni, per quanto alto, azzardando un confronto con quello di un eventuale sviluppo di una soluzione proprietaria per la gestione delle stampe. Nell’articolo non viene minimamente citato alcun software di reportistica open source. Eppure l’attuale classifica stilata dalla nota rivista Java Developer Jurnal [19] riguardo ai software maggiormente apprezzati dagli utenti Java per la categoria reporting tool (JDJ Reader’s choise 2003) vede JasperReports e JFreeReport piazzati nelle prime cinque posizioni! Senza commentare il fatto che JFreeReport risulta più votato di Reporting tool in ambiente Open Source - Pagina 81 di 84 JasperReports, tutti i rimanenti concorrenti più votati sono sponsor ufficiali dell’iniziativa. La soddisfazione di veder crescere giorno dopo giorno una nutrita comunità di utenti sparsi in tutto il mondo ed entusiasti di iReport è tuttavia impagabile. I due forum ufficiali contano ormai oltre 1800 messaggi di persone che scrivono suggerimenti, richiedono aiuto e offrono soluzioni, ma soprattutto apprezzano il programma. Le statistiche relative ai download di iReport indicano un chiaro trend rialzista, e spero di poter vedere presto questo programma ai primi posti delle prossime edizioni della classifica stilata da JDJ. D’altra parte, superando la soglia dei 20.000 download in meno di un anno, iReport ha già abbondantemente decretato il successo dell’ Open Source nella combattuta nicchia di mercato contesa dai reporting tool. Reporting tool in ambiente Open Source - Pagina 82 di 84 Bibliografia [1] Teodor Danciu - JasperReports Ultimate Guide - 2002 [2] Jim Menard - DataVision User's Manual - 2003 [3] Giulio Toffoli - iReport 0.2.x Manual - 2003 [4] Tetsuya Masuishi, Nobuo Takahashi - A Reporting Tool Using “Programming by Example” For Format Designation [5] Don Kiely - Add Reporting to Your Apps – VisualStudio Magazine, novembre 2003 [6] Andy Clark - Develop Flexible Reports – VisualStudio Magazine, maggio 2003 [7] Peter Varhol - Build Reporting into Applications – VisualStudio Magazine, novembre 2003 [8] ReportingEngines - Too Many Reporting Tools? - JavaPro Magazine, novembre 2003 [9] QuestSoftware - J2EE Server-Side Components - JavaPro Magazine, novembre 2003 [10] InetSoft - Integrated Reporting - JavaPro Magazine, novembre 2003 [11] CrystalDecisions - Crystal Reports and Java - JavaPro Magazine, novembre 2003 [12] ReportMill Software - Object Reporting - JavaPro Magazine, novembre 2003 [13] Panscopic - Back to Business - JavaPro Magazine, novembre 2003 [14] ExtenTech - Unlock Business Intelligence - JavaPro Magazine, novembre 2003 [15] Jinfonet Software - JReport for Enterprise-Ready Reporting - JavaPro Magazine, novembre 2003 Reporting tool in ambiente Open Source - Pagina 83 di 84 [16] Cognos - Cognos ReportNet™: The next generation of enterprisenterprise query and reporting - A cognos white paper – Agosto 2003 [17] Joseph Lauer - Reporting Tool, Evaluation Process [18] Crystal Decision - Extending Crystal Reports’ Technology into the Java World - 2002 [19] JDJ Reader’Choise 2003: Best Java Reporting Tool (http://www.syscon.com/java/readerschoice2003/liveupdate.cfm?BType=21) Reporting tool in ambiente Open Source - Pagina 84 di 84