Java
Java developer resources.
Architecture
A schematic diagram of Genero Report Writer for Java
Scalability
A schematic diagram illustrating the distributed nature of Genero Report Writer for Java
Highlights
Detailed feature overview
- Easy to use, WYSIWYG editor,
- Schema based, type-safe editing
- Avoids run-time errors caused by failing string conversions,
- Compile-time impact analysis,
- Lists issues in a report design caused by changes to the schema. This feature is of particular importance for end users that have customized or created their own report designs. Upon receipt of a software update they can check their reports against the new schemas shipped with the update to detect and fix any issues before making the update operational,
- Batch upgrades. A command line tool is available to perform batch upgrades of report design files from one version of the software to another,
- Batch updates and software-assisted issue resolution in the report designer. A command line tool is available to update the report design files in cases where the schemas may have changed (e.g. during an application update and the end user’s site). The update algorithm is optimal in the sense that it finds a minimal patch so that in the general case no manual intervention is required. In the rare case that parts of a schema have been removed or renamed users are assisted in resolving the issues in form of issue list that is persistently stored with the report design file until all issues have been resolved.
- Data stream and document formatting are separate,
- Multiple presentations per data source,
- Defines a clear interface between application vendors who are responsible for providing the data sources and their associated schemas and users who customize or add presentations to them.
- Process level interface as opposed to accessing the database directly,
- Less sensitive to database changes. Process level messages shield users from details of the database and allow application vendors to change the database schema without breaking customized or self made reports,
- Prevents replication of business rules in report designs. By accessing “cooked” data, users are shielded from the need to know details on how things are stored in the database. It avoids the replication of central business logic in the report designs (e.g. rules about which address is actually used as a billing address of an invoice when there are multiple choices in the database),
- Support for structured data as opposed to flat record sets returned by SQL queries. The data behind sophisticated reports such as invoices or delivery can rarely be represented as a flat list of records. The natural representation is a structured message allowing for arbitrary nested lists of different records. Using “sub reports” as in many ad hoc reporting tools is not an adequate solution since it adds unnecessary complexity and typically reverses the network communication causing performance problems due to network latency,
- Novel, serial, graphical matching and transformation language. Conceptually similar to XSL-T, the RTL transformation language is limited in the type of transformations it can do (e.g. no recursion), but can be represented graphically. It works for documents of arbitrary size.
- Single pass, unidirectional processing pipe. Since network latency can be regarded as a resource that does not scale it is important to avoid reversing the communication direction during a job. The engine can be used in a distributed environment with very high roundtrip times and low bandwidth without noticeable decrease in performance,
- Serial processing of arbitrarily sized documents.
- Thousands of pages, low and constant memory,
- Distributed processing and multiple server option. The multi tier option allows to offload the report rendering to one or more separate machines leaving only the data source message creation for the server.
- Pixel exact positioning,
- Relative positioning vertical and horizontal,
- Content propagation vertical and horizontal,
- Multicolumn layout,
- Tabular layout,
- Pivot tables,
- Sub-reports,
- Sophisticated headers and footers,
- Sophisticated page breaking,
- Label printing on varying media. The report design contains the description of a single label abstracting from the actual layout on the media removing the need to change the report design for different label printers or different label sheets,
- Running totals in headers and footers,
- Page n of m in headers and footers while retaining serial processing,
- Self-layouting business graphs,
- Large number of natively implemented bar codes,
- Bitmap and SVG images. The lean scalable vector graphics (also those of other origin such as bar codes and business graphics) are preserved in all formats that support vector drawing such as PDF, browser or printer output. In all other formats they are rendered into bitmaps.
- Design time API
- API for schema introspection,
- API for report design file introspection and generation,
- API for template based report design generation,
- API for pivot table configuration.
- Run time API
- Data level API,
- Selection of source,
- Configuration of localization,
- Recommend JAXB for schema generation and marshalling,
- Document level API,
- Selection of design,
- Configuration of page characteristics,
- Configuration of label layout,
- Device level API
- Selection of device (e.g. PDF, server printer, client printer, ..),
- Device specific configuration (e.g. Paper tray selection of printer).
- Data level API,
- Browser based report viewer
- Low band-width,
- 100% pixel exact rendering,
- Uses cacheable WOFF fonts and SVG vector graphics,
- Streaming capable for immediate rendering of huge reports,
- Fast, random navigation in huge documents,
- Bookmarkable and shareable reports
- Native report viewer
- Very fast processing, low, nearly fixed memory consumption,
- 100% pixel exact rendering using embedded fonts,
- Streaming capable for immediate rendering of huge reports,
- Fast, random navigation in huge documents,
- Support for silent printing
- Viewer not visible,
- Selecting printer via server API,
- Configuration of printer via server API (e.g. selecting paper source),
- Server side printing
- Serial processing if supported by the operating system,
- Programmatic control via IPP properties
- File generation
- PDF,
- RTF (MS-Word),
- XLS/XLSX (MS-Excel),
- Postscript,
- SVG
- Single design for multiple languages. Primitives are provided to translate strings and format data in locale specific manner individually per document at runtime. Layouts can be defined that handle the resulting differences in text size well.
- Asian language and alternative writing modes support.
- Efficient handling of Asian fonts.
- Support for self written document templates,
- Type-safe unrolling of field lists and placeholders,
- Support for complexly structured data sources.
- Human readable and version controllable file formats,
- Type safe report design editing,
- Compile time impact analysis after changed to data sources,
- Sophisticated report design upgrade algorithm (Similar to diff/patch).
- 100 % tolerant to addition of fields and structures,
- Good tolerance to removal,
- Reports conflicts and allows for manual correction.
- Graphical data source generator,
- Creation of code for XML generation,
- Creation of schema,
- Type-safe unrolling of field lists and placeholders,
- Support for complexly structured data sources.
All of the industry’s leading databases are supported:
- DB2
- Informix
- MS SQL Server
- MySQL
- Oracle
- PostrgreSQL
- …
Getting Started
Code examples
In this example we use a plain Java object (POJO) “Sales” as a data source as shown in the source code below:
//The XmlRootElement annotation causes a 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;
Graphical reports are designed based on a XML schema that matches the data to be serialized.
The “schemagen” command line tool can be used to generate the schema:
schemagen Sales.java
The schema for the sample program reads as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sales" type="sales"></xs:element>
<xs:complexType name="sales">
<xs:sequence>
<xs:element name="shopName" type="xs:string" nillable="true"></xs:element>
<xs:element name="zipCode" type="xs:int"></xs:element>
<xs:element name="day" type="xs:dateTime" nillable="true"></xs:element>
<xs:element name="items" type="salesItem" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="salesItem">
<xs:sequence>
<xs:element name="articleName" type="xs:string" nillable="true"></xs:element>
<xs:element name="category" type="category" nillable="true"></xs:element>
<xs:element name="price" type="xs:double"></xs:element>
<xs:element name="runningTotal" type="xs:double"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="category">
<xs:restriction base="xs:string">
<xs:enumeration value="Furniture"></xs:enumeration>
<xs:enumeration value="Art"></xs:enumeration>
<xs:enumeration value="Supplies"></xs:enumeration>
<xs:enumeration value="Travelling"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Design the report using Report Designer. Choose your report template, associate the triggers and populate the report with data picked from the data view.
The image below shows “SalesList.4rp” created in the Report Designer:
Select report design
if (args.length == 0) {
designFile = "SalesList.4rp";
} else {
designFile = args[0];
}
Configure the output
Select PDF output
PDFRenderer renderer = new PDFRenderer(handler);
Serialize model
Use the JAXB marshaller to serialize the data.
report.runFromJAXBObject(data);
Find below the complete listing of the JAVA program:
/*
* FOURJS_START_COPYRIGHT(U,2003)
* Property of Four Js*
* (c) Copyright Four Js 2003, 2014. 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.pxml.standardpipe.runtimeapi.*;
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;
import java.io.Serializable;
//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 items=new Vector();
public Sales(String shopName, int zipCode, Date day)
{
this.shopName=shopName;
this.zipCode=zipCode;
this.day=day;
items.add(new SalesItem("Tablelamp",SalesItem.Category.Furniture,23.00,null));
items.add(new SalesItem("Tablelamp",SalesItem.Category.Furniture,267.00, items.lastElement()));
items.add(new SalesItem("Officechair",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("Sunglasses",SalesItem.Category.Travelling,15.95, items.lastElement()));
items.add(new SalesItem("Penknife",SalesItem.Category.Travelling,6.25, items.lastElement()));
items.add(new SalesItem("Ornateangel",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 = "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() { }
}
Developer Tutorials
PDFs