Учебники

Скрипты отчетов

Мы видели в наших предыдущих главах, данные, отображаемые в отчете, обычно выбираются из параметров отчета и полей отчета. Эти данные могут быть обработаны с использованием переменных отчета и их выражений. Существуют ситуации, когда сложная функциональность не может быть легко достигнута с помощью выражений или переменных отчета. Примерами этого могут быть сложные манипуляции со строками, построение карт или списки объектов в памяти или манипуляции датами с использованием сторонних API Java. Для таких ситуаций JasperReports предоставляет нам простой и мощный способ сделать это с помощью Scriptlets .

Скриплеты — это последовательности кода Java, которые выполняются каждый раз, когда происходит событие отчета. На значения переменных отчета можно воздействовать через скриптлеты.

Декларация сценария

Мы можем объявить скриптлет двумя способами:

  • Использование элемента < scriptlet >. Этот элемент имеет атрибут name и class class . Атрибут class должен указывать имя класса, который расширяет класс JRAbstractScriptlet . Класс должен быть доступен в пути к классам во время заполнения отчета и должен иметь пустой конструктор, чтобы механизм мог создать его экземпляр на лету.

  • Использование атрибута scriptletClass элемента < jasperReport > в шаблоне отчета (JRXML). Устанавливая этот атрибут с полностью определенным именем скриптлета (включая полное имя пакета), мы указываем, что хотим использовать скриптлет. Экземпляр скриптлета, созданный с этим атрибутом, действует как первый скриптлет в списке скриплетов и имеет предопределенное имя REPORT.

Использование элемента < scriptlet >. Этот элемент имеет атрибут name и class class . Атрибут class должен указывать имя класса, который расширяет класс JRAbstractScriptlet . Класс должен быть доступен в пути к классам во время заполнения отчета и должен иметь пустой конструктор, чтобы механизм мог создать его экземпляр на лету.

Использование атрибута scriptletClass элемента < jasperReport > в шаблоне отчета (JRXML). Устанавливая этот атрибут с полностью определенным именем скриптлета (включая полное имя пакета), мы указываем, что хотим использовать скриптлет. Экземпляр скриптлета, созданный с этим атрибутом, действует как первый скриптлет в списке скриплетов и имеет предопределенное имя REPORT.

Класс сценариев

Скриплет — это Java-класс, который должен расширять любой из следующих классов:

  • net.sf.jasperreports.engine.JRAbstractScriptlet — этот класс содержит ряд абстрактных методов, которые должны быть переопределены в каждой реализации. Эти методы автоматически вызываются JasperReports в соответствующий момент. Разработчик должен реализовать все абстрактные методы.

  • net.sf.jasperreports.engine.JRDefaultScriptlet — этот класс содержит пустые реализации по умолчанию для каждого метода в JRAbstractScriptlet. От разработчика требуется только реализовать те методы, которые ему нужны для его / ее проекта.

net.sf.jasperreports.engine.JRAbstractScriptlet — этот класс содержит ряд абстрактных методов, которые должны быть переопределены в каждой реализации. Эти методы автоматически вызываются JasperReports в соответствующий момент. Разработчик должен реализовать все абстрактные методы.

net.sf.jasperreports.engine.JRDefaultScriptlet — этот класс содержит пустые реализации по умолчанию для каждого метода в JRAbstractScriptlet. От разработчика требуется только реализовать те методы, которые ему нужны для его / ее проекта.

В следующей таблице перечислены методы в вышеприведенном классе. Эти методы будут вызываться механизмом отчетов в соответствующее время, на этапе заполнения отчета.

S.NO Метод и описание
1

public void beforeReportInit ()

Вызывается до инициализации отчета.

2

public void afterReportInit ()

Вызывается после инициализации отчета.

3

public void beforePageInit ()

Вызывается перед инициализацией каждой страницы.

4

public void afterPageInit ()

Вызывается после инициализации каждой страницы.

5

public void beforeColumnInit ()

Вызывается перед инициализацией каждого столбца.

6

public void afterColumnInit ()

Вызывается после инициализации каждого столбца.

7

public void beforeGroupInit (String groupName)

Вызывается до инициализации группы, указанной в параметре.

8

public void afterGroupInit (String groupName)

Вызывается после инициализации группы, указанной в параметре.

9

public void beforeDetailEval ()

Вызывается перед каждой записью в подробном разделе отчета.

10

