Wednesday, January 02, 2008

BIRT: Creating Event Handlers in Java

I'm speaking at EclipseCon 2008

Strange, although I wrote about it in this article, I never wrote an article on how to use Java classes as Event Handlers in BIRT. I probably was meaning to, but it was one of those things that slipped my mind. Its taken me a few weeks, but I am slowly coming out of perpetual daze from a series of excessively demanding jobs, the book writing, and the wedding over the past 6 months.

So, in this article we are going to look at how to create an external event handler in Java, and how to get BIRT to call it. I will look at using this in the Eclipse environment only, with a brief explanation on how to get the class to work in a BIRT deployed environment.

1: Start a new Java project called MyEventHandler.


2: In your project, be sure to include the libraries from the BIRT Runtime.



3: Create a new class called CountingScriptedEventHandler. Be sure to include a package, otherwise BIRT will not recognize it. I am not sure why that is the case, it just will not. The class must inherit the org.eclipse.birt.report.engine.api.script.eventadapter. ScriptedDataSetEventAdapter class.



4: Using Eclipses built in Override/Implement method utility, available from the Source menu, pick the fetch and open methods to implement.




5: Use the following code for the Event Handler:

package com.digiassn.blogspot.birt.handlers;

import org.eclipse.birt.report.engine.api.script.IUpdatableDataSetRow;
import org.eclipse.birt.report.engine.api.script.ScriptException;
import org.eclipse.birt.report.engine.api.script.eventadapter.ScriptedDataSetEventAdapter;
import org.eclipse.birt.report.engine.api.script.instance.IDataSetInstance;

public class CountingScriptedEventHandler extends ScriptedDataSetEventAdapter {
int count = 0;

@Override
public boolean fetch(IDataSetInstance dataSet, IUpdatableDataSetRow row) {
try {
if (count < 10)
{
row.setColumnValue("count", count);

count++;

return true;
}
} catch (ScriptException e) {
e.printStackTrace();
}

return super.fetch(dataSet, row);
}
}


6: Save your file. Exit Eclipse and reenter (not sure why the event handler won’t show up without this step, but it won’t). Now, create a report project called MyEventHandlerReport.
7: Create a new report called myEventReport.rptDesign.
8: Add in a new Scripted Data Source.


9: Create a new scripted Data Set. Create a single column called count.



10: Select the data set. In the Property Editor, select the Event Handler tab. Click browse and select the event handler from the list.



11: Now, select the data set in the Data Explorer, and drag it over to the Report Designer.



Save and run the report.



Well, that’s cool and all, but how do we get report parameters into this guy. Lets say we wanted the user to able to limit the count themselves instead of using a hardcoded number. Well, we need to get access to the Report Context object, which is not available in the open or fetch method. So instead, we need access to the BeforeOpen method in the parent class. Rewrite the event handler like so:

package com.digiassn.blogspot.birt.handlers;

import org.eclipse.birt.report.engine.api.script.IReportContext;
import org.eclipse.birt.report.engine.api.script.IUpdatableDataSetRow;
import org.eclipse.birt.report.engine.api.script.ScriptException;
import org.eclipse.birt.report.engine.api.script.eventadapter.ScriptedDataSetEventAdapter;
import org.eclipse.birt.report.engine.api.script.instance.IDataSetInstance;

public class CountingScriptedEventHandler extends ScriptedDataSetEventAdapter {
int count = 0;
int MAX_NUM;

@Override
public boolean fetch(IDataSetInstance dataSet, IUpdatableDataSetRow row) {
try {
if (count < MAX_NUM)
{
row.setColumnValue("count", count);

count++;

return true;
}
} catch (ScriptException e) {
e.printStackTrace();
}

return super.fetch(dataSet, row);
}

@Override
public void beforeOpen(IDataSetInstance dataSet,
IReportContext reportContext) {

super.beforeOpen(dataSet, reportContext);

if (reportContext.getParameterValue("MAX_NUMBER") != null)
MAX_NUM = (Integer)reportContext.getParameterValue("MAX_NUMBER");
else
MAX_NUM = 10;
}
}


Next, I create a report parameter of type Integer called MAX_NUMBER.



Now, when I run the report, and put in the parameter, it controls the number of results I see.

3 comments:

Anonymous said...

Hi!

Your tutorial works fine with the integrated preview, but if you use a stand alone (RunAndRenderTask) the report is empty, as if the dataSet returned no values.
Are there any special requisites (besides the Run and Render example in the main site) to run a report with a scripted data source/set outside the preview?

Thanks in advance,
LL (lflobo@gmail.com)

Anonymous said...

Please ignore this last post.
Problem was related with the use of openjdk. Lost 3 days with this issue :(

Regards,
LL

Rosh said...
This comment has been removed by the author.