jfreechart icon indicating copy to clipboard operation
jfreechart copied to clipboard

Using Thai display locale crashes XYPlot constructor when used with PeriodAxis

Open stevemcleod opened this issue 7 years ago • 1 comments

I discovered this unusual bug from user crash reports. Here's the minimum self-contained code sample that will reliably reproduce it.

I'm using Java 1.8.0_131 on Mac with JFreeChart 1.0.19. Problem occurs on Windows, too.


package com.barbarysoftware.pokercopilot;

import org.jfree.chart.axis.PeriodAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import java.util.Locale;

public class ScratchSpace {

    public static void main(String[] args) {
        // crash happens when display locale is default (eg en-AU), but format locale is th-TH
        Locale.setDefault(Locale.Category.FORMAT, new Locale.Builder().setLanguageTag("th-TH").build());

        final TimeSeries timeSeries = new TimeSeries("Series 1");
        timeSeries.add(new Day(), 0);
        PeriodAxis domainAxis = new PeriodAxis("domain label");

        // exception occurs here
        XYPlot plot = new XYPlot(new TimeSeriesCollection(timeSeries), domainAxis, null, null);

        System.out.println("plot = " + plot);
    }
}


Exception in thread "main" java.lang.NullPointerException
	at org.jfree.chart.axis.PeriodAxis.setRange(PeriodAxis.java:566)
	at org.jfree.chart.axis.PeriodAxis.autoAdjustRange(PeriodAxis.java:1081)
	at org.jfree.chart.axis.PeriodAxis.configure(PeriodAxis.java:578)
	at org.jfree.chart.axis.Axis.setPlot(Axis.java:1043)
	at org.jfree.chart.plot.XYPlot.<init>(XYPlot.java:668)

I've tracked it down to TimeSeriesCollection. In fact, there is already a FIXME comment in the code that predicted this problem:

    public TimeSeriesCollection(TimeSeries series, TimeZone zone) {
        // FIXME:  need a locale as well as a timezone
        if (zone == null) {
            zone = TimeZone.getDefault();
        }
        this.workingCalendar = Calendar.getInstance(zone);

whereas the PeriodAxis constructor correctly uses the locale to get a calendar instance:

this.calendar = Calendar.getInstance(timeZone, locale);

stevemcleod avatar Sep 06 '17 09:09 stevemcleod

A workaround is to check at app startup if your user's display locale is not the same as the format locale, AND if the format locale is th-TH. If so, then set the format locale to match the display locale.

stevemcleod avatar Sep 06 '17 10:09 stevemcleod