toltsch Posted September 11, 2006 Share Posted September 11, 2006 Hi Everyone. I'm using the 1.2.2 version of Jasper Reports. I'm seeing performance issues when using the JRXmlDataSource. I have an input file of about 700K and it takes about 2 secs per page to fill the report. The output of the report is sent to PDF (this is fast and appears to have no issues). I've seen post from 2003 on discussing that files of 2MB and over have had slow response times when using the JRXmlDataSource. I've also seen posts back from the JasperReports Dev team that for better response you have to code a the report using a custom DataSource. Is this the only option for better response time for large XML files? Can anyone point me at a good example of implementing a custom XML DataSource? Also, has anyone come up with a new Xml DataSource which others can use? Any help will be greatly appreciated. Thanks, Tim Link to comment Share on other sites More sharing options...
toltsch Posted September 12, 2006 Author Share Posted September 12, 2006 I rewrote the JasperReports JRXmlDataSource using Jaxen and I got a 600% increase in performance. Maybe the Jasper Reports team can rewrite their version using Jaxen? Here is the source code for other people struggling with this issue. I'm using Jasper Reports 1.2.2 with Jaxen 1.1 /* * Created on Sep 10, 2006 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */package com.cwi.direct.custom.datasource; import net.sf.jasperreports.engine.JRDataSource;import net.sf.jasperreports.engine.JRException;import net.sf.jasperreports.engine.JRField;import net.sf.jasperreports.engine.util.JRXmlUtils; import java.io.File;import java.util.List;import java.util.ArrayList; import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.DocumentBuilder; import org.apache.commons.beanutils.ConvertUtils; import org.jaxen.JaxenException;import org.jaxen.XPath;import org.jaxen.dom.*; import org.w3c.dom.Document; /** * @author Tim Oltsch (toltsch@commercialware.com) * @version $Id: CWXmlDataSource.java,v 1.0 2006/09/11 09:00:00 toltsch Exp $ */public class CWXmlDataSource implements JRDataSource{ // the xml document private org.w3c.dom.Document document; // the XPath select expression that gives the nodes to iterate private String selectExpression; // the node list private List nodeList; // the node list length private int nodeListLength; // the current node private Object currentNode; // current node index private int currentNodeIndex = - 1; /** * */ public CWXmlDataSource() { } public CWXmlDataSource(Document document, String selectExpression) throws JRException { this.document = document; this.selectExpression = selectExpression; moveFirst(); } public CWXmlDataSource(String uri, String selectExpression) throws JRException { this(CWXmlDataSource.loadDocumentFromFile(uri), selectExpression); } public void moveFirst() throws JRException { if (document == null) throw new JRException("document cannot be not null"); if (selectExpression == null) throw new JRException("selectExpression cannot be not null"); try { currentNode = null; currentNodeIndex = -1; nodeListLength = 0; nodeList = getXpathNodeList(document, selectExpression); nodeListLength = nodeList.size(); } catch (Exception e) { throw new JRException("XPath selection failed. Expression: " + selectExpression, e); } } /** * */ public boolean next() throws JRException { if(currentNodeIndex == nodeListLength - 1) return false; currentNode = nodeList.get(++ currentNodeIndex); return true; } /** * */ public Object getFieldValue(JRField jrField) throws JRException { if(currentNode == null) return null; String expression = jrField.getDescription(); if (expression == null || expression.length() == 0) return null; Object value = null; Class valueClass = jrField.getValueClass(); if(Object.class != valueClass) { String text = null; try { text = getXpathStringValue(currentNode,expression); } catch (Exception e) { throw new JRException("XPath selection failed. Expression: " + expression, e); } if(text != null) { if(String.class == valueClass) value = text; else value = ConvertUtils.convert(text.trim(), valueClass); } } return value; } protected static Document loadDocumentFromFile(String file) throws JRException { Document doc = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.parse(new File(file)); } catch(Exception e) { throw new JRException("Input file:"+file+ " was not found."); } return doc; } protected List getXpathNodeList(Object doc,String domxpath) throws Exception { try { XPath xpath = new DOMXPath(domxpath); Object ro = xpath.evaluate(doc); if (ro instanceof List) return (List)xpath.evaluate(doc); else { List results = new ArrayList(); results.add(ro); return results; } } catch(JaxenException je) { throw je; } } protected String getXpathStringValue(Object node,String domxpath) throws Exception { try { XPath xpath = new DOMXPath(domxpath); String value = xpath.stringValueOf(node); if (value.length() == 0) return null; else return value; } catch(JaxenException je) { throw je; } } public CWXmlDataSource subDataSource(String selectExpr) throws JRException { // create a new document from the current node Document doc = subDocument(); return new CWXmlDataSource(doc, selectExpr); } public Document subDocument() throws JRException { if(currentNode == null) { throw new JRException("No node available. Iterate or rewind the data source."); } // create a new document from the current node Document doc = JRXmlUtils.createDocument((org.w3c.dom.Node)currentNode); return doc; } public CWXmlDataSource dataSource(String selectExpr) throws JRException { return new CWXmlDataSource(document, selectExpr); }} Link to comment Share on other sites More sharing options...
lucianc Posted June 14, 2007 Share Posted June 14, 2007 The Xalan-specific XPath evaluation code has been extracted from JRXmlDataSource into a separate class which implements a generic XPath interface (JRXPathExecuter). A Jaxen-based implementation of this interface has also been written. A JR property (in jasperreports.properties) is used to specify the XPath executer factory class. By default, the Xalan-based XPath executer is still used (to ensure backward compatibility). To switch to the Jaxen-based XPath executer, set the following property:Code:net.sf.jasperreports.xpath.executer.factory=net.sf.jasperreports.engine.util.xml.JaxenXPathExecuterFactory All these changes can be found on JasperReports SVN trunk. If you have any feedback on this, let us know. Regards,Lucian Link to comment Share on other sites More sharing options...
toltsch Posted June 15, 2007 Author Share Posted June 15, 2007 What release of JasperReport will this be part of?:) Link to comment Share on other sites More sharing options...
lucianc Posted June 15, 2007 Share Posted June 15, 2007 The next one: 1.3.5, 1.4.0 or 2.0.0 (the numbering is not yet decided). In the mean time, you can get the SVN code (register a user for the developer area of JasperForge and use it to check-out http://scm.jasperforge.org/svn/repos/jasperreports/trunk/jasperreports), build it and see whether it works as expected. Finding any potential issues before the next release is preferable. Regards,Lucian Link to comment Share on other sites More sharing options...
shivamadagani Posted December 20, 2010 Share Posted December 20, 2010 After setting the below property in default.jasperreports.properties, we are not able to see any data in excel.net.sf.jasperreports.xpath.executer.factory=net.sf.jasperreports.engine.util.xml.JaxenXPathExecuterFactory But we are getting the data from database and we are passing that data to JRXmlDataSource .Do we need make changes anywhere else?Thanks shiva Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now