Integrating BIRT into RAP applications

Today I will show you a simple way on how to integrate BIRT into your RAP application to produce reports and display them in the Browser widget.

At the moment I’m writing my diploma thesis and among other things I used BIRT (for the first time ever). It was really hard for me to get it running in RAP, but finally it worked!



Changelog

April 8, 2009: “6. Print BIRT report - the simple way” added.

1. Setting up the environment

So what do we need? I used the following settings (Windows):

Why do we use the Eclipse SR1 (3.4.1)? Because the Eclipse SR2 does not work properly with RAP.
We need the BIRT Runtime later.

Start Eclipse, open the Eclipse update manager (Help\Software Updates), choose the “Available Software”-tab and “Add Site”. Now add the following site:

http://download.eclipse.org/rt/rap/1.2/update

And of course, we need BIRT installed in Eclipse to produce nice charts. In the update manager, choose your Eclipse release (for example “Ganymade Update Site”) and select “Charting & Reporting” and “Database Development”. (You can also visit “Installing BIRT using Update Manager Instructions” for help!)

We can now install the selected software (RAP and BIRT). This may take some time.

Restart Eclipse, open the “Welcome” view (Help\Welcome), choose “Rich Ajax Platform” and “Install Target Platform”.

2. Copying BIRT Runtime to RAP target

Unpack the previously downloaded BIRT Runtime to any folder on your harddrive. Switch to “birt-runtime\ReportEngine\plugins” and delete the following plugins, because the RAP ones are newer than in BIRT (RAP 1.2 M5 and BIRT 2.3.2):

org.eclipse.core.contenttype

org.eclipse.core.expressions

org.eclipse.core.jobs

org.eclipse.core.runtime

org.eclipse.equinox.app

org.eclipse.equinox.common

org.eclipse.equinox.preferences

org.eclipse.equinox.registry

org.eclipse.osgi.services

org.eclipse.osgi

org.eclipse.update.configurator

Now copy all remaining plugins to the RAP target’s “plugins” directory. You can find the right folder in Eclipse by “Window\Preferences” and then “Plug-in Development\Target Platform”.
(for example: “eclipse\configuration\org.eclipse.rap.target-1.2\eclipse\plugins”)

Back in Eclipse switch to “Window\Preferences\Plug-in Development\Target Platform” and hit “Reload”.

That’s it.

3. Create a new project

Now that it is everything ready we choose the “Plug-in Development” perspective and create a new project. Leave the default settings as they are.

BIRT in RAP - New Project

Use one of the templates to create the project because then everything is configured correctly. I used the “RAP Application with a View”.

If everything was created properly, you should now see the following classes:

Activator

Application

ApplicationActionBarAdvisor

ApplicationWorkbenchAdvisor

ApplicationWorkbenchWindowAdvisor

Perspective

View

To test the application you should open the plugin.xml (Overview) an hit “Launch a RAP Application”.

BIRT in RAP - Launch RAP

What’s next? We customize the run configuration to handle the BIRT chart generation.
Open the “Run Configurations” (Run\Run Configurations) and select the following bundles at the “Bundles” tab:

com.ibm.icu instead of com.ibm.icu.base

org.eclipse.birt.api

org.eclipse.birt.chart.device.extension

org.eclipse.birt.chart.engine

org.eclipse.birt.chart.engine.extension

org.eclipse.birt.chart.reportitem

org.eclipse.birt.core

org.eclipse.birt.data

org.eclipse.birt.data.aggregation

org.eclipse.birt.report.data.adapter

org.eclipse.birt.report.engine

org.eclipse.birt.report.engine.emitter.html

org.eclipse.birt.report.item.crosstab.core

org.eclipse.birt.report.model

Then push the “Add Required Bundles” button. You should have about 70 bundles selected now. Start the application again.

Our application is now bundle-ready to render BIRT reports!

4. Generate a report with the BIRT Report Designer

Switch to the “Report Design” perspective, create a new blank BIRT report (File\New\Other\Business Intelligence and Reporting Tools\Report) and then add a chart to it. (I added a bar chart; 2D with Depth; translucent; Color by category)

If you don’t know how to create a BIRT report you should visit [1].

Then create a new “Scripted Data Source” and a “Scripted Data Set” for the report. This is an easy way to transfer data from a Java class to the report.

Double click the “Scripted Data Set” and add the two “Output Columns” named “category” (String) and “value” (Integer) to it.

