Actuellement en version 3.0.0, cette API open source est gratuite. Elle n'est pas sans défaut mais présente de bons points.

Les défauts :
- elle ne couvre pas encore toutes les fonctionnalités offertes par jasper ;
- le support est payant ( un forum existe, mais il faut s'armer de patience …).

Les bons points :
- les exemples fournis constituent de bons tutoriels ;
- il est facile de créer des tableaux croisés dynamiquement en quelques lignes de codes.

Voici une brève description de cette API prometteuse, pour plus d'informations rendez-vous sur http://dynamicjasper.sourceforge.net.

1 : Un petit aperçu de la construction de tableau croisé deux lignes et deux colonnes.

CrosstabBuilder cb = new CrosstabBuilder();
 
cb.setHeight(500)
  .setWidth(500)
  .setHeaderStyle(mainHeaderStyle)
  .setDatasource("sr",DJConstants.DATA_SOURCE_ORIGIN_PARAMETER, DJConstants.DATA_SOURCE_TYPE_COLLECTION)
  .setUseFullWidth(true)
  .setColorScheme(0)
  .setCellBorder(Border.PEN_1_POINT);
 
 
cb.addMeasure("valeur",BigDecimal.class.getName(), DJCalculation.SUM, "Montant",measureStyle);
 
// Les deux lignes						
DJCrosstabRow row = new CrosstabRowBuilder()
   .setProperty("libelle_crit_1_niv_1",String.class.getName())
   .setHeaderWidth(200)
   .setHeight(50)
   .setTitle('titre de cette ligne')
   .setShowTotals(true)
   .setTotalStyle(totalStyle)
   .setTotalHeaderStyle(totalHeaderStyle)
   .setHeaderStyle(colAndRowHeaderStyle)
   .build();
 
cb.addRow(row);
 
row = new CrosstabRowBuilder()
   .setProperty("libelle_crit_1_niv_2",String.class.getName())
   .setHeaderWidth(200)
   .setHeight(50)
   .setTitle('titre de cette ligne')
   .setShowTotals(true)
   .setTotalStyle(totalStyle)
   .setTotalHeaderStyle(totalHeaderStyle)
   .setHeaderStyle(colAndRowHeaderStyle)
   .build();
 
cb.addRow(row);
 
// Les deux colonnes
DJCrosstabColumn col = null;
col = new CrosstabColumnBuilder()
   .setProperty("libelle_crit_2_niv_1",String.class.getName())
   .setHeaderHeight(60)
   .setWidth(200)
   .setTitle('titre de cette colonne')
   .setShowTotals(true)
   .setTotalStyle(totalStyle)
   .setTotalHeaderStyle(totalHeaderStyle)
   .setHeaderStyle(colAndRowHeaderStyle)
   .build();
 
cb.addColumn(col);
 
col = new CrosstabColumnBuilder()
   .setProperty("libelle_crit_2_niv_2",String.class.getName())
   .setHeaderHeight(60)
   .setWidth(200)
   .setTitle('titre de cette colonne')
   .setShowTotals(true)
   .setTotalStyle(totalStyle)
   .setTotalHeaderStyle(totalHeaderStyle)
   .setHeaderStyle(colAndRowHeaderStyle)
   .build();
 
cb.addColumn(col);
 
 
// construction du tableau croisé		
DJCrosstab djcross = cb.build();
 
String reportPath = getServletContext().getInitParameter("chemin");
 
String reportFullPath = reportPath + getServletContext().getInitParameter("chemin specifique");
 
FastReportBuilder drb = new FastReportBuilder();
 
//ajoute le tableau dans l'entete du rapport
drb.addHeaderCrosstab(djcross); 
 
drb.setPrintColumnNames(true)
   .setAllowDetailSplit(false)
 
//Pour Excel, aucune pagination
   .setIgnorePagination(true) 
 
   .setMargins(0, 0, 0, 0)
   .setTitle("titre")
   .setSubtitle("sous titre")
   .setPageSizeAndOrientation(new Page(5000, 5000, false))
   .setUseFullPageWidth(true);
 
DynamicReport dr = drb.build();
 
Map<String, Object> params = new HashMapBilan(critereBilan, "Montant : ", map);
 
jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(),lignes );
 
JasperReport jr = DynamicJasperHelper.generateJasperReport(dr,  new ClassicLayoutManager(), params);
 
Collection dummyCollection = lignes;
dummyCollection = SortUtils.sortCollection(dummyCollection,dr.getColumns());
 
JRDataSource ds = new JRBeanCollectionDataSource(dummyCollection);	
jp = JasperFillManager.fillReport(jr, params,ds);
 
// un petit utilitaire pour afficher intégré dans l'API
JasperViewer.viewReport(jp);

2 : Un exemple de feuille de style pour rendre plus sympathique le rapport ainsi généré.

initStyles();
 
private void initStyles() {
new StyleBuilder(false).setFont(Font.ARIAL_BIG_BOLD).setHorizontalAlign(HorizontalAlign.LEFT)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setTransparency(Transparency.OPAQUE)
	.setBorderBottom(Border.PEN_2_POINT)
	.build();
 
totalHeaderStyle = new StyleBuilder(false)
	.setHorizontalAlign(HorizontalAlign.CENTER)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM_BOLD)
	.setTextColor(Color.BLACK)
	.setBackgroundColor(Color.orange)
	.setTransparent(false)
	.build();
 
new StyleBuilder(false)
	.setHorizontalAlign(HorizontalAlign.CENTER)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM_BOLD)
	.setTextColor(Color.BLACK)
	.setBackgroundColor(Color.orange)
	.build();
 
colAndRowHeaderStyle = new StyleBuilder(false)
	.setHorizontalAlign(HorizontalAlign.CENTER)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM)
	.build();
 
mainHeaderStyle = new StyleBuilder(false)
	.setHorizontalAlign(HorizontalAlign.LEFT)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM)
	.setTextColor(Color.BLACK)
	.build();
 
totalStyle = new StyleBuilder(false).setPattern("#,###")
	.setHorizontalAlign(HorizontalAlign.CENTER)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM_BOLD)
	.setBackgroundColor(Color.orange)
	.setBorderColor(Color.BLACK)
	.setTransparent(false)
	.build();
 
measureStyle = new StyleBuilder(false).setPattern("#,###")
	.setHorizontalAlign(HorizontalAlign.CENTER)
	.setVerticalAlign(VerticalAlign.MIDDLE)
	.setFont(Font.ARIAL_MEDIUM)
	.setStretching(Stretching.RELATIVE_TO_TALLEST_OBJECT)
	.build();
}