Hot questions for Using JasperReports in jfreechart

Question:

I am working on a jasper report in which I am using java customizers to make some changes in the chart look. In my report I am creating a bar chart which looks like below:

Here I am using following code to show labels on top of bars:

CategoryPlot plot = (CategoryPlot)chart.getPlot();
BarRenderer barRenderer = (BarRenderer)plot.getRenderer();
CategoryPlot categoryPlot = (CategoryPlot) chart.getPlot();
categoryPlot.getRenderer().setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER));

I want to increase the space between top of bars and labels. I am not getting a way to do this. Can someone suggest me how to do this?


Answer:

Try adding an offset to the label anchor:

categoryPlot.getRenderer().setItemLabelAnchorOffset(10.0d);

Question:

I am using Studio to create a JasperReports's report. I need to increase the width of the line chart (default is too thin). As far I know JasperReports use Jfeechart for the chart, and I googled this piece of code to do the customization.

public class TSChartCustomizer extends JRAbstractChartCustomizer {
    public void customize(JFreeChart chart, JRChart jasperChart) {
       XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer();
        BasicStroke stroke = new BasicStroke(3f);
        renderer.setSeriesStroke(1, stroke);
    }
}

I have built and added above class to a jar and added it in the jasper project. And in the chart properties can select the class in customizer class. But when I run the report I got this error:

java.lang.ClassCastException: org.jfree.chart.plot.CategoryPlot cannot be cast to org.jfree.chart.plot.XYPlot

I think the problem is probably with the code, but I don't know Jfreechart...

P.S below is the report code, a very simple one for demonstration:

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="test6" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f147421f-bbe6-42bd-b26e-7f4f7cee333a">
    <queryString>
        <![CDATA[select 'p1' as prod, 'm1' as mon, 10 as num
union all select 'p1' as prod, 'm2' as mon, 20 as num
union all select 'p1' as prod, 'm3' as mon, 30 as num]]>
    </queryString>
    <field name="prod" class="java.lang.String"/>
    <field name="mon" class="java.lang.String"/>
    <field name="num" class="java.lang.Integer"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <summary>
        <band height="325" splitType="Stretch">
            <lineChart>
                <chart evaluationTime="Report">
                    <reportElement x="178" y="125" width="200" height="200" uuid="124ec6e6-b32d-477d-84a4-36c8d4df3ac2"/>
                    <chartTitle/>
                    <chartSubtitle/>
                    <chartLegend/>
                </chart>
                <categoryDataset>
                    <categorySeries>
                        <seriesExpression><![CDATA[$F{prod}]]></seriesExpression>
                        <categoryExpression><![CDATA[$F{mon}]]></categoryExpression>
                        <valueExpression><![CDATA[$F{num}]]></valueExpression>
                    </categorySeries>
                </categoryDataset>
                <linePlot>
                    <plot/>
                    <categoryAxisFormat>
                        <axisFormat/>
                    </categoryAxisFormat>
                    <valueAxisFormat>
                        <axisFormat/>
                    </valueAxisFormat>
                </linePlot>
            </lineChart>
        </band>
    </summary>
</jasperReport>

Answer:

The chart customizer does not work for category charts, it was meant to be used for XY or timeseries charts.

For category charts you will need something like the following (also note that the series index is 0-based):

public class TSChartCustomizer extends JRAbstractChartCustomizer {
    public void customize(JFreeChart chart, JRChart jasperChart) {
        AbstractCategoryItemRenderer renderer = (AbstractCategoryItemRenderer) chart.getCategoryPlot().getRenderer();
        BasicStroke stroke = new BasicStroke(3f);
        renderer.setSeriesStroke(0, stroke);
    }
}

Question:

(I am basing my question on this HARDCODED example from April 2016 and am seeking an updated, dynamic answer since the "bug" has been fixed - not having the locale available in the Customizer)

/* -Hardcoded example */
getNumberInstance(Locale.US)); //"Locale.US" is hardcoded rather than using the locale set in the report

Goal: Pass Locale set in jasper reports to chart and read with chart Customizer.

  • How do I properly read the Report Locale now that the bug of it not being available has been fixed (see here)?

