Signaler des scriptlets

Nous l'avons vu dans nos chapitres précédents, les données affichées sur le rapport sont généralement extraites des paramètres du rapport et des champs du rapport. Ces données peuvent être traitées à l'aide des variables de rapport et de leurs expressions. Il existe des situations où une fonctionnalité complexe ne peut pas être obtenue facilement à l'aide d'expressions ou de variables de rapport. Des exemples de cela peuvent être des manipulations complexes de chaînes, la construction de cartes ou des listes d'objets en mémoire ou des manipulations de dates à l'aide d'API Java tierces. Pour de telles situations, JasperReports nous fournit un moyen simple et puissant de le faire avecScriptlets.

Les scriptlets sont des séquences de code Java qui sont exécutées chaque fois qu'un événement de rapport se produit. Les valeurs des variables de rapport peuvent être affectées par les scriptlets.

Déclaration de scriptlet

Nous pouvons déclarer un scriptlet de deux manières -

  • En utilisant <scriptlet> élément. Cet élément a un attribut de nom et un attribut de classe . L' attribut class doit spécifier le nom de la classe, qui étend la classe JRAbstractScriptlet . La classe doit être disponible dans le classpath au moment du remplissage du rapport et doit avoir un constructeur vide, afin que le moteur puisse l'instancier à la volée.

  • Utilisation de l'attribut scriptletClass de l'élément <jasperReport>, dans le modèle de rapport (JRXML). En définissant cet attribut avec le nom complet du scriptlet (y compris le nom complet du package), nous indiquons que nous voulons utiliser un scriptlet. L'instance de scriptlet, créée avec cet attribut, agit comme le premier scriptlet de la liste des scriptlets et porte le nom prédéfini REPORT.

Classe de scriptlet

Un scriptlet est une classe java, qui doit étendre l'une des classes suivantes -

  • net.sf.jasperreports.engine.JRAbstractScriptlet- Cette classe contient un certain nombre de méthodes abstraites qui doivent être remplacées dans chaque implémentation. Ces méthodes sont appelées automatiquement par JasperReports au moment opportun. Le développeur doit implémenter toutes les méthodes abstraites.

  • net.sf.jasperreports.engine.JRDefaultScriptlet- Cette classe contient les implémentations vides par défaut de chaque méthode dans JRAbstractScriptlet. Un développeur n'est tenu de mettre en œuvre que les méthodes dont il a besoin pour son projet.

Le tableau suivant répertorie les méthodes de la classe ci-dessus. Ces méthodes seront appelées par le moteur de rapport au moment opportun, lors de la phase de remplissage du rapport.

S.NON Méthode et description
1

public void beforeReportInit()

Appelé avant l'initialisation du rapport.

2

public void afterReportInit()

Appelé après l'initialisation du rapport.

3

public void beforePageInit()

Appelé avant l'initialisation de chaque page.

4

public void afterPageInit()

Appelé après l'initialisation de chaque page.

5

public void beforeColumnInit()

Appelé avant l'initialisation de chaque colonne.

6

public void afterColumnInit()

Appelé après l'initialisation de chaque colonne.

sept

public void beforeGroupInit(String groupName)

Appelé avant l'initialisation du groupe spécifié dans le paramètre.

8

public void afterGroupInit(String groupName)

Appelé après l'initialisation du groupe spécifié dans le paramètre.

9

public void beforeDetailEval()

Appelé avant que chaque enregistrement de la section Détails du rapport ne soit évalué.

dix

public void afterDetailEval()

Appelé après chaque enregistrement dans la section détail du rapport est évalué.

N'importe quel nombre de scriptlets peut être spécifié par rapport. Si aucun scriptlet n'est spécifié pour un rapport, le moteur crée toujours une seule instance JRDefaultScriptlet et l'enregistre avec le paramètre REPORT_SCRIPTLET intégré.

Nous pouvons ajouter toutes les méthodes supplémentaires dont nous avons besoin à nos scriptlets. Les rapports peuvent appeler ces méthodes à l'aide du paramètre intégré REPORT_SCRIPTLET.

Scriptlets globaux

