Jump to content

Error while de/serializing virtualized reports


pdiwakar

Recommended Posts

Hello,

   First of all thanks for contributing a great to the community. Ok, coming to my issue. I am using FileVirtualizer to fill a large report. After filling the report I serialized the Print object to file, when I retrieved (or de serialize) the Print object from the file I am getting the following exception. I use jasper reports version 3.1.2. For demonstration and to reproduce the error I modified one of the virtualizer sample provided with the Jasper Reports.

 

Thanks & Regards

Diwakar

 

Buildfile: build.xml

pdf:
     [java] Filling time : 1344
     [java] Writing the report object to file streem ...
     [java] Reading the report object from file streem ...
     [java] java.lang.IllegalStateException: Wrong object stored with UID "32960703_26_27_-1467324815"
     [java]     at net.sf.jasperreports.engine.fill.JRAbstractLRUVirtualizer.registerObject(JRAbstractLRUVirtualizer.java:431)
     [java]     at net.sf.jasperreports.engine.base.JRVirtualPrintPage.setThreadVirtualizer(JRVirtualPrintPage.java:447)
     [java]     at net.sf.jasperreports.engine.base.JRVirtualPrintPage.readObject(JRVirtualPrintPage.java:411)
     [java]     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
     [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     [java]     at java.lang.reflect.Method.invoke(Method.java:597)
     [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
     [java]     at java.util.ArrayList.readObject(ArrayList.java:593)
     [java]     at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
     [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     [java]     at java.lang.reflect.Method.invoke(Method.java:597)
     [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1869)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
     [java]     at VirtualizerApp.main(VirtualizerApp.java:133)
     [java] java.lang.IllegalStateException: Wrong object stored with UID "32960703_26_27_-1467324815"
     [java]     at net.sf.jasperreports.engine.fill.JRAbstractLRUVirtualizer.registerObject(JRAbstractLRUVirtualizer.java:431)
     [java]     at net.sf.jasperreports.engine.base.JRVirtualPrintPage.setThreadVirtualizer(JRVirtualPrintPage.java:447)
     [java]     at net.sf.jasperreports.engine.base.JRVirtualPrintPage.readObject(JRVirtualPrintPage.java:411)
     [java]     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
     [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     [java]     at java.lang.reflect.Method.invoke(Method.java:597)
     [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
     [java]     at java.util.ArrayList.readObject(ArrayList.java:593)
     [java]     at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
     [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     [java]     at java.lang.reflect.Method.invoke(Method.java:597)
     [java]     at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1846)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
     [java]     at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1869)
     [java]     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
     [java]     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
     [java]     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
     [java]     at VirtualizerApp.main(VirtualizerApp.java:133)

Code:
/* * ============================================================================ * GNU Lesser General Public License * ============================================================================ * * JasperReports - Free Java report-generating library. * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. *  * JasperSoft Corporation * 303 Second Street, Suite 450 North * San Francisco, CA 94107 * http://www.jaspersoft.com */import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.HashMap;import java.util.Map;import net.sf.jasperreports.engine.JRVirtualizationHelper;import net.sf.jasperreports.engine.JRDataSource;import net.sf.jasperreports.engine.JREmptyDataSource;import net.sf.jasperreports.engine.JRException;import net.sf.jasperreports.engine.JRExporterParameter;import net.sf.jasperreports.engine.JRParameter;import net.sf.jasperreports.engine.JasperExportManager;import net.sf.jasperreports.engine.JasperFillManager;import net.sf.jasperreports.engine.JasperPrint;import net.sf.jasperreports.engine.JasperPrintManager;import net.sf.jasperreports.engine.export.JRCsvExporter;import net.sf.jasperreports.engine.fill.JRFileVirtualizer;import net.sf.jasperreports.view.JasperViewer;/** * @author Teodor Danciu (teodord@users.sourceforge.net) * @version $Id: VirtualizerApp.java 1938 2007-10-31 13:19:04Z teodord $ */public class VirtualizerApp{	/**	 * 	 */	private static final String TASK_PRINT = "print";	private static final String TASK_PDF = "pdf";		private static final String TASK_XML = "xml";	private static final String TASK_XML_EMBED = "xmlEmbed";	private static final String TASK_HTML = "html";	private static final String TASK_CSV = "csv";		private static final String TASK_VIEW = "view";		private static final String TASK_EXPORT = "export";	/**	 * 	 */	public static void main(String[] args)	{		if (args.length == 0)		{			usage();			return;		}		String taskName = args[0];		String fileName = args[1];		try		{			// Virtualization works only with in memory JasperPrint objects.			// All the operations will first fill the report and then export			// the filled object.						// creating the data source			JRDataSource ds = new JREmptyDataSource(1000);						// creating the virtualizer			JRFileVirtualizer virtualizer = new JRFileVirtualizer(2, "tmp");						// filling the report			JasperPrint jasperPrint = fillReport(fileName, ds, virtualizer);			if (TASK_PRINT.equals(taskName))			{				JasperPrintManager.printReport(jasperPrint, true);			}			else if (TASK_PDF.equals(taskName))			{                try {                    File file = new File("C:\\Temp\\Test.jasper");                    FileOutputStream fos = new FileOutputStream(file);                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fos);                    System.out.println("Writing the report object to file streem ...");                    JRVirtualizationHelper.setThreadVirtualizer(virtualizer);                    objectOutputStream.writeObject(jasperPrint);                    objectOutputStream.flush();                    objectOutputStream.close();                    fos.close();                        FileInputStream fis = new FileInputStream(file);                    System.out.println("Reading the report object from file streem ...");                    ObjectInputStream objectInputStream = new ObjectInputStream(fis);                    JasperPrint constructedReport = (JasperPrint) objectInputStream.readObject();                    objectInputStream.close();                    fis.close();                } catch (Exception e) {                    e.printStackTrace();                    throw e;                }				exportPDF(jasperPrint);			}			else if (TASK_XML.equals(taskName))			{				exportXML(jasperPrint, false);			}			else if (TASK_XML_EMBED.equals(taskName))			{				exportXML(jasperPrint, true);			}			else if (TASK_HTML.equals(taskName))			{				exportHTML(jasperPrint);			}			else if (TASK_CSV.equals(taskName))			{				exportCSV(jasperPrint);			}					else if (TASK_EXPORT.equals(taskName))			{				exportPDF(jasperPrint);				exportXML(jasperPrint, false);				exportHTML(jasperPrint);				exportCSV(jasperPrint);								// manually cleaning up				virtualizer.cleanup();			}			else if (TASK_VIEW.equals(taskName))			{				JasperViewer.viewReport(jasperPrint, true);			}			else			{				usage();			}		}		catch (JRException e)		{			e.printStackTrace();		}		catch (Exception e)		{			e.printStackTrace();		}	}	private static void exportCSV(JasperPrint jasperPrint) throws JRException	{		long start = System.currentTimeMillis();		JRCsvExporter exporter = new JRCsvExporter();		exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);		exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, jasperPrint.getName() + ".csv");		exporter.exportReport();		System.err.println("CSV creation time : " + (System.currentTimeMillis() - start));	}	private static void exportHTML(JasperPrint jasperPrint) throws JRException	{		long start = System.currentTimeMillis();		JasperExportManager.exportReportToHtmlFile(jasperPrint, jasperPrint.getName() + ".html");		System.err.println("HTML creation time : " + (System.currentTimeMillis() - start));	}	private static void exportXML(JasperPrint jasperPrint, boolean embedded) throws JRException	{		long start = System.currentTimeMillis();		JasperExportManager.exportReportToXmlFile(jasperPrint, jasperPrint.getName() + ".jrpxml", embedded);		System.err.println("XML creation time : " + (System.currentTimeMillis() - start));	}	private static void exportPDF(JasperPrint jasperPrint) throws JRException	{		long start = System.currentTimeMillis();		JasperExportManager.exportReportToPdfFile(jasperPrint, jasperPrint.getName() + ".pdf");		System.err.println("PDF creation time : " + (System.currentTimeMillis() - start));	}		private static JasperPrint fillReport(String fileName, JRDataSource dataSource, JRFileVirtualizer virtualizer) throws JRException	{		long start = System.currentTimeMillis();		// Preparing parameters		Map parameters = new HashMap();		parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);		JasperPrint jasperPrint = JasperFillManager.fillReport(fileName, parameters, dataSource);				virtualizer.setReadOnly(true);		System.err.println("Filling time : " + (System.currentTimeMillis() - start));		return jasperPrint;	}	/**	 * 	 */	private static void usage()	{		System.out.println("VirtualizerApp usage:");		System.out.println("\tjava VirtualizerApp task file");		System.out.println("\tTasks : print | pdf | xml | xmlEmbed | html | csv | export | view");	}}
Link to comment
Share on other sites

  • Replies 8
  • Created
  • Last Reply

Top Posters In This Topic

Currently you cannot use the same virtualizer for the original JasperPrint object and for the deserialized JasperPrint.  Moreover, you can't use a file virtualizer that writes on the same folder as the file virtualizer of the original report (unless this virtualizer has been disposed).  Please log this as a bug.

Possible workarounds:

  • Use a different file virtualizer that writes on a different folder for the deserialized report.
  • Switch to swap file virtualizers, and use a different virtualizer for the deserialized report.

Note that JRVirtualizationHelper.setThreadVirtualizer() is used during deserialization, so it makes more sense to call it before objectInputStream.readObject().

Regards,

Lucian

Link to comment
Share on other sites

  • 2 weeks later...

We are getting similar errors during deserialization, with JRVirtualPrintPage.readObject in the stacktrace. 

First, we create a new instance of JRFileVirtualizer for each report being filled with JasperFillManager.fillReportToFile   But all of these File Virtualizer objects use the same directory (and the maxSize is set to 1 which is probably too small).

Later, when the JasperPrint is de-serialized from the file, our development team has passed no virtualizer to the ThreadLocal context. So, reports which have been saved without error, run out of memory when the system reads them again from disk.  This makse sense.  If there is sufficient memory, we still get errors like "stream corrupted" during deserialization.

I understand the best solution for de-serialization would be to create a separate directory, and install a virtualizer on the thread before we call loadObject().  From what you told us about the bug, it could not run the virtualizer in the same common directory, because the IDs of objects may clash with their previous values used at serialization.

However, it would be more elegant if we could always use the same virtualization directory. Which version is going to include the fix made to JRVirtualPrintPage ?


regards,

Andrew
 



Post Edited by andrewsc at 06/06/2009 17:51



Post Edited by andrewsc at 06/06/2009 17:59
Link to comment
Share on other sites

Hi Diwakar,

I'm scrutinizing the way in which the JRSwapFile constructor creates a unique file name. It contains the identityHashCode and the current time. Strictly speaking, the VM specification does not guarantee this to be unique. The granularity of the time is not always as fine as a millisecond. In theory, different objects may hash to the same integer. In practice, I don't know how much this should be a concern, but if it happens once a year, then it is a bad year -:)

I'm tempted to subclass JRSwapFile, and use a unique number allocator from a static Integer. If there is a power failure, files may be left behind.  In order to avoid inadvertently reusing a file, we could keep the existing truncate logic. Or, the unique number allocator, at its first invocation, could delete all files in the directory. Something like:

private static long unique_id = 0;

private static synchronized long allocate_unique( String directory )

{

       if ( 0 == unique_id )

      {

           // This is the first invocation, after startup.

          // Delete all files in "directory", in case they were left behind.

      }

     unique_id ++;

     return unique_id ;

}

Or, we could leave the task of allocating a unique ID to the application. Most applications already have some kind of unique identifier for each JasperPrint instance, and we could bring a unique ID from the database. 

Regards,

Andrew

 



Post Edited by andrewsc at 08/06/2009 20:57
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...