Skip to content

DocxReportingJavaMain

Angelo edited this page Mar 1, 2017 · 11 revisions

Docx Reporting in Java Main

This section explains step by step how to generate a report created with MS Word docx by using Velocity syntax to set fields to replace. You can download docxandvelocity-*-sample.zip which is the project explained in this section.

We will create a basic docx document DocxProjectWithVelocity.docx :

The $project.Name is a merge field and project is Java model Project class which define Project#getName(). The field name start with project because we will register the Java Model with project key in the context like this :

Project project = new Project("XDocReport");
context.put("project", project);

After report process we will generate the document DocxProjectWithVelocity_Out.docx :

Steps section are :

  1. Add XDocReport JARs in your classpath project.
  2. Create Java model create your Java model.
  3. Design docx report design your docx report with MS Word by using Velocity syntax to set fields to replace.
  4. Generate docx report generate docx report by using XDocReport API.

If you wish to :

  • use Docx with Freemarker, you could download *docxandfreemarker-**-sample.zip.
  • use Docx with Velocity, you could download *docxandvelocity-**-sample.zip.

Add XDocReport JARs

XDocReport is very modular. It means that you can choose your document type (odt, docx...) as source report and use template engine syntax to set fields name (Freemarker/Velocity...).

In our case we will generate report from docx with Velocity. So we need to set well JARs in your classpath. Here screen of your Eclipse project (if you are using Eclipse) after adding XDocReport JARs :

Required JARs

For any document type and template engine you need to add following JARs :

JARs name Description OSGi Bundle/Fragment
fr.opensagres.xdocreport.core XDocReport Core Bundle
fr.opensagres.xdocreport.document Document type API Bundle
fr.opensagres.xdocreport.template Template engine API Bundle
fr.opensagres.xdocreport.converter Converter API Bundle

Docx Document JAR

In this section we wish using docx as document source for report, so you need to add Docx document implementation JAR:

JARs name Description OSGi Bundle/Fragment
fr.opensagres.xdocreport.document.docx Docx Document implementation Fragment -> fr.opensagres.xdocreport.document

Note for OSGi : this JAR is a fragment linked to the bundle OSGi fr.opensagres.xdocreport.document.

Velocity JARs

In this section we wish to use Velocity as syntax to set fields, so you need to add Velocity template engine implementation and Velocity JARs.

Velocity Template JAR

Add Velocity template engine implementation JAR:

JARs name Description OSGi Bundle/Fragment
fr.opensagres.xdocreport.template.velocity Velocity template engine implementation Fragment -> fr.opensagres.xdocreport.template

Note for OSGi : this JAR is a fragment linked to the bundle OSGi fr.opensagres.xdocreport.template.

Velocity JARs

Add Velocity JARs :

JARs name Description
velocity-1.7 Velocity
commons-collections-3.2.1 Commons Collection
commons-lang-2.4 Commons Lang
oro-2.0.8 ORO

Create Java model

Now you can create your Java model that you wish use in your docx report. In this section we will use Java Project model like this :

package fr.opensagres.xdocreport.samples.docxandvelocity.model;

public class Project {

  private final String name;

