Report configurations and the boot process

Before JfreeReport can be used for the first time, it must be configured and all subsystems need to be initialized. This needs to be done once in the lifetime of the JVM.

The preferred way to do this, is to call "Boot.start()". Calling this method will manually start the report system initialization. In case that the booting was not triggered manually, this method will also be called when the report configuration is used for the first time. The automatic booting cannot guarantee that subsystems may have performed operations in an fully configured state.

During the boot process, the system loads the report configuration and loads and initializes the known JFreeReport modules.

Loading report configuration

The report configuration can be separated into a local, a global and a defaults section. Entries from the local section are used by the report system to configure a specific report instance. The values for these keys are defined in the report and do not affect other reports.

The local report configuration can be reached via

Code:

JFreeReport.getReportConfiguration

The global configuration is used to configure the report system itself and provides default values for the local section. This configuration can be reached via

Code:

ReportConfiguration.getGlobalConfig()

Specifying global keys in the local configuration has no effect, it is not possible to reconfigure the subsystems this way, except the system explictly reads local configuration keys from the report object.

The report configuration is a multiple level datasource. Each level provides defaults for the higher levels. The defined levels are:

Default Provider:

  1. Local configuration (JFreeReport.getConfiguration())
  2. Global configuration (JFreeReportBoot.getInstance().getGlobalConfig())
  3. System-Properties
  4. PropertyFile(s): "/jfreereport.properties"
  5. Package configuration
  6. PropertyFile: "/org/jfree/report/ext/jfreereport.properties"
  7. PropertyFile: "/org/jfree/report/jfreereport.properties"
  8. Hardcoded defaults

The general contract of the report configuration says: values from the local configuration override values from the global configuration. And global configuration values override default values.

Levels with higher numbers are queried before levels with lower numbers. This means, that local keys are preferred to any global key and settings defined by the system properties are preferred to all other default values.

Modifying the "/org/jfree/report/jfreereport.properties" or
"/org/jfree/report/ext/jfreereport.properties" file is not recommended, both files provide default values for the base package and contain the list of default modules known to JFreeReport. Any local configuration should be done in the "/jfreereport.properties" file or in the system properties.

The specified property files are searched in the classpath using
Code:

Class.getResource()

. This means, that you will have to place these files into the root of the jar files or that you will have to include the directory, which contains the file, in the classpath.

The preferred way of supplying configuration values for the report system is to create a "/jfreereport.properties" file. This file must be loadable with the same classloader as the one that was used to load the JFreeReport classes, or a parent of that classloader.

As user libraries should never be placed into the JDK's lib/ext directory I'll assume that the default application classloader was used to load both the JFreeReport classes and the application or applet.

The user properties should be placed into the root of the classpath (or in java-speak: into the "default package")

If you place this file into a jar-file, you should add it to the root of that jar-file with

Code:

jar -cf your-file.jar jfreereport.properties

or if your properties file in not in the current working directory
Code:

jar -cf your-file.jar -C path_to_your_file/ jfreereport.properties

or place it into a directory which is part of the classpath.

if your classpath is
Code:

CLASSPATH="/opt/your-app"

then simply place your jfreereport.properties file into this directory.

Initializing the modules

Once the report configuration is completely initalized, the modules will be loaded and initialized.

The package manager will load all modules and resolves all dependencies. If a modules dependencies cannot be satisfied, the loading of that module will fail. If the dependencies contain circular references, the whole
loading of these modules will fail.

The list of initial module is fed to the package manager from the Boot class.

For every given module, the package manager will load the module class with Class.newInstance(). The module implementation must have a public default constructor, or loading will fail.

After that, the package manager tries to resolve all required and optional modules and loads these modules. If the loading fails for one of the required modules, the whole loading process for the module (and all module requirering
this module) will fail. Loader errors for optional modules are ignored.

Once all modules all loaded, the modules will be configured. This will load the report configuration into the package managers configuration set (level 4 from above). This step does activate the content or perform any not undoable work - this is done in the next step.

The last step is to actually initialize the module. If the module is part of a larger subsystem, it may register itself into that system or perform other initialization steps (like registering the available fonts).

If a module is part of a larger subsystem, it will be guaranteed, that all subsystem modules are initialized and configured before any dependent modules get configured.

Writing modules


Module specification basics

Modules define all metadate necessary to successfully load and use the classes of the module. The modules define a set of core attributes, so that the module management can be automated.

These core attributes are

  • Name: The name of the module
  • Producer: Who wrote that stuff (ie. how to flame for bugs )
  • Description: A short text describing the purpose of the module
  • Subsystem: The name of the subsystem to which this module belongs to.
  • Major-, Minor- and Patchlevel version: used by the dependency tracking.

Additionally a module may contain a set of required and optional modules. The package manager will use this information to resolve all dependencies and to load and initialize these base packages. Modules with a version less than the required version are considered non-existent and will not be used. Missing or invalid required modules will cause the loading process to fail, missing optional modules are ignored.

Module specification implementation

A module specification is implemented by creating a class which implements the org.jfree.report.modules.Module interface. Such an module requires an public default constructor, as the module class will be instantiated by
Class.newInstance();.

The module class must be immutable, once created it should not change its returned attributes, or the package manager may be very confused.

All classes for that module should be contained in the same package or in a sub-package of that module package. All used configuration keys should start with the package name to reduce name clashes. If the module initialization has to modify the report configuration, if should use the package managers report configuration for that purpose.

We provide a default implementation of the module interface with the class AbstractModule. This class loads the module specification from a file named "modules.properties" and the module configuration from the file "configuration.properties". Both files must be contained in the same package as the module implementation.

The module properties file is no plain properties file. It defines several sections and for every section some attributes. Comments start with '#'. Sections start at the beginning of the line, while section attributes have at least one leading whitespace before the attribute name.

Section names end with an colon, the colon is also used to separate attribute names and values.

The possible section types are defined:

module-info: defines the base attributes of the module. There can only be one module-info section in the file.

depends: defines a required module. There can be more than one module be defined. optional: defines an optional module. More than one module may be specified.

The module-info section defines the following attributes:

  • name: the name of the module
  • producer: who to flame
  • description: some textual explaination of the modules purpose
  • subsystem: the name of the subsystem this module belongs to
  • version.major, version.minor and version.patchlevel:
  • integer numbers defining the modules current version.

The depends and the optional sections define the following attributes:

  • module: the class name of the module specification implementation of the required module.
  • version.major, version.minor and version.patchlevel:
  • integer numbers defining the modules current version.