Eclipse BIRT Charting API examples

I’ve been playing with the Eclipse BIRT Charting APIs and have bought an excellent book called Integrating and Extending BIRT (3rd Edition) by Jason Weathersby, Tom Bondur, Iana Chatalbasheva. On trying out the Charting API examples, however, I came across a problem that took me a while to figure out.

The code example in the book looks like this:


    public static void main(String[] args) {
        Chart myChart = ChartWithAxesImpl.create();
        Serializer si = SerializerImpl.instance();
        try {
            si.write(myChart, new FileOutputStream(
                new File("<path_to_myChart.chart>")));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

The book goes to some length to explain that a system environment variable of either

STANDALONE

or

BIRT_HOME="<path_to_Report_Engine>"

must be set.  However, the Birt code doesn’t actually try to read this variable!  Furthermore, if the Serializer can’t actually determine that it should be standalone, we get the following stack trace:


org.eclipse.birt.core.exception.BirtException: error.CannotStartupOSGIPlatform
	at org.eclipse.birt.core.framework.Platform.startup(Platform.java:81)
	at org.eclipse.birt.chart.util.PluginSettings.instance(PluginSettings.java:367)
	at org.eclipse.birt.chart.util.PluginSettings.instance(PluginSettings.java:335)
	at org.eclipse.birt.chart.model.impl.SerializerImpl.(SerializerImpl.java:70)
	at uk.co.lhsd.birt.chart.examples.SimpleChart.main(SimpleChart.java:39)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.NullPointerException
	at org.eclipse.birt.core.framework.jar.ServicePlatform.startup(ServicePlatform.java:205)
	at org.eclipse.birt.core.framework.jar.ServiceLauncher.startup(ServiceLauncher.java:80)
	at org.eclipse.birt.core.framework.Platform.startup(Platform.java:75)
	... 9 more

So, how do we tell the Serializer that we’re running standalone, when we can’t use the environment variable? Well, the standard response would be to configure it in a PlatformConfig object. But guess what? The Serializer doesn’t read the PlatformConfig object.  It references a PluginSettings object which in this case ignores the config completely.

The trick is to create a different PluginSettings instance and pass in a PlatformConfig to it.  When the Serializer is invoked, it uses the already-created PluginSettings instead of creating a new one.  The code then looks like this:


    public static void main(String[] args) {
        PlatformConfig config = new PlatformConfig();
        config.setProperty(PluginSettings.PROP_STANDALONE, "true");
        PluginSettings.instance(config);
        // Result of above method call is ignored.
        // However, PluginSettings.instance() called from Serializer
        // returns the previously created instance.
        Chart myChart = ChartWithAxesImpl.create();
        Serializer si = SerializerImpl.instance();
        try {
            si.write(myChart, new FileOutputStream(
                new File("<path_to_myChart.chart>")));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Hey, presto - the Serializer starts and completes in standalone mode with no errors.