public void afterDetailEval ()

Вызывается после каждой записи в подробном разделе отчета.

public void beforeReportInit ()

Вызывается до инициализации отчета.

public void afterReportInit ()

Вызывается после инициализации отчета.

public void beforePageInit ()

Вызывается перед инициализацией каждой страницы.

public void afterPageInit ()

Вызывается после инициализации каждой страницы.

public void beforeColumnInit ()

Вызывается перед инициализацией каждого столбца.

public void afterColumnInit ()

Вызывается после инициализации каждого столбца.

public void beforeGroupInit (String groupName)

Вызывается до инициализации группы, указанной в параметре.

public void afterGroupInit (String groupName)

Вызывается после инициализации группы, указанной в параметре.

public void beforeDetailEval ()

Вызывается перед каждой записью в подробном разделе отчета.

public void afterDetailEval ()

Вызывается после каждой записи в подробном разделе отчета.

В отчете может быть указано любое количество скриптлетов. Если скриптлет не указан для отчета, механизм все равно создает один экземпляр JRDefaultScriptlet и регистрирует его с помощью встроенного параметра REPORT_SCRIPTLET.

Мы можем добавить любые дополнительные методы, которые нам нужны, к нашим скриптлетам. Отчеты могут вызывать эти методы с помощью встроенного параметра REPORT_SCRIPTLET.

Глобальные сценарии

Мы можем связать скриптлеты с отчетами по-другому, то есть объявить скриптлеты глобально. Это заставляет скриптлеты применяться ко всем отчетам, заполняемым в данном развертывании JasperReports. Это легко сделать благодаря тому, что скриптлеты могут быть добавлены в JasperReports в качестве расширений. Точка расширения сценария представлена интерфейсом net.sf.jasperreports.engine.scriptlets.ScriptletFactory . JasperReports загрузит все фабрики скриплетов, доступные через расширения во время выполнения. Затем он запросит у каждого из них список экземпляров скриптлетов, которые они хотят применить к текущему отчету, который выполняется. При запросе списка экземпляров сценариев механизм предоставляет некоторую контекстную информацию, которую фабрика может использовать, чтобы решить, какие сценарии действительно применяются к текущему отчету.

Отчет губернаторов

Регуляторы — это всего лишь расширение глобальных скриплетов, которые позволяют нам решать проблему, связанную с тем, что механизм отчетов входит в бесконечный цикл во время выполнения при создании отчетов. Неверные шаблоны отчетов не могут быть обнаружены во время разработки, поскольку в большинстве случаев условия для ввода бесконечных циклов зависят от фактических данных, которые вводятся в двигатель во время выполнения. Органы управления отчетами помогают в принятии решения о том, вошел ли определенный отчет в бесконечный цикл, и они могут его остановить. Это предотвращает исчерпание ресурсов для машины, на которой выполняется отчет.

JasperReports имеет два простых регулятора отчетов, которые будут останавливать выполнение отчета на основе указанного максимального числа страниц или указанного интервала времени ожидания. Они —

  • net.sf.jasperreports.governors.MaxPagesGovernor — это глобальный скриптлет, который ищет два свойства конфигурации, чтобы определить, применяется он или нет к отчету, который выполняется в данный момент. Свойства конфигурации:

    • net.sf.jasperreports.governor.max.pages.enabled = [правда | ложь]

    • net.sf.jasperreports.governor.max.pages = [целое число]

  • net.sf.jasperreports.governors.TimeoutGovernor — это также глобальный скриптлет, который ищет следующие два свойства конфигурации, чтобы определить, применяется он или нет.

    Свойства конфигурации:

    • net.sf.jasperreports.governor.timeout.enabled = [правда | ложь]

    • net.sf.jasperreports.governor.timeout = [] миллисекунд

net.sf.jasperreports.governors.MaxPagesGovernor — это глобальный скриптлет, который ищет два свойства конфигурации, чтобы определить, применяется он или нет к отчету, который выполняется в данный момент. Свойства конфигурации:

net.sf.jasperreports.governor.max.pages.enabled = [правда | ложь]

net.sf.jasperreports.governor.max.pages = [целое число]

net.sf.jasperreports.governors.TimeoutGovernor — это также глобальный скриптлет, который ищет следующие два свойства конфигурации, чтобы определить, применяется он или нет.

Свойства конфигурации:

net.sf.jasperreports.governor.timeout.enabled = [правда | ложь]