Select the “Scripted Data Set” (1) and switch to the “Script” tab (2). Make sure that the “open” script is selected (3).

BIRT in RAP - Report Data Source

Add the following snippet to the script.

i = 0;
dataset = params["CHART_DATASET"].value;

The CHART_DATA is a report parameter which is defined in the Java class. More about this later.

Now switch to the “fetch” script and paste the following snippet:

if ( i < dataset.length ) {
  row["value"] = dataset[i][0];
  row["category"] = dataset[i][1];
  i++;
  return true;
}
  return false;

Now double click the chart, select the created “Scripted Data Set” and enter the value (row["value"]) and the category (row["category"]). We ignore the errors which are shown above.

BIRT in RAP - Report Select Data

5. Render BIRT report and show it in the Browser widget

Switch to the “Plug-In Development” perspective, open the “View.java” and clean it up. It should now look like this:

public class View extends ViewPart {
  public static final String ID = "de.tim_pietrusky.birt_in_rap.view";

  public void createPartControl(Composite parent) {
  }  

  public void setFocus() {}
}

Now we breathe life into the view by

setting up the right URL to the BIRT report file

setting a report parameter to “transfer” some data set to the report

setting the output of the task to render as HTML

handling the path of the rendered chart image

  private Browser browser;

  private static final String reportName = "birt_in_rap_report.rptdesign";
  private static final String reportDirLocal = "/resources/birt/";
  private static final String reportDirServer = "/birt/";
  private String reportDesign; // Full path to the local BIRT report file
  private String URL;

  private IReportEngine engine = null;
  private EngineConfig config = null;
  private IReportRunnable design = null;
  private IRunAndRenderTask task;
  private HTMLRenderOption renderOptions;

  private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

  public void createPartControl(Composite parent) {
    this.setPartName("BIRT in RAP");
    browser = new Browser(parent, SWT.NONE);
    configureURL();

    try {
      config = new EngineConfig();
      IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
      engine = factory.createReportEngine(config);

      URL url;
      InputStream fs = null;
      try {
        url = new URL(reportDesign);
        fs = url.openStream();
      } catch (MalformedURLException ex) {
        ex.printStackTrace();
      } catch (IOException ex) {
        ex.printStackTrace();
      }

      design = engine.openReportDesign(fs);

      // Create task to run and render the report
      task = engine.createRunAndRenderTask(design);

      // Example dataset
      Object[][] dataset = new Object[3][2];
      for (int i = 0; i < dataset.length; i++) {
        dataset[i][0] = (i + 1) * 2;
        dataset[i][1] = "category " + (i + 1);
      }

      // Set the dataset for the chart as report parameter
      task.setParameterValue("CHART_DATASET", dataset);

      // Render the report to HTML
      renderOptions = new HTMLRenderOption();
      renderOptions.setOutputFormat(HTMLRenderOption.HTML);
      renderOptions.setOutputStream(outputStream);

      // Please delete the unnecessary \"
      // I needed it to show the right code in my blog
      String webAppBase = (ContextProvider.getWebAppBase()).replaceAll("\\\\\"", "/");
      String path = webAppBase + reportDirServer + RWT.getSessionStore().getId();

      // Handle the image-path
      renderOptions.setImageHandler(new HTMLServerImageHandler());
      renderOptions.setImageDirectory(path);
      renderOptions.setBaseImageURL(URL + reportDirServer + RWT.getSessionStore().getId());

      task.setRenderOption(renderOptions);
      task.run();
      task.close();

      // Set the HTML output to the Browser widget
      browser.setText(outputStream.toString());

      engine.destroy();

    } catch (EngineException ex) {
      ex.printStackTrace();
    }
  }

  // Set the URL for the BIRT report for different environments.
  private void configureURL() {
    // Protocol, ip & port
    ServletContext sc = RWT.getRequest().getSession().getServletContext();

    String realPath = sc.getRealPath("/");

    HttpServletRequest request = RWT.getRequest();
    String protocol = "http://";
    String ip = request.getLocalAddr();
    int port = request.getLocalPort();
    URL = protocol + ip + ":" + port;
    String webAppName = "";

    if (realPath == null) { // Start application locally within Eclipse (Windows)
      reportDesign = URL + reportDirLocal + reportName;
    } else { // Start application on a server (Apache Tomcat or so)
      webAppName = sc.getContextPath();
      reportDesign = URL + webAppName + reportDirLocal + reportName;
      URL = URL + webAppName;
    }
  }