Problem: In the Customizer Class (written in Java) this command does not contain anything: JRParameter.REPORT_LOCALE.

public class AssetsChartMod implements JRChartCustomizer {

    public void customize(JFreeChart chart, JRChart jasperChart) {

            /* ----> */
            System.out.println( JRParameter.REPORT_LOCALE ); // PRINTS NOTHING

Answer:

Unfortunately, we can't get report's parameters from JRChart object. This would be the easiest way to get Locale from parameters map.

But we can perform this trick:

  1. Add property locale for chart at jrxml file.

The snippet of jrxml file with chart declaration:

<pie3DChart>
    <chart customizerClass="ru.alex.PieChartCustomizer" theme="aegean">
        <reportElement positionType="Float" x="0" y="0" width="100" height="100">
            <propertyExpression name="locale"><![CDATA[((java.util.Locale) ($P{REPORT_PARAMETERS_MAP}.get("REPORT_LOCALE"))).toString()]]></propertyExpression>
        </reportElement>

The property can be only of String type, this is why I performed cast at expression.

  1. At JRChartCustomizer class I'm getting the property with help of JRChart.getPropertiesMap() method.

At my case the package name was ru.alex.

public class PieChartCustomizer implements JRChartCustomizer {

    private static final String LOCALE_PROPERTY = "locale"; // the same name as at jrxml file
    private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;

    @Override
    public void customize(JFreeChart chart, JRChart jasperChart) {
        PiePlot pieChart = (PiePlot) chart.getPlot();
        JRPropertiesMap map = jasperChart.getPropertiesMap();

        Locale locale = DEFAULT_LOCALE; // this is default Locale if property was not set
        if (map != null && !map.isEmpty()) {
            if (!isNullOrEmpty(map.getProperty(LOCALE_PROPERTY))) {
                locale = Locale.forLanguageTag(map.getProperty(LOCALE_PROPERTY).replace("_", "-")); // here we have Locale passed via property 'locale'. Replacement applied: en_GB -> en-GB, for example
            }
        }

        // some actions 
    }

    private static boolean isNullOrEmpty(String string) {
        return string == null || string.isEmpty();
    }
}

Voila, we got report's locale at customizer.

Question:

I have a JFreeChart which I'm running through a customizer (JRAbstractChartCustomizer). I have figured out how to color individual bars and item labels according to the data (eg green for >90%, yellow for 75-90%, red for <75%) by extending BarRenderer and overriding getItemLabelPaint(int row, int column) and getItemPaint(int row, int column). Each bar has a corresponding tick with a String label, since the domain is by name rather than by numeric value. I need a way to individually color the tick labels based on the value similar to how I color the bars and the item labels.

What method do I override in BarRenderer, or what other thing do I do in my JRChartCustomizer to override the color on an individual basis.

What I'm doing for the item labels: (I want to do basically the same thing, but for tick labels)

class CustomBarRenderer extends BarRenderer {

    private final Color COLOR_GREEN = new Color(0, 227, 0);
    private final Color COLOR_YELLOW = new Color(247, 210, 0);
    private final Color COLOR_RED = new Color(237, 26, 0);

    @Override
    public Paint getItemLabelPaint(int row, int col) {
        CategoryDataset cDataset = getPlot().getDataset();

        if (cDataset != null) {
            Number itemValue = cDataset.getValue(row, col);

            String rowKey = cDataset.getRowKey(row).toString();
            String colKey = cDataset.getColumnKey(col).toString();

            if (itemValue != null) {
                int intVal = itemValue.intValue();

                if (intVal > yellowHigh) {
                    return COLOR_GREEN;
                } else if (intVal >= yellowLow) {
                    return COLOR_YELLOW;
                } else {
                    return COLOR_RED;
                }
            }
        }

        // if all else fails...
        return super.getItemLabelPaint(row, col);
    }

    @Override
    public Paint getItemPaint(int row, int col) {
        ... similar to above ...
    }
}

Answer:

Your chart's domain axis tick label is rendered by a CategoryAxis. You can use setTickLabelPaint() to color labels by category. The example below modifies BarChartDemo1 to make the "Test" category label a shade of green.

CategoryPlot plot = (CategoryPlot) chart.getPlot();
CategoryAxis domain = plot.getDomainAxis();
domain.setTickLabelPaint("Test", Color.green.darker());

For finer control, you can override getTickLabelPaint() in a custom CategoryAxis that has access to the dataset referenced by your CustomBarRenderer. The existing implementation uses a Map<Category, Paint> as a lookup table. The Map is private, but the approach may give you an idea of how to proceed.

Question:

I am using JasperReports to generate a report with charts. One of them is a bar chart and I'd like to set the increment of the axis values in 20 units.

You can see my previous approach at this link: BarChart bar value labels are hidden by the margin

This is my customizer class:

    public class BarChartCustomizer extends JRAbstractChartCustomizer {

    @Override
    public void customize(JFreeChart jFreeChart, JRChart jrChart) {

        CategoryPlot plot = (CategoryPlot) jFreeChart.getPlot();
        plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        NumberFormat numberFormat = NumberFormat.getNumberInstance();
        numberFormat.setMaximumFractionDigits(2);
        numberFormat.setMinimumFractionDigits(2);
        rangeAxis.setNumberFormatOverride(numberFormat);
        BarRenderer barRenderer = (BarRenderer) plot.getRenderer();
        barRenderer.setItemMargin(0.0);
        rangeAxis.setUpperMargin(0.20);
        rangeAxis.setAutoRange(true);
        CategoryAxis categoryAxis = plot.getDomainAxis();
        categoryAxis.setAxisLineStroke(new BasicStroke(2f)); 
        rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setAxisLineStroke(new BasicStroke(2f));
    }
}

I tried with rangeAxis.setMinorTickCount(20); with no success.

As usual, the final solution will be included in the sample code located in my GitHub repository: https://github.com/MichaelKnight/jaspertest.git


Answer:

Try this

rangeAxis.setTickUnit(new NumberTickUnit(20));

Also see the net.sf.jasperreports.chart.range.axis.tick.interval property (documented at http://jasperreports.sourceforge.net/config.reference.html#net.sf.jasperreports.chart.range.axis.tick.interval), which does exactly that.

Question:

I have a horizontal bar chart. I want to make it such that I only show the labels for the domains, but not the range because I already have labels at the end of each bar showing their exact value. This is what the bar chart currently looks like :

I want to get rid of the tick labels on the range (0, 25, 50, 75, 100) while keeping the tick labels on the domain. How can I do this without getting rid of both? I've tried :

public class BarCustomizer implements JRChartCustomizer {
    @Override
    public void customize(JFreeChart chart, JRChart jasperChart) {
         BarRenderer  renderer = (BarRenderer) chart.getCategoryPlot().getRenderer(); 
         renderer.setMaximumBarWidth(0.99);
         renderer.setItemMargin(-2);

         ValueAxis rangeAxis = chart.getCategoryPlot().getRangeAxis();
         rangeAxis.setVerticalTickLabels(false);

         rangeAxis.setTickLabelsVisible(false);
    }   
}

But this just makes labels on both axis go invisible.


Answer:

I solved the issue by setting the setTickLabelsVisible for both axis (even though by default the domain axis should show the tick labels). It seems that setting only one of the axis would result in setting true or false for both axis (weird bug). So setting the domain axis to setTickLabelsVisible(true) while setting the range axis setTickLabelsVisible(false) solved my issue.

Question:

I have requirement to show a XyLineChart with adding data dynamically. I have used the chart Customizer to read data from db with some additional logic and adding that to chart. But I am not able to create tool tip on mouse over for each data points on chart. following is my code for Customizer.

What is the correct way to create Tool tip on Mouse over?

public class MyChartCustomizer extends JRAbstractChartCustomizer{

    @Override
    public void customize(JFreeChart chart, JRChart jrChart) {
        XyPlot plot= chart.getXyPlot;
        XYSeriesCollection ds =  (XYSeriesCollection) plot.getDataset();
        XYSeries x1 = new XYSeries("C 1", true, true);

        x1.add(10,20);
        XYBarRenderer ren = (XYBarRenderer) plot.getRenderer();
        plot.setRenderer(ren);
        ren.setSeriesToolTipGenerator(0, new XYToolTipGenerator() {
            @Override
            public String generateToolTip(XYDataset arg0, int arg1, int arg2) {
                return "C 1";
            }
            });
            ren.setToolTipGenerator(new XYToolTipGenerator() {
                @Override
                public String generateToolTip(XYDataset arg0, int arg1, int arg2)                   {
                    return "C 1";
                }
            });
            chart.fireChartChanged();
        }
    }
}

Answer:

Thank you, Petter and Trashgod helping me out to find the solution for this issue. The actual issue is, if we add the new data using customizer then the new data point get display on the graph but respected tool tip does not get generated and the map used for tooltip will not be updated on html code. Since I have to use jasper server as per requirement I implemented following work around other way will be simply generate chart image with map using jfreechart API and display on the jsp page(no need for report design....).. Following is the way I Implemented this.

I used the following code to generate the same chart which jasperserver/jasper studio create the chart. this gives me same chart which internally get created and I create the map for tooltips and passing it as parameter to browser and using javascript function inserting the new map html code with the chart image.

            XYSeriesCollection xyDataSet = new XYSeriesCollection();

        JFreeChart chart = ChartFactory.createXYLineChart(
                cur_chart.getTitle(),
                cur_chart.getxLabel(), cur_chart.getyLabel(),
                xyDataSet,
                PlotOrientation.VERTICAL,
                true,
                true,
                false);

        String chartId = null;
        for ( Object  tt :  chart.getSubtitles()){
            if (tt instanceof TextTitle){
                chartId= ((TextTitle) tt).getText();
            }
        }

        XYPlot plot = chart.getXYPlot();


    //following code to set font size and color is required so that same chart with matching tooltip pixels can we generated. 
        LegendItemCollection legends =  plot.getLegendItems();


        List<JRSeriesColor> colors = new ArrayList<JRSeriesColor>();

        System.out.println("Customizer: "+ chartId);

        NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
        xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        Color trans = new Color(0xFF, 0xFF, 0xFF, 0);
        chart.setBackgroundPaint(trans);
        plot .setBackgroundPaint(trans);
        chart.getLegend().setBackgroundPaint(trans);

        chart.setTitle(cur_chart.getTitle());

        Font font3 = new Font("Dialog", Font.PLAIN, 10); 
        plot.getDomainAxis().setLabelFont(font3);
        plot.getRangeAxis().setLabelFont(font3);
        plot.getDomainAxis().setLabelPaint(Color.BLACK);
        plot.getRangeAxis().setLabelPaint(Color.BLACK);

    //some more code to add real time data to XyDataset, 


    ToolTipTagFragmentGenerator tooltipConstructor = new ToolTipTagFragmentGenerator() {
            public String generateToolTipFragment(String arg0) {
                String toolTip = " title = \"" + arg0.replace("\"", "") + "\"";
                return (toolTip);
            }
        };

        URLTagFragmentGenerator urlConstructor = new URLTagFragmentGenerator() {
            public String generateURLFragment(String arg0) {
                String address = " href=\"ControllerAddress\\methodName?"
                    + arg0.replace("\"", "") + "\"";
                return (address);
            }
        };



        ChartRenderingInfo info = new ChartRenderingInfo(
                new StandardEntityCollection());
       // BufferedImage bi  chart.createBufferedImage(272, 178, info); 
        TextTitle tt =  new TextTitle("chart1");
        tt.setFont(font3);
        chart.addSubtitle(tt);
        ChartUtilities.saveChartAsPNG(new File("/tmp/test.png"), chart, 500, 250, info);
    String map = ChartUtilities.getImageMap(cur_chart.getName(), info, tooltipConstructor, urlConstructor);

Question:

I have a requirement to display negative values in pie chart in jasper reports.I am able to achieve this using customizer class.In createCustomizedDataset method I am checking if value is negative then later on while generating label I am appending "-" sign

PiePlot piePlot = (PiePlot) chart.getPlot();
    PieDataset dataset = piePlot.getDataset(); // line 1
    PieDataset dataset1 = createCustomizedDataset(dataset,piePlot);
    piePlot.setDataset(dataset1);

    StandardPieSectionLabelGenerator labelGen = new StandardPieSectionLabelGenerator(
            "{1}") {

        @SuppressWarnings("rawtypes")
        @Override
        public String generateSectionLabel(PieDataset dataset, Comparable key) {
            String label = super.generateSectionLabel(dataset, key);

            if(dataSetKeys.contains(key.toString())){
                return "-"+label;
            }else{
                return label;
            }
        }

    };

Output is below :

ISSUE IS : if there are multiple entries for negative values I am getting a different category with negative values combined.At line 1 the dataset key for these negative values is 'Other'.Here I have two categories one with value as "-2.02" and one with "-0.01". So instead of showing two slices it is showing one slice of 2.02+0.01=2.03.Problem is the dataset in customize method is like that.


Answer:

I got it resolved as in chat edit wizard minimum expression was set to 0.Remove that to solve the issue.

Question:

I have two projects set up as client and server using Spring in Java 7 update 51. The underlying system is Scientific Linux 6.5 (kernel version 2.6.32-431.23.3.el6.x86_64). The used libraries are jasperreports-5.6.0, iText-2.1.7, jcommon-1.0.15 and jfreechart-1.0.12 .

The client reads a JasperReports design document (.jrxml) into a byte array and sends it to the server. The server then creates a JasperPrint object:

InputStream inputStream = new ByteArrayInputStream(reportDesignByteArray);
jasperReport = JasperCompileManager.compileReport(inputStream);
jasperPrint = JasperFillManager.fillReport(jasperReport, parameter, dataSource);

This object is returned to the client via RMI. At this point I am getting the following error (JasperPrint is derived from Serializable though):

java.io.EOFException
  at java.io.ObjectInputStream$BlockDataInputStream.readBoolean(ObjectInputStream.java:2758)
  at java.io.ObjectInputStream.readBoolean(ObjectInputStream.java:905)
  at org.jfree.io.SerialUtilities.readStroke(SerialUtilities.java:204)
  at org.jfree.chart.plot.CategoryPlot.readObject(CategoryPlot.java:5037)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:500)
  at org.jfree.chart.JFreeChart.readObject(JFreeChart.java:1670)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:500)
  at net.sf.jasperreports.engine.fill.JRTemplatePrintImage.readObject(JRTemplatePrintImage.java:445)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
  at java.util.ArrayList.readObject(ArrayList.java:771)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
  at java.util.ArrayList.readObject(ArrayList.java:771)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
  at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:500)
  at net.sf.jasperreports.engine.JasperPrint.readObject(JasperPrint.java:722)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
  at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
  at cern.lhc.hwc.acctesting.gui.dialog.CreateNewReportDialog.createReport(CreateNewReportDialog.java:185)
  at cern.lhc.hwc.acctesting.gui.dialog.CreateNewReportDialog$2$1.construct(CreateNewReportDialog.java:126)
  at cern.accsoft.gui.frame.Task.doConstruct(Task.java:320)
  at cern.accsoft.gui.frame.Task.access$300(Task.java:58)
  at cern.accsoft.gui.frame.Task$SwingWorkerExt.doInBackground(Task.java:420)
  at javax.swing.SwingWorker$1.call(SwingWorker.java:296)
  at java.util.concurrent.FutureTask.run(FutureTask.java:262)
  at javax.swing.SwingWorker.run(SwingWorker.java:335)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:744)

I tried to perform the serialization myself with the following procedure:

Server

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(jasperPrint);
byte[] serializedPrint = byteArrayOutputStream.toByteArray();

Client

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serializedPrint);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
jasperPrint = (JasperPrint) objectInputStream.readObject();

I still get the same error. However, it works in a local unit test, so the error only appears when using RMI. I also checked the serialized object regarding size and SHA-1 hash on the server and the client side. They are identical.

Do you have any suggestions how to fix this?


Answer:

The problem was solved by updating JFreeChart to version 1.0.13 on both server and client side.