lundi 24 septembre 2007

Java Scripted Datasets avec BIRT: une solution souple et pratique !

BIRT est un projet open-source de la communauté Eclipse.org permettant de réaliser des états (reports) à partir d'un fichier de mise en forme (rptdesign xml), de données diverses (base de données) et d'un moteur de génération des éditions (BIRT engine) le tout dans un monde J2EE.

La plupart du temps, BIRT est présenté comme une solution orientée BI (Business Intelligence)... du décisionnel. Et pourtant, c'est aussi une solution très adaptée pour réaliser des documents pour des applications métiers qui necessitent la réalisation de documents à partir de grappes d'objet métier java et non à partir de bases de données directement.

Je m'explique... dans les exemples BIRT on voit toujours des data sources pour se connecter directement à une base de données or ce n'est pas forcément pratique quand doit réaliser un document qui correspond à un écran pour lequel il existe déjà un service métier permettant de récupérer les données à afficher dans le document.

Pour ce faire, il existe les scripted data sources et les scripted data sets. Ils permettent d'utiliser des objets java pour les afficher dans le document. Par défaut, le data set est codé en javascript au sein de l'éditeur BIRT dans Eclipse. Le code javascript est stocké dans le document BIRT (rptdesign ou rptlibrary). Cela peut poser plusieurs problèmes lors de la réalisation du document.

Premièrement, le javascript est simple certe mais l'éditeur BIRT actuel ne permet pas d'apporter beaucoup d'aide au developpeur (autocompletion, verificateur de syntaxe...).

Deuxièmement, il n'est pas possible de mettre des points d'arrêt pour débugger le document lors de la génération avec le moteur BIRT.

Troisièmement, le code du data set est stocket dans le document BIRT de description de l'édition avec tous les désagréments que cela comporte.

Mais heureusement il existe une ultime solution pour pallier à ces trois problèmes les java scripted data sets ! Ils permettent tout simplement de remplacer les javascripted data sets par une classe java.

La classe java doit implémenter ScriptedDataSetEventAdapter avec les méthodes :

public boolean fetch(IDataSetInstance set, IUpdatableDataSetRow row) { ... }
public void beforeOpen(IDataSetInstance dataSet, IReportContext reportContext) { ... }
public boolean describe(IDataSetInstance arg0, IScriptedDataSetMetaData arg1) { ... }

Exemple:

import org.eclipse.birt.report.engine.api.script.eventadapter.ScriptedDataSetEventAdapter;
import org.eclipse.birt.report.engine.api.script.instance.IDataSetInstance;
import org.eclipse.birt.report.engine.api.script.IUpdatableDataSetRow;
import org.eclipse.birt.report.engine.api.script.IScriptedDataSetMetaData;


public class MyScriptedDataSetEventAdapter extends ScriptedDataSetEventAdapter {

private static final String COLUMN_FOO = "Foo";
private static final String COLUMN_BAR = "Bar";

private int index = 0;
private int size;

private MyObject test;

public boolean fetch(IDataSetInstance set, IUpdatableDataSetRow row) {
if( index >= size){
return false;
}
try{
row.setColumnValue(COLUMN_FOO, test.getListToFetch().get(index).getFoo());
row.setColumnValue(COLUMN_BAR, test.getListToFetch().get(index).getBar());
}catch (Exception e){
//myLogger.log(e) you know wtf to do here ;-)
}
index += 1;
return true;
}

public void beforeOpen(IDataSetInstance dataSet, IReportContext reportContext) {
test = (MyObject) reportContext.getGlobalVariable("myObjectName");
size= test.getListToFetch().size();
}

public boolean describe(IDataSetInstance arg0, IScriptedDataSetMetaData arg1) {
arg1.addColumn(COLUMN_FOO, String.class);
arg1.addColumn(COLUMN_BAR, Double.class);
return true;
}

}

Pour débugger rien de plus simple, mettre un point d'arrêt et lancer l'application en debug...
Pour s'assurer de la syntaxe du code... Eclipse est la !
Pour aider a la récupération des données issues de la grappe métier passée en paramètre à BIRT... encore une fois Eclipse est la !

PS: Par contre pour les projets utilisants BIRT coté client RCP... il peut y avoir des problèmes de partage de classpath... apparement les dataset scipted java ne sont pas trouvé... donc pour le moment méthode a utiliser uniquement coté serveur... a moins que...