Source code for a simple Java report application
This simple Java source file provides an example of a report program written in Java, using the Genero Report Writer for Java APIs.
- Creates the data model.
- Loads the data into memory.
- Configures the output of the report.
- Streams the data to the report engine.
/*
* FOURJS_START_COPYRIGHT(U,2003)
* Property of Four Js*
* (c) Copyright Four Js 2003, 2021. All Rights Reserved.
* * Trademark of Four Js Development Tools Europe Ltd
* in the United States and elsewhere
*
* Four Js and its suppliers do not warrant or guarantee that these samples are
* accurate and suitable for your purposes.
* Their inclusion is purely for information purposes only.
* FOURJS_END_COPYRIGHT
*/
import com.fourjs.report.runtime.*;
import java.awt.Desktop;
import java.io.File;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import javax.xml.bind.JAXBException;
import org.xml.sax.SAXException;
import java.util.Vector;
import java.util.Date;
//The XmlRootElement annotation causes an global element declaration to be produced in the schema.
@XmlRootElement
public class Sales {
//The XmlElement annotation maps a property to an XML element.
//The Genero Engine does not support optional variables so setting "required=true" is mandatory.
//If a variable needs to be optional then use "nillable=true" and set the variable to null when
//there is no value. If a primitive type needs to be optional then use the corresponding
//object wrapper instead (e.g java.lang.Integer for "int").
@XmlElement(required = true, nillable = true)
public String shopName;
@XmlElement(required = true)
public int zipCode;
@XmlElement(required = true, nillable = true)
public Date day;
//This and any other public collection will be serialized in the order they are declared descending
//recursively into the classes contained in the collections.
public Vector<SalesItem> items=new Vector<SalesItem>();
public Sales(String shopName, int zipCode, Date day)
{
this.shopName=shopName;
this.zipCode=zipCode;
this.day=day;
items.add(new SalesItem("Table lamp",SalesItem.Category.Furniture,23.00,null));
items.add(new SalesItem("Table lamp",SalesItem.Category.Furniture,267.00, items.lastElement()));
items.add(new SalesItem("Office chair",SalesItem.Category.Furniture,155.00, items.lastElement()));
items.add(new SalesItem("Grandfather clock",SalesItem.Category.Furniture,329.00, items.lastElement()));
items.add(new SalesItem("Scissors",SalesItem.Category.Supplies,19.00, items.lastElement()));
items.add(new SalesItem("Measuring tape",SalesItem.Category.Supplies,23.00, items.lastElement()));
items.add(new SalesItem("Sun glasses",SalesItem.Category.Travelling,15.95, items.lastElement()));
items.add(new SalesItem("Pen knife",SalesItem.Category.Travelling,6.25, items.lastElement()));
items.add(new SalesItem("Ornate angel",SalesItem.Category.Art,1.95, items.lastElement()));
}
/** Default Constructor that is required for JAXB deserialization.
In this program this is never used.
*/
public Sales() { assert false; }
/**
Runs the report using the design file specified in args[0] or "SalesList.4rp" otherwise.
The program creates the file "SalesList.pdf" and opens it using Desktop.open() which will typically
invoke the Acrobat Reader.
*/
public static void main(String[] args) throws JAXBException, IOException, SAXException
{
String designFile;
String outputFilename = "SalesList.pdf";
if (args.length == 0) {
designFile = "../src/SalesList.4rp";
} else {
designFile = args[0];
}
FormatHandler handler = new FormatWriter(outputFilename);
PDFRenderer renderer = new PDFRenderer(handler);
FourRpLayouter report = new FourRpLayouter(designFile, renderer);
report.setDebugLevel(9);
Sales data = new Sales("Columbus Arts", 75038, new Date());
report.runFromJAXBObject(data);
// open the file
File result = new File(outputFilename);
Desktop desktop = Desktop.getDesktop();
desktop.open(result);
}
}
class SalesItem
{
public enum Category {Furniture, Art, Supplies, Travelling };
@XmlElement(required = true, nillable = true)
public String articleName;
@XmlElement(required = true, nillable = true)
public Category category;
@XmlElement(required = true)
public double price;
@XmlElement(required = true)
public double runningTotal;
//The previous item is passed to allow computing the running total.
public SalesItem(String articleName, Category category, double price, SalesItem previousItem)
{
this.articleName=articleName;
this.category=category;
this.price=price;
this.runningTotal=previousItem==null?price:previousItem.runningTotal+price;
}
/** Default Constructor that is required for JAXB deserialization.
In this program this is never used.
*/
public SalesItem() { }
}
An overview of the simple report
public class Sales
- whereSales
represents the sales of a particular shop on a particular day.class SalesItem
- whereSalesItems
represents the individual items sold in the shop on that day.
POJO means that the objects are not required to implement any specific interfaces or to be extensions of a specific class. These objects are annotated to hint to JAXB how these objects are to be serialized to XML.
- The Report Model Objects, which specifies the data the report will include.
- A
main
method to run the report using a simple list design and to view the result in PDF format.
Since Java 6, JAXB (Java architecture for XML Binding) is available as part of the J2SE standard distribution. It provides a means to serialize plain Java objects in a streaming manner, and it provides a schema generator capable of creating an XML schema from a set of annotated Java classes.
Using this API is the method proposed in this example.
Mandatory Java classes to be imported
import com.fourjs.report.runtime.*;
// Specific class of Genero Report Writer
import java.io.File;
// Generate the report file on disk
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import javax.xml.bind.JAXBException;
import org.xml.sax.SAXException;
XML annotations
@XmlRootElement
- The
@XmlRootElement
annotation causes a global element declaration to be produced in the schema.... @XmlRootElement public class Sales { ...
@XmlElement
- The
@XmlElement
annotation maps a property to an XML element.@XmlElement(required = true, nillable = true) public String shopName; @XmlElement(required = true) public int zipCode; @XmlElement(required = true, nillable = true) public Date day;
Note: The Genero Report Engine does not support optional values; settingrequired=true
is mandatory. If a variable needs to be optional, use "nillable=true
" and set the variable to null when there is no value. @XmlAttribute
- The
@XmlAttribute
annotation maps a property to an XML attribute.
Default Constructor required for JAXB deserialization
The default constructors required for JAXB deserialization are duplicates of the main constructors. While required, they are never used by the program.
Genero Report Writer APIs and Java code highlights
- Use a handler
object.
FormatHandler handler = new FormatWriter(outputFilename);
- Define a renderer according to the expected output format. In this example, the
PDFRenderer
is specified. See Change report output format (Java) for a summary of your choices.PDFRenderer renderer = new PDFRenderer(handler);
- Create the report object specifying the report design file and the renderer
object.
FourRpLayouter report = new FourRpLayouter(designFile, renderer);
- Specify the data.
Sales data = new Sales("Columbus Arts", 75038, new Date());
- Run the report.
report.runFromJAXBObject(data);
The following is an alternative method for running a report, using a data file (.xml) instead of a database.
In our simple program, no iterator is specified. All the data is in memory, and the standard iterator goes through that list in memory, done internally by
RunFromJAXB
. To see code that uses an iterator, examine the code in the OrderReportJava demo.report.runFromXML("my_data_file.xml");
- Generate the report file on
disk.
File result = new File(outputFilename);