marciopd Posted July 17, 2010 Share Posted July 17, 2010 I'm using crosstabs in a possibly pretty large report.I designed the report so that the data didn't get all loaded together into memory. Well, tried :DThe thing is that it seems that there's a problem with jasperreports' crosstab report filling engine (JRFillCrosstab).Using a eclipse plugin (http://www.eclipse.org/mat/) to analyse the heap dump on out of memory error, i get that JRFillCrossTab stores the data in a arraylist that keeps growing and growing...Code to reproduce the issue is attached. Class ReportServiceImpl has the main method to be executed.You should modify the constant ReportServiceImpl.TMP_DIR_PATH to a temporary path in your file system.Any help please?Post Edited by marciopd at 07/17/2010 05:04 Link to comment Share on other sites More sharing options...
marciopd Posted July 19, 2010 Author Share Posted July 19, 2010 Someone? Link to comment Share on other sites More sharing options...
marciopd Posted July 20, 2010 Author Share Posted July 20, 2010 I reported this issue as a bug. Please vote:http://jasperforge.org/projects/jasperreports/tracker/view.php?id=4785 Link to comment Share on other sites More sharing options...
marciopd Posted July 20, 2010 Author Share Posted July 20, 2010 class that generates the report: ReportServiceImpl.javaCode:package report;import java.util.HashMap;import java.util.Map;import model.QueryLazyList;import net.sf.jasperreports.engine.JREmptyDataSource;import net.sf.jasperreports.engine.JRException;import net.sf.jasperreports.engine.JRParameter;import net.sf.jasperreports.engine.JRVirtualizer;import net.sf.jasperreports.engine.JasperExportManager;import net.sf.jasperreports.engine.JasperFillManager;import net.sf.jasperreports.engine.JasperPrint;import net.sf.jasperreports.engine.JasperReport;import net.sf.jasperreports.engine.fill.JRSwapFileVirtualizer;import net.sf.jasperreports.engine.util.JRSwapFile;import ar.com.fdvs.dj.core.DJConstants;import ar.com.fdvs.dj.core.DynamicJasperHelper;import ar.com.fdvs.dj.core.layout.ClassicLayoutManager;import ar.com.fdvs.dj.domain.DJCalculation;import ar.com.fdvs.dj.domain.DJCrosstab;import ar.com.fdvs.dj.domain.DynamicReport;import ar.com.fdvs.dj.domain.Style;import ar.com.fdvs.dj.domain.builders.CrosstabBuilder;import ar.com.fdvs.dj.domain.builders.DynamicReportBuilder;import ar.com.fdvs.dj.domain.constants.Border;public class ReportServiceImpl { /** * Tmp dir path. */ private static final String TMP_DIR_PATH = "/tmp"; /** * Generates test report. * @return * @throws JRException erro */ public byte[] generateCrossTabReport() throws JRException { DynamicReportBuilder drb = new DynamicReportBuilder();; DJCrosstab djcross = new CrosstabBuilder().setHeight(200).setWidth(500) .setDatasource("sr", DJConstants.DATA_SOURCE_ORIGIN_PARAMETER, DJConstants.DATA_SOURCE_TYPE_COLLECTION, true) .setUseFullWidth(true) .setAutomaticTitle(false) .setCellBorder(Border.THIN) .addColumn("State", "state", String.class.getName(), false) .addRow("City", "city", String.class.getName(),false) .addMeasure("amount", String.class.getName(), DJCalculation.NOTHING, "Amount", new Style()) .setCellDimension(17, 60) .setColumnHeaderHeight(30) .setRowHeaderWidth(80) .build(); drb.addHeaderCrosstab(djcross); DynamicReport dr = drb.build(); // put a collection in the parameters map to be used by the crosstab Map<String, Object> reportParams = new HashMap<String, Object>(); reportParams.put("sr", getTestDataLazyList()); // set a swap file virtualizer JRSwapFile swapFile = new JRSwapFile(TMP_DIR_PATH, 1024, 10); JRVirtualizer virtualizer = new JRSwapFileVirtualizer(1024, swapFile, true); reportParams.put(JRParameter.REPORT_VIRTUALIZER, virtualizer); // generates jasper report JasperReport jasperReport = DynamicJasperHelper.generateJasperReport(dr, new ClassicLayoutManager(), reportParams); // fills report and generates jasperprint JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, reportParams, new JREmptyDataSource()); // export to pdf bytes return JasperExportManager.exportReportToPdf(jasperPrint); } /** * returns test data. * @return test data */ private QueryLazyList getTestDataLazyList() { return new QueryLazyList(1000); } public static void main(String[] args) throws JRException { byte[] result = new ReportServiceImpl().generateCrossTabReport(); System.out.println(result.length); }} Link to comment Share on other sites More sharing options...
marciopd Posted July 20, 2010 Author Share Posted July 20, 2010 AbstractLazyList.javaCode:package model;import java.util.AbstractList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * Lazy list to a generic type. */public abstract class AbstractLazyList<T> extends AbstractList<T> { /** * Already loaded data. */ private final Map<Integer, T> loadedData; /** * How much itens shoud be retrieved at a query. */ private final int pageSize; /** * Constructor with page size. * @param pageSize page size */ public AbstractLazyList(int pageSize) { super(); this.pageSize = pageSize; this.loadedData = new HashMap<Integer, T>(pageSize); } @Override public T get(int position) { if (!loadedData.containsKey(position)) { loadedData.clear(); List<T> results = queryPage(position, pageSize); int index = position; for (T item : results) { loadedData.put(index, item); index++; } } return loadedData.get(position); } @Override public int size() { return getTotalQueryResultsSize(); } /** * Queries the new page. * @param position initial position * @param pageSize page size * @return results from position to page size */ public abstract List<T> queryPage(int position, int pageSize); /** * Returns the total results returned by the query. * @return total number of results */ public abstract int getTotalQueryResultsSize();} Link to comment Share on other sites More sharing options...
marciopd Posted July 20, 2010 Author Share Posted July 20, 2010 QueryLazyList.javaCode:/** * */package model; import java.util.ArrayList;import java.util.List; /** * Test implementation for a lazy list. */public class QueryLazyList extends AbstractLazyList<CrossTabDataVO> { /** * Total number of results. */ int totalNumberResults = Integer.MAX_VALUE; public QueryLazyList(int pageSize) { super(pageSize); } @Override public int getTotalQueryResultsSize() { return totalNumberResults; } @Override public List<CrossTabDataVO> queryPage(int position, int pageSize) { List<CrossTabDataVO> resultsPage = new ArrayList<CrossTabDataVO>(pageSize); for(int i = position; i < position + pageSize; i++) { CrossTabDataVO crossTabDataVO = new CrossTabDataVO(); crossTabDataVO.setState("State " + i); crossTabDataVO.setCity("City " + i); crossTabDataVO.setAmount(i + ",00"); resultsPage.add(crossTabDataVO); } return resultsPage; }} Link to comment Share on other sites More sharing options...
marciopd Posted July 20, 2010 Author Share Posted July 20, 2010 CrossTabDataVO.javaCode:package model; import java.io.Serializable; /** * Data to be used inside crosstab. */public class CrossTabDataVO implements Serializable { /** serial. */ private static final long serialVersionUID = 3785582945804552430L; private String state; private String city; private String amount; public String getState() { return state; } public void setState(String state) { this.state = state; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getAmount() { return amount; } public void setAmount(String amount) { this.amount = amount; }} Link to comment Share on other sites More sharing options...
lucianc Posted July 22, 2010 Share Posted July 22, 2010 Crosstabs were meant to present concise aggregated data. The aggregation is performed in-memory, and it is scalable wrt large data volumes as long as the data falls into a small number of buckets.Therefore crosstabs do not suit the case of creating large tables. What exactly do you want to display in your crosstab?Regards,Lucian Link to comment Share on other sites More sharing options...
marciopd Posted July 22, 2010 Author Share Posted July 22, 2010 In my case, i'm dealing with large tables.I used crosstabs because it deals well with dynamic columns and when theses columns gets larger than the page width. Can I design a report so that its columns are dynamic and jasper will deal automatically with column breaks? Thanks for helping Link to comment Share on other sites More sharing options...
lucianc Posted July 27, 2010 Share Posted July 27, 2010 marciopdWrote: In my case, i'm dealing with large tables. I used crosstabs because it deals well with dynamic columns and when theses columns gets larger than the page width. Can I design a report so that its columns are dynamic and jasper will deal automatically with column breaks? Thanks for helping Follow-up at http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=77084 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