présentation du framework Birt
Date de publication : 30/01/2007
Par
Moritan
Cet article est une présentation générale du générateur de rapport Birt de la fondation Eclipse.
I. Remerciement
II. Introduction
III. Détail
IV. L'API
V. Les formats
V-A. RptTemplate
V-B. RptDesign
V-C. RptDocument
VI. Les fonctionnalités du framework BIRT
VII. Installer son environnement
VII-A. Téléchargement de Birt
VII-B. Installation de l'environnement de développement
VII-C. Déploiement de l'implémentation BirtViewer
VII-C-1. Déploiement sur un serveur Tomcat
VII-C-2. Déploiement sur un serveur Glassfish
VII-C-3. Utilisation du BirtViewer
VI-C-3-a. Déposer un nouveau rapport
VII-C-3-b. Les urls utiles
VIII. Intégration du framework BIRT dans votre application
VIII-A. Intégration dans une application J2EE
VIII-B. Intégration dans une application J2SE
VIII-B-1. Implémentation dans une application Eclipse RCP
VIII-B-2. Intégration dans une application Non Eclipse RCP
IX. Conclusion
I. Remerciement
Merci à ... pour sa relecture.
II. Introduction
BIRT ou "Business Intelligence Reporting Tool" est une solution développée par la fondation Eclipse.
Basé sur la plateforme Eclipse, BIRT est un générateur de rapport open source.
Développé en Java, il est principalement destiné a être utilisé dans un contexte J2EE, mais il est possible de l'utiliser dans un contexte J2SE.
BIRT n'est pas une solution "out-of-the-box", c'est principalement un framework à destination des développeurs.
III. Détail
Derrière le sigle BIRT se cache plusieurs choses, il s'agit principalement du nom du projet sur le site Eclipse.org
Le projet est composé de quatre principaux modules :
1. Un moteur de rapport (runtime) que l'on peut intégrer dans sa propre solution
2. Un plugin Eclipse pour concevoir les rapports
3. Un client RCP pour concevoir les rapports
4. Un exemple d'implémentation J2EE (Web-Viewer)
Evidemment, le plugin et le client RCP offre finalement les mêmes fonctionnalités.
Mais il est intéressant de voir que la possibilité d'offrir un éditeur simple
et dédié pour la conception des rapports reste offerte.
IV. L'API
L'api BIRT se scinde en trois grandes parties.
Le Design Engine API (DE), permet la création et la manipulation des modèles de rapport.
C'est cette partie de l'API qui est utilisée dans le designer.
La second section de l'API, appelé Report Engine API (RE), permet à partir d'un fichier modèle
de rapport de générer le rapport en temps que tel avec ses données.
Enfin la Charts API, permet de générer des graphiques à partir des données du rapport.
La Charts API est aussi disponible séparément pour être utilisé dans vos autres projets java.
V. Les formats
Les rapports Birt se basent sur trois formats de fichier.
V-A. RptTemplate
Les fichiers RptTemplate sont des fichiers modèles. Il peuvent être regroupés en bibliothèque ou utilisés seuls.
Les fichiers RptTemplate sont utilisés principalement dans le Designer de BIRT, pour constituer les squelettes des fichiers RptDesign générés.
V-B. RptDesign
Un rapport Birt est représenté par un fichier RptDesign.
Ce fichier n'est autre qu'un fichier XML, permettant la persistance des données du rapports.
Un fichier Rptdesign est un document autoporteur. Il contient toutes les informations nécessaire pour son exécution par un moteur BIRT.
V-C. RptDocument
Il s'agit de la forme compilée des fichiers rptdesign. C'est à partir de ce fichier que sera produit le rendu final du rapport.
VI. Les fonctionnalités du framework BIRT
Le framework Birt permet d'effectuer toutes les opérations possibles pour obtenir un rapport.
Que se soit à la conception par la création, modification des fichiers XML de description (RPTTemplate et RTPDesign), que lors de la génération d'un rapport en offrant la maitrise des des
différents paramètres de génération( gestion du cache, format de sortie,etc..).
Il y a donc peu de chose que ne puisse faire ce framework, il faut néanmoins prévoir un environnement à mettre à disposition de l'utilisateur que ce soit les implémentations par défaut fournies ou un environnement personnalisé réalisé afin de d'intégrer au mieux BIRT dans le système d'information.
D'un point de vu plus utilisateur, le moteur de BIRT est capable de traiter des rapports avec diverses sources de données.
Il est donc possible dans un rapport de conjuguer des données provennant de différentes bases de données ou de fichiers XML.
Le requétage des bases de données se fait par l'intermédiaire d'un driver jdbc, Il n'y a donc pas plus de limitation dans le rapport BIRT/Base de données que dans un programme Java classique.
Les sources XML sont intérogés graçe à une couche ODA fournit par le framework BIRT, mais les requètes sont proches des requètes Xpath.
Toutes les données manipulées au sein d'un rapport, peuvent être transformées, triées, filtrées, regroupées.
VII. Installer son environnement
VII-A. Téléchargement de Birt
Pour commencer il suffit de télécharger les composants dont on a besoin sur le site d'Eclipse
Afin d'obtenir le support du format PDF.
Il faut ensuite télécharger
iText.
Copier le fichier itext-1.3.jar dans le répertoire
"/plugins/com.lowagie.itext_*/lib".
Cette dernière étape est nécessaire aussi bien pour l'utilisation du designer ou pour l'utilisation du Webviewer.
VII-B. Installation de l'environnement de développement
Les archives fournient sur le site d'Eclipse vous permettent
de choisir librement votre environnement de développement.
Donc au choix, soit le plugin à insérer dans votre environnement Eclipse actuel, soit utiliser Le client RCP, Birt Designer dédié.
VII-C. Déploiement de l'implémentation BirtViewer
VII-C-1. Déploiement sur un serveur Tomcat
L'application BirtViewer est fournie sous la forme d'un fichier war.
Le déploiement se fait donc simplement par dépot du fichier birt.war
dans le répertoire webapps de votre serveur Tomcat.
VII-C-2. Déploiement sur un serveur Glassfish
L'archive war ne fonctionne pas directement dans un serveur Glassfish.
Il est nécessaire auparavant de modifier l'archive war.
Première étape, il faut créer un fichier sun-web.xml :
sun-web.xml |
<? xml version="1.0" encoding="UTF-8"? >
<! DOCTYPE sun - web - app PUBLIC " -
//Sun Microsystems, Inc.
//DTD Application Server 9.0 Servlet 2.5
//EN " " http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd " >
< sun-web-app error-url = " " >
< context-root > /birt-viewer< / context-root >
< class-loader delegate = " false " / >
< jsp-config >
< property name = " classdebuginfo " value = " true " >
< description > Enable debug info compilation in the generated servlet class< / description >
< / property >
< property name = " mappedfile " value = " true " >
< description > Maintain a one-to-one correspondence between static
content and the generated servlet class' java code< / description >
< / property >
< / jsp-config >
< / sun-web-app >
|
Il faut placer ensuite ce fichier dans le répertoire "WEB-INF" de l'archive.
Deuxième étape, il faut rajouter la librairie "commons-logging.jar" dans le répertoire
"WEB-INF/lib" de l'archive.
Il ne reste plus qu'à déployer l'archive sur votre serveur Glassfish.
Si vous n'avez jamais déployé d'application war sur un serveur glassfish, vous pouvez consulter
cette page pour plus d'information.
VII-C-3. Utilisation du BirtViewer
VI-C-3-a. Déposer un nouveau rapport
L'implémentation de référence ne prend pas en compte pour le moment la gestion des rapports.
La publication et la sélection des rapports doit se faire manuellement par l'utilisateur.
VII-C-3-b. Les urls utiles
Deux adresses sont disponibles pour l'utilsateur :
http://sitePrefix/birt-viewer/frameset?option1=value1;option2=value2
http://sitePrefix/birt-viewer/run?option1=value1;option2=value2
|
L'adresse frameset permet l'exécution du rapport dans une page aux fonctionnalités étendues
L'adresse run permet d'exécuter un rapport dans une page minimum restriente à la seule sortie du rapport.
Chacune de ces deux adresses prennent différents paramètres.
Paramètres disponibles de l'url
- __format – Le format de sortie, seulement pour l'adresse /run
- __page – Page à afficher, seulement pour l'adresse /frameset
- __isnull – Permet de passer la valeur null à un paramètre du rapport
- __locale – Positionne la locale du rapport
- __report – Chemin vers le fichier design du rapport à exécuter
- __document – Chemin vers le fichier document du rapport à exécuter
- __svg – Active le support du format svg
- __overwrite – Permet de purger manuellement le fichier document du rapport
- Parametername=value - Ce format permet de passer les paramètres du rapport
La servlet BirtViewer offre quelques possibilités de configuration de la pateforme.
Ces paramètres sont placés dans dans le fichier web.xml
Web.xml |
BIRT_VIEWER_LOCALE – Locale par défaut de la plateforme
BIRT_VIEWER_REPORT_ROOT – Ce paramètre n'est pas encore utilisé
BIRT_VIEWER_WORKING_FOLDER – Répertoire par défaut à utiliser si le chemein du rapport est un chemin relatif
BIRT_VIEWER_IMAGE_DIR – Répertoire ou le Report Engine Service ira créer les images.
Ce chemin peut-être absolue ou relatif
BIRT_VIEWER_LOG_DIR - Répertoire ou le Report Engine Service ira placer ses logs.
Ce chemin peut-être absolue ou relatif
BIRT_VIEWER_LOG_LEVEL – java.util.logging.Level Niveau utiliser dans les logs du moteur.
BIRT_VIEWER_SCRIPTLIB_DIR – Répertoire utilisé pour Java Event handlers.
Ce chemin peut-être absolue ou relatif
|
VIII. Intégration du framework BIRT dans votre application
La modularité du framework Birt vous permet de l'utiliser aussi bien dans une application Java SE que dans une application WEB.
De plus libre à vous de choisir les implémentations par défaut fournient en standard ou de d'intégrer le framework de génération de rapport selon votre propre implémentation.
VIII-A. Intégration dans une application J2EE
BirtConfig.propertiies |
logDirectory= c:/ temp
logLevel= FINEST
|
BirtEngine.java |
import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.IReportEngine;
import javax.servlet.*;
import org.eclipse.birt.core.framework.PlatformServletContext;
import org.eclipse.birt.core.framework.IPlatformContext;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
public class BirtEngine {
private static IReportEngine birtEngine = null ;
private static Properties configProps = new Properties ();
private final static String configFile = " BirtConfig.properties " ;
public static synchronized void initBirtConfig () {
loadEngineProps ();
}
public static synchronized IReportEngine getBirtEngine (ServletContext sc) {
if (birtEngine = = null )
{
EngineConfig config = new EngineConfig ();
if ( configProps ! = null ){
String logLevel = configProps.getProperty (" logLevel " );
Level level = Level.OFF;
if (" SEVERE " .equalsIgnoreCase (logLevel))
{
level = Level.SEVERE;
} else if (" WARNING " .equalsIgnoreCase (logLevel))
{
level = Level.WARNING;
} else if (" INFO " .equalsIgnoreCase (logLevel))
{
level = Level.INFO;
} else if (" CONFIG " .equalsIgnoreCase (logLevel))
{
level = Level.CONFIG;
} else if (" FINE " .equalsIgnoreCase (logLevel))
{
level = Level.FINE;
} else if (" FINER " .equalsIgnoreCase (logLevel))
{
level = Level.FINER;
} else if (" FINEST " .equalsIgnoreCase (logLevel))
{
level = Level.FINEST;
} else if (" OFF " .equalsIgnoreCase (logLevel))
{
level = Level.OFF;
}
config.setLogConfig (configProps.getProperty (" logDirectory " ), level);
}
config.setEngineHome (" " );
IPlatformContext context = new PlatformServletContext ( sc );
config.setPlatformContext ( context );
try
{
Platform.startup ( config );
}
catch ( BirtException e )
{
e.printStackTrace ( );
}
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject ( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
birtEngine = factory.createReportEngine ( config );
}
return birtEngine;
}
public static synchronized void destroyBirtEngine () {
if (birtEngine = = null ) {
return ;
}
birtEngine.shutdown ();
Platform.shutdown ();
birtEngine = null ;
}
public Object clone () throws CloneNotSupportedException {
throw new CloneNotSupportedException ();
}
private static void loadEngineProps () {
try {
ClassLoader cl = Thread.currentThread ().getContextClassLoader ();
InputStream in = null ;
in = cl.getResourceAsStream (configFile);
configProps.load (in);
in.close ();
} catch (IOException e) {
e.printStackTrace ();
}
}
}
|
ParameterTask.java |
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.IGetParameterDefinitionTask;
import org.eclipse.birt.report.engine.api.IParameterDefnBase;
import org.eclipse.birt.report.engine.api.IParameterGroupDefn;
import org.eclipse.birt.report.engine.api.IParameterSelectionChoice;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IScalarParameterDefn;
import org.eclipse.birt.report.model.api.CascadingParameterGroupHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.ScalarParameterHandle;
public class ParametersTask {
static HashMap< String, HashMap< String, Serializable> > getParameters (
IReportEngine engine, IReportRunnable design)
throws EngineException {
HashMap< String, HashMap< String, Serializable> > parmDetails = new HashMap< String, HashMap< String, Serializable> > ();
IGetParameterDefinitionTask task = engine
.createGetParameterDefinitionTask (design);
Collection params = task.getParameterDefns (true );
Iterator iter = params.iterator ();
while (iter.hasNext ()) {
IParameterDefnBase param = (IParameterDefnBase) iter.next ();
if (param instanceof IParameterGroupDefn) {
IParameterGroupDefn group = (IParameterGroupDefn) param;
Iterator i2 = group.getContents ().iterator ();
while (i2.hasNext ()) {
IScalarParameterDefn scalar = (IScalarParameterDefn) i2
.next ();
parmDetails.put (scalar.getName (), loadParameterDetails (
task, scalar, design, group));
}
} else {
IScalarParameterDefn scalar = (IScalarParameterDefn) param;
parmDetails.put (scalar.getName (), loadParameterDetails (task,
scalar, design, null ));
}
}
return parmDetails;
}
private static HashMap< String, Serializable> loadParameterDetails (
IGetParameterDefinitionTask task, IScalarParameterDefn scalar,
IReportRunnable report, IParameterGroupDefn group) {
HashMap< String, Serializable> parameter = new HashMap< String, Serializable> ();
if (group = = null ) {
parameter.put (" Parameter Group " , " Default " );
} else {
parameter.put (" Parameter Group " , group.getName ());
}
parameter.put (" Name " , scalar.getName ());
parameter.put (" Help Text " , scalar.getHelpText ());
parameter.put (" Display Name " , scalar.getDisplayName ());
parameter.put (" Display Format " , scalar.getDisplayFormat ());
if (scalar.isHidden ()) {
parameter.put (" Hidden " , " Yes " );
} else {
parameter.put (" Hidden " , " No " );
}
if (scalar.allowBlank ()) {
parameter.put (" Allow Blank " , " Yes " );
} else {
parameter.put (" Allow Blank " , " No " );
}
if (scalar.allowNull ()) {
parameter.put (" Allow Null " , " Yes " );
} else {
parameter.put (" Allow Null " , " No " );
}
if (scalar.isValueConcealed ()) {
parameter.put (" Conceal Entry " , " Yes " );
} else {
parameter.put (" Conceal Entry " , " No " );
}
switch (scalar.getControlType ()) {
case IScalarParameterDefn.TEXT_BOX:
parameter.put (" Type " , " Text Box " );
break ;
case IScalarParameterDefn.LIST_BOX:
parameter.put (" Type " , " List Box " );
break ;
case IScalarParameterDefn.RADIO_BUTTON:
parameter.put (" Type " , " Radio Box " );
break ;
case IScalarParameterDefn.CHECK_BOX:
parameter.put (" Type " , " Check Box " );
break ;
default :
parameter.put (" Type " , " Text Box " );
break ;
}
switch (scalar.getDataType ()) {
case IScalarParameterDefn.TYPE_STRING:
parameter.put (" Data Type " , " String " );
break ;
case IScalarParameterDefn.TYPE_FLOAT:
parameter.put (" Data Type " , " Float " );
break ;
case IScalarParameterDefn.TYPE_DECIMAL:
parameter.put (" Data Type " , " Decimal " );
break ;
case IScalarParameterDefn.TYPE_DATE_TIME:
parameter.put (" Data Type " , " Date Time " );
break ;
case IScalarParameterDefn.TYPE_BOOLEAN:
parameter.put (" Data Type " , " Boolean " );
break ;
default :
parameter.put (" Data Type " , " Any " );
break ;
}
ReportDesignHandle reportHandle = (ReportDesignHandle) report
.getDesignHandle ();
ScalarParameterHandle parameterHandle = (ScalarParameterHandle) reportHandle
.findParameter (scalar.getName ());
parameter.put (" Default Value " , parameterHandle.getDefaultValue ());
parameter.put (" Prompt Text " , parameterHandle.getPromptText ());
parameter.put (" Data Set Expression " , parameterHandle.getValueExpr ());
if (scalar.getControlType () ! = IScalarParameterDefn.TEXT_BOX) {
if (parameterHandle.getContainer () instanceof CascadingParameterGroupHandle) {
Collection sList = Collections.EMPTY_LIST;
if (parameterHandle.getContainer () instanceof CascadingParameterGroupHandle) {
int index = parameterHandle.getContainerSlotHandle ()
.findPosn (parameterHandle);
Object[] keyValue = new Object[index];
for (int i = 0 ; i < index; i+ + ) {
ScalarParameterHandle handle = (ScalarParameterHandle) ((CascadingParameterGroupHandle) parameterHandle
.getContainer ()).getParameters ().get (i);
keyValue[i] = handle.getDefaultValue ();
}
String groupName = parameterHandle.getContainer ().getName ();
task.evaluateQuery (groupName);
sList = task.getSelectionListForCascadingGroup (groupName,
keyValue);
HashMap< Object, String> dynamicList = new HashMap< Object, String> ();
for (Iterator sl = sList.iterator (); sl.hasNext ();) {
IParameterSelectionChoice sI = (IParameterSelectionChoice) sl
.next ();
Object value = sI.getValue ();
Object label = sI.getLabel ();
dynamicList.put (value, (String) label);
}
parameter.put (" Selection List " , dynamicList);
}
} else {
Collection selectionList = task.getSelectionList (scalar
.getName ());
if (selectionList ! = null ) {
HashMap< Object, String> dynamicList = new HashMap< Object, String> ();
for (Iterator sliter = selectionList.iterator (); sliter
.hasNext ();) {
IParameterSelectionChoice selectionItem = (IParameterSelectionChoice) sliter
.next ();
Object value = selectionItem.getValue ();
String label = selectionItem.getLabel ();
dynamicList.put (value, label);
}
parameter.put (" Selection List " , dynamicList);
}
}
}
return parameter;
}
}
|
WebReport.java |
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.birt.report.engine.api.EngineConstants;
import org.eclipse.birt.report.engine.api.HTMLRenderContext;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.IReportEngine;
public class WebReport extends HttpServlet {
private static final long serialVersionUID = 1L ;
private IReportEngine birtReportEngine = null ;
protected static Logger logger = Logger.getLogger ( " org.eclipse.birt " );
public WebReport () {
super ();
}
public void doGet (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String reportName = req.getParameter (" ReportName " );
String format = req.getParameter (" format " );
if (format.equalsIgnoreCase (" pdf " )){
resp.setContentType ( " application/pdf " );
resp.setHeader (" Content-Disposition " ," inline; filename=test.pdf " );
} else {
resp.setContentType (" text/html " );
}
ServletContext sc = req.getSession ().getServletContext ();
this .birtReportEngine = BirtEngine.getBirtEngine (sc);
HTMLRenderContext renderContext = new HTMLRenderContext ();
renderContext.setBaseImageURL (req.getContextPath ()+ " /images " );
renderContext.setImageDirectory (sc.getRealPath (" /images " ));
logger.log ( Level.FINE, " image directory " + sc.getRealPath (" /images " ));
System.out.println (" stdout image directory " + sc.getRealPath (" /images " ));
HashMap< String, HTMLRenderContext> contextMap = new HashMap< String, HTMLRenderContext> ();
contextMap.put ( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderContext );
IReportRunnable design;
try
{
design = birtReportEngine.openReportDesign ( sc.getRealPath (" /Reports " )+ " / " + reportName );
IRunAndRenderTask task = birtReportEngine.createRunAndRenderTask ( design );
task.setAppContext ( contextMap );
HashMap< String, HashMap< String, Serializable> > params = ParametersTask.getParameters (birtReportEngine, design);
Set< String> set = params.keySet ();
Iterator< String> iterator = set.iterator ();
String name = null ;
String defaultValue= null ;
while (iterator.hasNext ()) {
String element = iterator.next ();
System.out.println (" element : " + element);
HashMap< String, Serializable> param = params.get (element);
name = (String) param.get (" Name " );
defaultValue= (String) param.get (" Default Value " );
if (req.getParameter (name)! = null )
defaultValue= req.getParameter (name);
task.setParameterValue (name, defaultValue);
}
HTMLRenderOption options = new HTMLRenderOption ();
if (format.equalsIgnoreCase (" pdf " )){
options.setOutputFormat (HTMLRenderOption.OUTPUT_FORMAT_PDF);
} else {
options.setOutputFormat (HTMLRenderOption.OUTPUT_FORMAT_HTML);
}
options.setOutputStream (resp.getOutputStream ());
task.setRenderOption (options);
task.run ();
task.close ();
} catch (Exception e){
e.printStackTrace ();
throw new ServletException ( e );
}
}
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType (" text/html " );
PrintWriter out = response.getWriter ();
out.println (" <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"> " );
out.println (" <HTML> " );
out.println (" <HEAD><TITLE>A Servlet</TITLE></HEAD> " );
out.println (" <BODY> " );
out.println (" Post does nothing " );
out.println (" </BODY> " );
out.println (" </HTML> " );
out.flush ();
out.close ();
}
@throws
public void init () throws ServletException {
BirtEngine.initBirtConfig ();
}
public void destroy () {
super .destroy ();
BirtEngine.destroyBirtEngine ();
}
}
|
VIII-B. Intégration dans une application J2SE
VIII-B-1. Implémentation dans une application Eclipse RCP
VIII-B-2. Intégration dans une application Non Eclipse RCP
IX. Conclusion
Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.