There are some unresolved imports to fix. Open the “plugin.xml”, switch to the “Dependencies” tab and add the following plugins:

org.eclipse.birt.core

org.eclipse.birt.report.engine

org.eclipse.birt.chart.engine

Ok. Everything ready? No, because our application needs to know how to find the BIRT report file on the server. So we need to register the resources directory via an extension point. Open the “plugin.xml” (if it is not already opened), switch to the “Dependencies” tab and add the following equinox plugin:

org.eclipse.equinox.http.registry

Switch to the “Extensions” tab and add the following extension point:

org.eclipse.equinox.http.registry.resources

Edit the extension element details with alias = “/resources/birt” and base-name = “/resources/birt” (Without the quotation marks). This path is the same as above at line 4.

BIRT in RAP - Register resources

Start the application and you will see your BIRT chart in the Browser widget.

BIRT in RAP - BIRT chart in Browser widget

6. Print BIRT report - the simple way

A simple (and for now the only, see [2].) way to print a BIRT report within the browser widget is to execute a JavaScript in the browser.

So first, we open our View.java and add the following method:

  public void executeScript(String script) {
    browser.execute(script);
  }

The browser widget is now prepared to execute JavaScript from the “outside” of the View.java.

Next we need to give the user the possibility to print the BIRT report when he clicks for example on an element in the file menu. Let’s call it “Print report”. So we create a new class named “PrintAction.java” which extends org.eclipse.jface.action.Action.

BIRT in RAP - PrintActin.java

Now we fill the PrintAction.java with life:

  public static final String ID = "de.tim_pietrusky.birt_in_rap.printAction"; //$NON-NLS-1$

  public PrintAction(IWorkbenchWindow window) {
    setId(PrintAction.ID);
    setText("Print report");
  }

  public void run() {
    View view = (View) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
        .getActivePage().findView(View.ID);

    view.executeScript("window.print();");
  }

At line 9 we get the current instance of the View.java, to call the View#executeScript() method. (window.print(); is the JavaScript method to forward a call to the OS to print the page)

At the end we need to register the created action with the ApplicationActionBarAdvisor.java to be used by the user. I looks like this:

  ...
  private PrintAction printAction;

  protected void makeActions(IWorkbenchWindow window) {
    ...
    printAction = new PrintAction(window);
    register(printAction);
  }

  protected void fillMenuBar(IMenuManager menuBar) {
    MenuManager fileMenu = new MenuManager("&File",IWorkbenchActionConstants.M_FILE);
    menuBar.add(fileMenu);
    ...
    fileMenu.add(printAction);
  }
  ...

Questions? Suggestions? If not then thank you for your attention.

You can download the whole project and my Target Platform:



Share and Enjoy:
  • Digg
  • del.icio.us
  • Google
  • Facebook
  • Mixx
  • Sphinn
  • TwitThis
  • LinkedIn
  • Live
  • MySpace
  • Yigg
  • Slashdot

7 Responses to “Integrating BIRT into RAP applications”

  1. feng  on April 8th, 2009

    But how to print the report?

  2. Tim Pietrusky

    Tim Pietrusky  on April 8th, 2009

    Hey feng,

    I extended the tutorial to explain how to simply print a BIRT report via Browser#execute(Strint script).

  3. BIRT linking user  on April 18th, 2009

    Hi,

    Your help would be appreciated. Is it simply possible to open a link of a report in a new browser window inside the rap session? If I link to the same report the result would be having two “BIRT in RAP” windows in my web browser.

    I tried out modifying your example report by adding a “Mouse Click” event to the “Value (Y) Series” of the bar chart with following “URI”-expression: “http://127.0.0.1:2210/rap?startup=view”;
    Trying it out opened a new window (and new rap session) of my web browser. This is not desired.

    I have currently no intention to use birt with rap now.

  4. Tim Pietrusky

    Tim Pietrusky  on April 19th, 2009

    Hey BIRT linking user,

    what are you trying to achive?

    Do you want to show the rendered report in a new browser window instead of showing it in the browser widget?

    Please specify your exact problem so I can help you!

  5. BIRT linking user  on April 20th, 2009

    Hi,

    “browser widget” is the appropriate term to describe what I mean.
    The desired behaviour of following a report link would be opening a new browser widget inside the web browser window.
    As a result there would be only one web browser window (or only one web browser tab) (that is, i assume, one rap session) with multiple browser widgets, each displaying a report.

  6. Anirudh_Raghavan  on June 3rd, 2009

    Very useful blog


Leave a Reply