net.sf.jasperreports.governor.timeout = [] миллисекунд

Свойства обоих регуляторов можно задать глобально, в файле jasperreports.properties или на уровне отчета, в качестве пользовательских свойств отчета. Это полезно, потому что разные отчеты могут иметь различный расчетный размер или ограничения по времени, а также потому, что вы можете захотеть включить регуляторы для всех отчетов, в то время как некоторые отключить его, или наоборот.

пример

Давайте напишем класс скриптлета ( MyScriptlet ). Содержимое файла C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ MyScriptlet.java выглядит следующим образом:

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.";
   }

}

Подробности вышеупомянутого класса скриптлета следующие:

  • В методе afterReportInit мы устанавливаем значение для переменной «someVar» this.setVariableValue («someVar», new String («Это значение переменной было изменено сценарием.»)).

  • В конце класса был определен дополнительный метод с именем ‘hello’ . Это пример метода, который может быть добавлен в Scriptlet, который на самом деле возвращает значение, а не устанавливает переменную.

В методе afterReportInit мы устанавливаем значение для переменной «someVar» this.setVariableValue («someVar», new String («Это значение переменной было изменено сценарием.»)).

В конце класса был определен дополнительный метод с именем ‘hello’ . Это пример метода, который может быть добавлен в Scriptlet, который на самом деле возвращает значение, а не устанавливает переменную.

Далее мы добавим ссылку на класс скриптлета в наш существующий шаблон отчета (глава « Конструкции отчета» ). Пересмотренный шаблон отчета (jasper_report_template.jrxml) выглядит следующим образом. Сохраните его в каталоге 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>

Детали пересмотренного шаблона отчета приведены ниже —

  • Мы ссылались на класс MyScriptlet в атрибуте scriptletClass элемента <jasperReport>.

  • Скриплеты могут только получать доступ, но не изменять поля и параметры отчета. Однако скриптлеты могут изменять значения переменных отчета. Это может быть достигнуто путем вызова метода setVariableValue (). Этот метод определен в классе JRAbstractScriptlet, который всегда является родительским классом любого скриптлета. Здесь мы определили переменную someVar , которая будет изменена MyScriptlet, чтобы иметь значение Это значение было изменено скриптлетом .

  • Приведенный выше шаблон отчета имеет вызов метода в группе Summary, который иллюстрирует, как писать новые методы (в скриптлетах) и использовать их в шаблоне отчета. ( $ P {REPORT_SCRIPTLET} .hello () )

Мы ссылались на класс MyScriptlet в атрибуте scriptletClass элемента <jasperReport>.

Скриплеты могут только получать доступ, но не изменять поля и параметры отчета. Однако скриптлеты могут изменять значения переменных отчета. Это может быть достигнуто путем вызова метода setVariableValue (). Этот метод определен в классе JRAbstractScriptlet, который всегда является родительским классом любого скриптлета. Здесь мы определили переменную someVar , которая будет изменена MyScriptlet, чтобы иметь значение Это значение было изменено скриптлетом .

Приведенный выше шаблон отчета имеет вызов метода в группе Summary, который иллюстрирует, как писать новые методы (в скриптлетах) и использовать их в шаблоне отчета. ( $ P {REPORT_SCRIPTLET} .hello () )

Java-коды для заполнения отчетов остаются без изменений. Содержимое файла C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ JasperReportFill.java указано ниже —

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();
      }
   }
}

Содержимое файла POJO C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ DataBean.java указано ниже —

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;
   }
}

Содержимое файла C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ DataBeanList.java указано ниже —

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;
   }
}

Генерация отчетов

Мы скомпилируем и выполним вышеуказанный файл, используя наш обычный процесс сборки ANT. Содержимое файла build.xml (сохраненного в каталоге C: \ tools \ jasperreports-5.0.1 \ test) приведено ниже.

Файл импорта — baseBuild.xml взят из главы « Настройка среды» и должен быть расположен в том же каталоге, что и 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>

Далее, давайте откроем окно командной строки и перейдем в каталог, где находится build.xml. Наконец, выполните команду ant -Dmain-class = com.tutorialspoint.JasperReportFill (viewFullReport является целью по умолчанию) как —

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

В результате вышеупомянутой компиляции открывается окно JasperViewer, как показано на приведенном ниже экране —

Пример Jasper Report Scriplet

Здесь мы видим два сообщения из класса MyScriptlet —