Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » BIRT » RunTask+RenderTask vs. RunAndRenderTask(Using the same render options, the two strategies lead to different results, I don't understand why)
RunTask+RenderTask vs. RunAndRenderTask [message #1114922] Mon, 23 September 2013 12:11 Go to next message
Robert Walter is currently offline Robert Walter
Messages: 29
Registered: July 2011
Junior Member
Hi,

I use two different strategies to create BIRT reports due to performance reasons and assumed that the result should be the same, but it turns out it isn't.

Context: User's of my application can configure whether they want to export data in either PDF or HTML or in both formats at once.

In case that both formats should be exported, I create a RunTask instance once (to store the runtime report design) and then use a RenderTask instance to render both outputs.

For the case of only one output (PDF or HTML), I wanted to make use of the RunAndRenderTask class since it seems to be a bit more perfomant in terms of memory consumption than my former approach.

Since I encountered a page overflow issue lately which I describe here, I had to set the PAGE_OVERFLOW option to FIT_TO_PAGE_SIZE for PDF rendering to avoid doubled pages. As a consequence of that, it turned out that my two strategies now produce differently layouted results and I cannot figure out why (since I set up the same engine options as well as render options).

Here is how the two strategies are basically implemented (I rewrote it in two separate functions for this post, to make it better comparable):
Version 1: runTask + renderTask
private List<String> generateBirtReportV1(Resource transformedResource, final IProgressMonitor subMonitor)
		throws EngineException {
	subMonitor.beginTask("Generate Birt report", 31);
	EngineConfig config = createEngineConfig();
	IReportEngine engine = createEngine(config);

	final List<String> filesToOpen = Lists.newArrayList();
	try {
		checkAndHandleMonitorCanceled();
		IReportRunnable reportRunnable = null;
		for (final Format f : this.formats) {
			final IFile file = getOutputFile(f);

			// we only have to run this task once for all output formats
			if (reportRunnable == null) {
				reportRunnable = runRunTask(engine, transformedResource, subMonitor);
			}

			runRenderTask(engine, reportRunnable, f, transformedResource, subMonitor);
			final IFile file = getOutputFile(f);
			String path = file.getLocation().toPortableString();
			filesToOpen.add(path);
		}

	} finally {
		engine.destroy();
		subMonitor.done();
	}
	return filesToOpen;
}

protected IReportRunnable runRunTask(IReportEngine engine, Resource transformedResource, final IProgressMonitor monitor) throws EngineException {
	IReportRunnable design = getReport(engine);
	if (design == null) {
		return null;
	}
	final IRunTask runTask = engine.createRunTask(design);
	setCommonTaskSettings(runTask, transformedResource);
	try {
		runTask.run(getTargetPath().concat(".rptdocument"));
		return runTask.getReportRunnable();
	} finally {
		runTask.close();
	}
}

protected void runRenderTask(IReportEngine engine, IReportRunnable reportRunnable, Format format,
		Resource transformedResource, final IProgressMonitor monitor) throws EngineException {
	IReportDocument reportDocument = engine.openReportDocument(getTargetPath().concat(".rptdocument"));
	final IRenderTask renderTask = engine.createRenderTask(reportDocument, reportRunnable);
	renderTask.setRenderOption(createRenderOption(format));
	setCommonTaskSettings(renderTask, transformedResource);
	try {
		renderTask.render();
	} finally {
		renderTask.close();
		reportDocument.close();
		disposeOutputStream();
	}
}


Version2: RunAndRenderTask (which is used for all formats in this example)
private List<String> generateBirtReportV2(Resource transformedResource, final IProgressMonitor subMonitor)
		throws EngineException {
	subMonitor.beginTask("Generate Birt report", 31);
	EngineConfig config = createEngineConfig();
	IReportEngine engine = createEngine(config);

	final List<String> filesToOpen = Lists.newArrayList();
	try {
		checkAndHandleMonitorCanceled();
		for (final Format f : this.formats) {
			runRunAndRenderTask(engine, f, transformedResource, new SubProgressMonitor(subMonitor, 20));
			final IFile file = getOutputFile(f);
			String path = file.getLocation().toPortableString();
			filesToOpen.add(path);
		}

	} finally {
		engine.destroy();
		subMonitor.done();
	}
	return filesToOpen;
}

protected void runRunAndRenderTask(IReportEngine engine, Format format, Resource transformedResource, final IProgressMonitor monitor) throws EngineException {
	IReportRunnable design = getReport(engine);
	if (design == null) {
		return;
	}
	final IRunAndRenderTask runAndRenderTask = engine.createRunAndRenderTask(design);
	runAndRenderTask.setRenderOption(createRenderOption(format));
	setCommonTaskSettings(runAndRenderTask, transformedResource);

	try {
		runAndRenderTask.run();
	} catch (OperationCanceledException e) {
		if (monitor.isCanceled()) {
			return;
		}
		throw e;
	} finally {
		runAndRenderTask.close();
		disposeOutputStream();
		monitor.done();
	}
}


As you can see, I use the same methods to create the render options and to set common task settings, which look like this:

protected void setCommonTaskSettings(IEngineTask engineTask, Resource transformedResource) {
	// ** locale
	engineTask.setLocale(new Locale(this.language));

	// ** Parameter Values
	if (transformedResource != null) {
		engineTask.setParameterValue("resource", transformedResource.getURI().toString());
	}
	engineTask.setParameterValue("project", toPlatformURIString(this.project).concat("/"));
	engineTask.setParameterValue("title", this.title);
	engineTask.setParameterValue("isTrial", ReportPlugin.getInstance().isTrial());
	// set parameter logo if user specified custom logo
	SpecConfigModel specConfigModel = getReportModel();
	String logoFilePath = specConfigModel.getLogoFilePath();
	if (logoFilePath != null && logoFilePath.length() > 0) {
		IPath path = new Path(logoFilePath);
		engineTask.setParameterValue("logo", "reports/customlogo/" + path.lastSegment());
	} // otherwise do nothing, the parameter logo should have a sensible
		// default in the rptdesign file
	String footer = specConfigModel.getFooter();
	if (footer != null && !Activator.isTrial()) {
		engineTask.setParameterValue("footer", footer);
	} // otherwise do nothing, there is a default footer
}

protected IRenderOption createRenderOption(final Format format1) {
	switch (format1) {
		case HTML:
			HTMLRenderOption htmlRenderOption = new HTMLRenderOption();
			htmlRenderOption.setOutputFileName(getOutputFileName(format1));
			htmlRenderOption.setOutputFormat(getBIRTFormat(format1));
			htmlRenderOption.setImageDirectory("images");
			htmlRenderOption.setHtmlTitle(this.title);
			htmlRenderOption.setEnableAgentStyleEngine(true);
			htmlRenderOption.setEnableInlineStyle(false);
			htmlRenderOption.setEnableCompactMode(true);

			return htmlRenderOption;
		case PDF:
		default:
			PDFRenderOption pdfRenderOption = new PDFRenderOption();
			pdfRenderOption.setOption(IPDFRenderOption.DPI, 96);
			OutputStream outputStream = createOutputStream(format1);
			if (outputStream != null) {
				pdfRenderOption.setOutputStream(outputStream);
			} else {
				pdfRenderOption.setOutputFileName(getOutputFileName(format1));
			}
			pdfRenderOption.setOutputFormat(getBIRTFormat(format1));
			pdfRenderOption.setOption(IPDFRenderOption.PDF_HYPHENATION, Boolean.TRUE);
			pdfRenderOption.setOption(IPDFRenderOption.PDF_TEXT_WRAPPING, Boolean.TRUE);
			pdfRenderOption.setOption(IPDFRenderOption.PAGE_OVERFLOW, IPDFRenderOption.FIT_TO_PAGE_SIZE);
			return pdfRenderOption;
	}
}


For Version 1, the layout for the PDF is as expected. BIRT adds page breaks automatically where appropriate, and in case of the issue I described in the other post, the page is shrunk a little to avoid doubled pages. However, the second version shrinks all contents between two explicitly added page breaks (in my rptdesign file, I have some occasions where I ALWAYS set a page break before a new heading), i.e. BIRT is not adding smart page breaks automatically.

I tried to debug the different EngineTasks but wasn't able to figure out where the different layout behavior comes from.
Any ideas?
Re: RunTask+RenderTask vs. RunAndRenderTask [message #1116180 is a reply to message #1114922] Wed, 25 September 2013 04:14 Go to previous messageGo to next message
Michael Williams is currently offline Michael Williams
Messages: 1595
Registered: July 2009
Senior Member

Are you able to create a report with the sample database or other sample data where I can see the issue happen?

Michael

Add interactivity, scheduling, sharing, live Excel export, and JS integration to your BIRT app with the new, free BIRT server, BIRT iHub F-Type.
Re: RunTask+RenderTask vs. RunAndRenderTask [message #1121105 is a reply to message #1116180] Mon, 30 September 2013 09:20 Go to previous messageGo to next message
Robert Walter is currently offline Robert Walter
Messages: 29
Registered: July 2011
Junior Member
Hi Michael,
I haven't had enough time to reproduce it with the sample database and I'm not sure if I will in the next days. But I'll let you know as soon as I can show you the issue.
Robert
Re: RunTask+RenderTask vs. RunAndRenderTask [message #1138456 is a reply to message #1121105] Tue, 15 October 2013 05:24 Go to previous message
Michael Williams is currently offline Michael Williams
Messages: 1595
Registered: July 2009
Senior Member

Sounds good. Just let me know. Hopefully I'll have more time to look into this and your other question, soon.

Michael

Add interactivity, scheduling, sharing, live Excel export, and JS integration to your BIRT app with the new, free BIRT server, BIRT iHub F-Type.
Previous Topic:Doubled pages in PDF Export
Next Topic:How to create dynamic meter chart scale
Goto Forum:
  


Current Time: Tue Sep 23 20:36:19 GMT 2014

Powered by FUDForum. Page generated in 0.02012 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software