Open Development Platform

Eclipse Platform

Subscribe to Eclipse Platform: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Eclipse Platform: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Eclipse Platform Authors: Janakiram MSV, Ken Fogel, Marcin Warpechowski, Michael Meiner, Liz McMillan

Related Topics: Eclipse Platform, Java Developer Magazine

Blog Feed Post

Raising Errors in Event Handlers

Let me start with a simple scenario.  You are writing a BIRT event handler and you expect the user to set a UserDefinedProperty that will guide the event handler code.  How do you handle the situation where the user forgets to add the UserDefinedVariable?  How do you provide a message back to the user to help them solve the problem?

In the past I have focused on using logging and stepping through code.  While effective, it requires the person using your event handler code to have a relatively high level of sophistication.  Wouldn't it be great if you could pass an error message from your event handler code to the ReportEngine, so that the message would be displayed through the standard error handling mechanism?

The methods that are used to add exceptions to a report are not visible from the Script API.  I hope that we can get an enhancement into BIRT 2.5 that will make this easy to do, but what if you want to add code like this to the early version of BIRT.

It turns out that it is easy enough to do using Java reflection.  The ReportContext object wraps an instance of the ExecutionContext.  ExecutionContext supports a method:
     addException(BirtException exception)


All we need to do is figure out how to expose this method to our EventHandlers (Java or JavaScript).  To do this I created a static method called addBirtException, the complete code listing is as follows:

public static void addBirtException(IReportContext reportContext , String errorMessage) {
addBirtException(reportContext , errorMessage, BirtException.WARNING);
}

public static void addBirtException(IReportContext reportContext , String errorMessage, Integer severity) {

BirtException be = new BirtException("org.eclipse.birt.report.engine", errorMessage, new Object[]{""} );
be.setSeverity(severity);

try {
// get the protect field 'context' from reportContext
Class rciClass = reportContext.getClass();
Field fieldFromScript = rciClass.getDeclaredField("context");
if (fieldFromScript == null) {
return;
}

// instantiate the ExecutionContext object that
// populates the context field
fieldFromScript.setAccessible(true);
Object execContext = fieldFromScript.get(reportContext);

// now get a handle to the addException method on ExecutionObject
Class execClass = execContext.getClass();
Method addMethod = execClass.getMethod("addException", new Class[] { BirtException.class });

// finally invoke the method which will add the BirtException
// to the report
addMethod.setAccessible(true);
addMethod.invoke(execContext, new Object[] { be });

// Lots of ways for this to break...
} catch (Exception e) {
logger.warning(e.getMessage());
e.printStackTrace();
}
return;
}


Once you have the ScriptUtil class in your classpath you can call it from your Java class by  adding this code:

    ScriptUtil.addBirtException(reportContext, "Simple Error Message", BirtException.WARNING);

Will cause your report to run with the following error messages to display in your report.



But why stop there.  Now that you have the ability you can go ahead and provide detailed help back to the people that are using your report or event handler class:

    ScriptUtil.addBirtException(reportContext, "Simple Error Message", BirtException.WARNING);

StringBuffer sb = new StringBuffer();
sb.append("Complex error message that is designed to help a\n");
sb.append("report developer that is using your event handler\n");
sb.append("to successfully debug an improper implementation.\n");
sb.append("Could also be used to help end users identify report\n");
sb.append("issues to support and help desk staff.\n");
sb.append("\t - Can include error codes from other products\n");
sb.append("\t - Can include domain specific messages.\n\n");
sb.append("No more looking around for message logs or tracing through\n");
sb.append("gnarly stack traces");
ScriptUtil.addBirtException(reportContext, sb.toString(), BirtException.WARNING);

gives you:


This code is also easily callable from JavaScript.

Packages.deapi_event_handler.ScriptUtil.addBirtException(addBirtException, "my message");

So pretty cool eh?

But there is more, the BirtException supports localization, resource bundles, formatting all of the features that you may want in advanced report development.

Read the original blog entry...

More Stories By Jason Weathersby

Jason Weathersby is a member of the extended BIRT development team at Actuate Corporation and has backgrounds in both computer science and technical writing. He has many years experience in technical consulting, training, writing, and publishing about reporting, business intelligence tools, and database technologies.