Nous pouvons associer des scriptlets d'une autre manière aux rapports, c'est-à-dire en déclarant les scriptlets globalement. Cela permet aux scriptlets de s'appliquer à tous les rapports remplis dans le déploiement JasperReports donné. Ceci est rendu facile par le fait que des scriptlets peuvent être ajoutés à JasperReports en tant qu'extensions. Le point d'extension du scriptlet est représenté par l' interface net.sf.jasperreports.engine.scriptlets.ScriptletFactory . JasperReports chargera toutes les fabriques de scriptlets disponibles via les extensions au moment de l'exécution. Ensuite, il demandera à chacun d'entre eux la liste des instances de scriptlets qu'ils souhaitent appliquer au rapport en cours d'exécution. Lorsqu'il demande la liste des instances de scriptlet, le moteur donne des informations de contexte que l'usine pourrait utiliser afin de décider quels scriptlets s'appliquent réellement au rapport actuel.

Gouverneurs du rapport

Les gouverneurs ne sont qu'une extension de scriptlets globaux qui nous permettent de résoudre un problème de moteur de rapport entrant en boucle infinie lors de l'exécution, tout en générant des rapports. Les modèles de rapport non valides ne peuvent pas être détectés au moment de la conception, car la plupart du temps, les conditions de saisie des boucles infinies dépendent des données réelles qui sont introduites dans le moteur au moment de l'exécution. Les gouverneurs de rapports aident à décider si un certain rapport est entré dans une boucle infinie et ils peuvent l'arrêter. Cela empêche l'épuisement des ressources pour la machine qui exécute le rapport.

JasperReports a deux gouverneurs de rapport simples qui arrêteraient l'exécution d'un rapport en fonction d'un nombre maximal de pages spécifié ou d'un intervalle de délai spécifié. Ils sont -

  • net.sf.jasperreports.governors.MaxPagesGovernor- Il s'agit d'un scriptlet global qui recherche deux propriétés de configuration pour décider s'il s'applique ou non au rapport en cours d'exécution. Les propriétés de configuration sont -

    • net.sf.jasperreports.governor.max.pages.enabled=[true|false]

    • net.sf.jasperreports.governor.max.pages=[integer]

  • net.sf.jasperreports.governors.TimeoutGovernor- Il s'agit également d'un scriptlet global qui recherche les deux propriétés de configuration suivantes pour décider s'il s'applique ou non.

    Les propriétés de configuration sont -

    • net.sf.jasperreports.governor.timeout.enabled=[true|false]

    • net.sf.jasperreports.governor.timeout=[milliseconds]

Les propriétés des deux gouverneurs peuvent être définies globalement, dans le fichier jasperreports.properties, ou au niveau du rapport, en tant que propriétés de rapport personnalisées. Ceci est utile car différents rapports peuvent avoir une taille estimée ou des délais d'expiration différents et également parce que vous pouvez activer les gouverneurs pour tous les rapports, tout en les désactivant pour certains, ou vice-versa.

Exemple

Écrivons une classe de scriptlet (MyScriptlet). Le contenu du fichier C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ MyScriptlet.java est le suivant -

package com.tutorialspoint;

import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;


public class MyScriptlet extends JRDefaultScriptlet {