  public Project(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

Design Docx report

At this step you can create your docx report with MS Word with the content :

Project: $project.Name

For the field to replace $project.Name, DON'T type directly the field in your document otherwise you could have some troubles because MS Word escape your content.

You must use MergeField (Champs de fusion) and not type directly $project.Name in your documentation.

If you wish to use another template engine directive to manage condition, loop... like :

It's the same thing than field, : DON'T type directly the directive* in your document but use MergeField.

You can note for this sample that you can style field. If you don't know how create MergeField, please see Docx Design Report section.

NOTE : for Freemarker, the square bracket syntax ([instead of <#if) must be used to have valid XML.

Generate docx report

Once you have create docx, save it in your project. In this sample the docx report was saved with DocxProjectWithVelocity.docx name in the fr.opensagres.xdocreport.samples.docxandvelocity package of the Java project.

Create Java class DocxProjectWithVelocity to load DocxProjectWithVelocity.docx and generate report in file DocxProjectWithVelocity_Out.docx like this :

package fr.opensagres.xdocreport.samples.docxandvelocity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.samples.docxandvelocity.model.Project;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

public class DocxProjectWithVelocity {

  public static void main(String[](#if) args) {
    try {
      // 1) Load Docx file by filling Velocity template engine and cache it to the registry
      InputStream in = DocxProjectWithVelocity.class.getResourceAsStream("DocxProjectWithVelocity.docx");
      IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in,TemplateEngineKind.Velocity);

      // 2) Create context Java model
      IContext context = report.createContext();
      Project project = new Project("XDocReport");
      context.put("project", project);

      // 3) Generate report by merging Java model with the Docx
      OutputStream out = new FileOutputStream(new File("DocxProjectWithVelocity_Out.docx"));
      report.process(context, out);

    } catch (IOException e) {
      e.printStackTrace();
    } catch (XDocReportException e) {
      e.printStackTrace();
    }
  }
}

Your Eclipse project looks like this :

Run DocxProjectWithVelocity Java class and DocxProjectWithVelocity_Out.docx will be generated in your project home :

If you open DocxProjectWithVelocity_Out.docx you will see :

Test Performance

XDocReport uses Velocity/Freemarker cache to improve a lot the performance. To test performance, create fr.opensagres.xdocreport.samples.docxandvelocity.DocxProjectWithVelocityTestPerf class like this which display time process for the first and second report generation :

package fr.opensagres.xdocreport.samples.docxandvelocity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.samples.docxandvelocity.model.Project;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

public class DocxProjectWithVelocityTestPerf {

	public static void main(String[] args) {
		try {

			String reportId = "MyId";

			// 1) Load Docx file by filling Velocity template engine and cache
			// it to the registry
			InputStream in = DocxProjectWithVelocityTestPerf.class
					.getResourceAsStream("DocxProjectWithVelocity.docx");
			IXDocReport report = XDocReportRegistry.getRegistry().loadReport(
					in, reportId, TemplateEngineKind.Velocity);

			// 2) Create context Java model
			IContext context = report.createContext();
			Project project = new Project("XDocReport");
			context.put("project", project);

			// 3) Generate report by merging Java model with the Docx
			OutputStream out = new FileOutputStream(new File(
					"DocxProjectWithVelocity_Out.docx"));
			long start = System.currentTimeMillis();
			report.process(context, out);
			System.out.println("Report processed in "
					+ (System.currentTimeMillis() - start) + " ms");

			// 4) Regenerate report
			IXDocReport report2 = XDocReportRegistry.getRegistry().getReport(
					reportId);
			out = new FileOutputStream(new File(
					"DocxProjectWithVelocity_Out.docx"));
			start = System.currentTimeMillis();
			report2.process(context, out);
			System.out.println("Report processed in "
					+ (System.currentTimeMillis() - start) + " ms");

		} catch (IOException e) {
			e.printStackTrace();
		} catch (XDocReportException e) {
			e.printStackTrace();
		}
	}
}

Run DocxProjectWithVelocityTestPerf Java class and DocxProjectWithVelocity_Out.docx will be generated twice and console display time process :

Report processed in 250 ms
Report processed in 16 ms

You can notice that the second report generation is very quick. This time is explained with use of velocity cache which cache the XML entry to merge with Java model.

Here report is loaded by filling an id :

String reportId = "MyId";

// 1) Load Docx file by filling Velocity template engine and cache
// it to the registry
InputStream in = DocxProjectWithVelocityTestPerf.class.getResourceAsStream("DocxProjectWithVelocity.docx");

The report is retrieved form the registry with this code :

IXDocReport report2 = XDocReportRegistry.getRegistry().getReport(reportId);

More features

Clone this wiki locally