Jump to: navigation, search

Scout/Tutorial/3.8/JasperReports Integration

Introduction

With this tutorial you will learn how to integrate the reporting library JasperReports into your Scout-application.

Lets assume you have completed the MiniCRM Tutorial.

The goal is the following functionality:

  • Choose "Generate report..." in the context menu of the company.
  • Generate the report of the selected company on the server.
  • Transfer the report to the client.
  • Open the report in the default pdf-viewer.

Part I - Integrate reporting engine

You need a plugin on the server side which holds all necessary files for the reporting engine. The scout sdk provides an easy way to create such a plugin. But first you have to download the Jasper Reports project from sourceforge and extract the contents somewhere.

Now create a new library bundle linked with the server.

ScoutTutorial-add-library-bundle.png

Add all jars from the lib folder and jasperreports-X.Y.Z.jar from the dist folder of jasperreports to the bundle.

ScoutTutorial-add-jasperlibs.png

Use org.eclipse.scout.minicrm.jasperreports as bundle name.

ScoutTutorial-new-server-bundle.png

Part II - Create the company report

The next step would be to create a basic company report. To bundle the report files with the server we need to create a new Plug-In Project "org.eclipse.scout.minicrm.reports", add it as Required-Plug-in to server and as dependency to the server product.

ScoutTutorial-new-plugin-project.png

ScoutTutorial-add-reports-plugin-to-product.png

ScoutTutorial-add-reports-dependency.png

Now switch to the Package Explorer and create a folder "reports" in the new plugin. Add the reports folder to the binary build in the build.properties file of the reports plugin.

ScoutTutorial-add-reports-dir.png

Use either iReport (http://sourceforge.net/projects/ireport/) to create a new company report company.jrxml in the reports folder or copy and paste the xml-code below in an eclipse text editor.

  • In iReport create a new Paramter "COMPANY_ID" type Long
  • add two String-fields "SHORT_NAME" and "NAME".
  • Delete all bands except Detail 1.
  • Create a query
SELECT * FROM COMPANY WHERE COMPANY_NR=$P{COMPANY_NR}

ScoutTutorial-ireport.png

  • Pull the fields SHORT_NAME and NAME into the Detail 1 band to create two text fields.
  • Now save and compile the report.

The resulting company.jrxml file should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<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="company" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="1323c093-d996-4147-9bf1-70dd55938124">
	<property name="ireport.zoom" value="1.0"/>
	<property name="ireport.x" value="0"/>
	<property name="ireport.y" value="0"/>
	<parameter name="COMPANY_NR" class="java.lang.Long"/>
	<queryString language="SQL">
		<![CDATA[SELECT * FROM COMPANY WHERE COMPANY_NR=$P{COMPANY_NR}]]>
	</queryString>
	<field name="SHORT_NAME" class="java.lang.String"/>
	<field name="NAME" class="java.lang.String"/>
	<background>
		<band splitType="Stretch"/>
	</background>
	<detail>
		<band height="42" splitType="Stretch">
			<textField>
				<reportElement uuid="fa7e30cb-3ea6-440b-b63a-dc78ad1a9b75" x="0" y="0" width="100" height="20"/>
				<textElement/>
				<textFieldExpression><![CDATA[$F{SHORT_NAME}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement uuid="16560b8b-c67b-434e-a669-0f1cf2a7d7ec" x="0" y="20" width="100" height="20"/>
				<textElement/>
				<textFieldExpression><![CDATA[$F{NAME}]]></textFieldExpression>
			</textField>
		</band>
	</detail>
</jasperReport>

Part III - Create the report on the server

Now you have to create a service which generates the report. First you need a new Custom Service Package called org.eclipse.scout.minicrm.server.services.custom.reporting. In this package you can create a new ReportingService.

ScoutTutorial-new-custom-service-package.png

ScoutTutorial-new-service-package.png

In this ReportingService you need to create a new Service Operation "createCompanyReport"

ScoutTutorial-new-service-operation-company-report.png

  @Override
  public byte[] createCompanyReport(Long companyID) throws ProcessingException {
    JasperPrint jasperPrint;
    // create a map to pass parameters to the report
    HashMap<String, Object> parameter = new HashMap<String, Object>();
    parameter.put("COMPANY_NR", companyID);
    try {
      // load the report from the reports plugin
      URL url = new URL("platform:/plugin/org.eclipse.scout.minicrm.reports/reports/company.jrxml");
      InputStream inputStream = url.openConnection().getInputStream();
      // compile the report
      JasperReport report = JasperCompileManager.compileReport(inputStream);
      // let Jasper Reports use our already defined SQL Connection
      jasperPrint = JasperFillManager.fillReport(report, parameter, SQL.getConnection());
      // don’t create a file but let jasper put the contents in an byte array
      ByteArrayOutputStream ba = new ByteArrayOutputStream();
      JasperExportManager.exportReportToPdfStream(jasperPrint, ba);
      // return the contents to the caller
      return ba.toByteArray();
    }
    catch (JRException e) {
      throw new ProcessingException("An error occured during the creation of the report.", e);
    }
    catch (MalformedURLException e) {
      throw new ProcessingException("Can't load the report file.", e);
    }
    catch (IOException e) {
      throw new ProcessingException("An IO-error occured while reading the report file.", e);
    }
  }

Part IV - Save and open the report on the client

Now create a new client service FileService and add a service operation openPdfFile to save the contents to a temporary file and open it with the default pdf-viewer.

ScoutTutorial-new-service-operation-openpdffile.png

  @Override
  public void openPdfFile(byte[] contents) throws ProcessingException {
    if (contents.length > 0) {
      // get a path to save the file
      File tmpPath = Activator.getDefault().getStateLocation().toFile();
      File tmpFile;
      try {
        String extension = ".pdf";
        String name = "report-";
        // get e unique temporary name
        tmpFile = File.createTempFile(name, extension, tmpPath);
        FileOutputStream fo = new FileOutputStream(tmpFile);
        fo.write(contents);
        fo.close();
        // let the vm handle the deletion of the temp file
        tmpFile.deleteOnExit();
        // use the ShellService to open the associated program
        SERVICES.getService(IShellService.class).shellOpen(tmpFile.getAbsolutePath());
      }
      catch (IOException e) {
        throw new ProcessingException("Can't create or write to tmp File.", e);
      }
    }
    else {
      throw new ProcessingException("Can't open report file.");
    }
  }

Part V - Call the services

The last thing you need to do is to add a new menu to the CompaniesTablePage and implement the execAction:

ScoutTutorial-add-generate-report-menu.png

  @Override
  protected void execAction() throws ProcessingException {
    byte[] report = SERVICES.getService(IReportingService.class).createCompanyReport(getTable().getCompanyNrColumn().getSelectedValue());
    SERVICES.getService(FileService.class).openPdfFile(report);
  }

Result

The result should look like this:

ScoutTutorial-result.png