   public void afterReportInit() throws JRScriptletException{
      System.out.println("call afterReportInit()");
      // this.setVariableValue("AllCountries", sbuffer.toString());
      this.setVariableValue("someVar", new String("This variable value 
         was modified by the scriptlet."));
   }

   public String hello() throws JRScriptletException {
      return "Hello! I'm the report's scriptlet object.";
   }

}

Les détails de la classe de scriptlet ci-dessus sont les suivants -

  • Dans la méthode afterReportInit , nous définissons une valeur sur la variable"someVar" this.setVariableValue ("someVar", new String ("Cette valeur de variable a été modifiée par le scriptlet.")).

  • À la fin du cours, une méthode supplémentaire appelée 'hello'a été défini. Voici un exemple de méthode qui peut être ajoutée au scriptlet qui renvoie en fait une valeur, plutôt que de définir une variable.

Ensuite, nous ajouterons la référence de classe de scriptlet dans notre modèle de rapport existant (Chapter Report Designs ). Le modèle de rapport révisé (jasper_report_template.jrxml) est le suivant. Enregistrez-le dans le répertoire C: \ tools \ jasperreports-5.0.1 \ test -

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<jasperReport xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50"
   scriptletClass = "com.tutorialspoint.MyScriptlet">
	
   <style name = "alternateStyle" fontName = "Arial" forecolor = "red">
      
      <conditionalStyle>
         <conditionExpression>
            <![CDATA[new Boolean($V{countNumber}.intValue() % 2 == 0)]]>
         </conditionExpression>
			
         <style forecolor = "blue" isBold = "true"/>
      </conditionalStyle>
   </style>
   
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[country]]>
      </fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[name]]>
      </fieldDescription>
   </field>

   <variable name = "countNumber" class = "java.lang.Integer" 
      calculation = "Count">
      <variableExpression><
         ![CDATA[Boolean.TRUE]]>
      </variableExpression>
   </variable>

   <variable name = "someVar" class = "java.lang.String">
      <initialValueExpression>
        <![CDATA["This is the initial variable value."]]>
      </initialValueExpression>
   </variable>

   <title>
      <band height = "100">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
              <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
              <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
				
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
        
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "50" width = "515" 
               height = "30" forecolor = "#993300"/>
             
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$V{someVar}]]>
            </textFieldExpression>
				
         </textField>

      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
				
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
                
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535"	height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement style = "alternateStyle" x="414" y = "0" 
               width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
				
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <summary>
      <band height = "45">
            
         <textField isStretchWithOverflow = "true">
            <reportElement x = "0" y = "10" width = "515" height = "15" />
            <textElement textAlignment = "Center"/>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA["There are " + String.valueOf($V{REPORT_COUNT}) +
                  " records on this report."]]>
            </textFieldExpression>
         </textField>
         
         <textField isStretchWithOverflow = "true">
            <reportElement positionType = "Float" x = "0" y = "30" width = "515"
               height = "15" forecolor = "# 993300" />
               
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{REPORT_SCRIPTLET}.hello()]]>
            </textFieldExpression>
            
         </textField>
         
      </band>
   </summary>
	
</jasperReport>

Les détails du modèle de rapport révisé sont donnés ci-dessous -

  • Nous avons référencé la classe MyScriptlet dans l'attribut scriptletClass de l'élément <jasperReport>.

  • Les scriptlets peuvent uniquement accéder aux champs et paramètres du rapport, mais pas les modifier. Cependant, les scriptlets peuvent modifier les valeurs des variables de rapport. Cela peut être accompli en appelant la méthode setVariableValue (). Cette méthode est définie dans la classe JRAbstractScriptlet, qui est toujours la classe parente de tout scriptlet. Ici, nous avons défini une variable someVar , qui sera modifiée par le MyScriptlet pour avoir la valeur Cette valeur a été modifiée par le scriptlet .

  • Le modèle de rapport ci-dessus a un appel de méthode dans la bande Résumé qui illustre comment écrire de nouvelles méthodes (dans des scriptlets) et les utiliser dans le modèle de rapport. ($P{REPORT_SCRIPTLET}.hello())

Les codes java pour le remplissage des rapports restent inchangés. Le contenu du fichierC:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java sont comme indiqué ci-dessous -

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

Le contenu du fichier POJO C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java sont comme indiqué ci-dessous -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

Le contenu du fichier C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java sont comme indiqué ci-dessous -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

Génération de rapports

Nous compilerons et exécuterons le fichier ci-dessus en utilisant notre processus de construction ANT normal. Le contenu du fichier build.xml (enregistré sous le répertoire C: \ tools \ jasperreports-5.0.1 \ test) est indiqué ci-dessous.

Le fichier d'importation - baseBuild.xml est extrait du chapitre Configuration de l'environnement et doit être placé dans le même répertoire que le build.xml.

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview 
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>

</project>

Ensuite, ouvrons la fenêtre de ligne de commande et allons dans le répertoire où build.xml est placé. Enfin, exécutez la commandeant -Dmain-class=com.tutorialspoint.JasperReportFill (viewFullReport est la cible par défaut) comme -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to bu
   [javac] Compiling 4 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] call afterReportInit()
   [java] call afterReportInit()

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 minutes 49 seconds

À la suite de la compilation ci-dessus, une fenêtre JasperViewer s'ouvre comme indiqué dans l'écran ci-dessous -

Ici, nous voyons que deux messages sont affichés à partir de la classe MyScriptlet -

  • Dans la section titre - Cette valeur de variable a été modifiée par le scriptlet
  • En bas - Bonjour! Je suis l'objet de scriptlet du rapport.