| Java, Eclipse and Web programming Tutorials |
Version 1.0
Copyright © 2008 - 2010 Lars Vogel / Hendrik Still
22.01.2010
| Revision History | ||
|---|---|---|
| Revision 0.1 - 0.2 | 07.03.2008 | Hendrik Still |
| Created Article | ||
| Revision 0.3 | 07.03.2009 | Lars Vogel |
| Correted datamodel, dao, fixed screenshots | ||
| Revision 0.4 | 26.03.2009 | Lars Vogel |
| Updated Article | ||
| Revision 0.4 | 12.04.2009 | Lars Vogel |
| Corrected open script | ||
| Revision 0.5 | 07.05.2009 | Lars Vogel |
| StockDaoMock always returns data | ||
| Revision 0.6 | 12.05.2009 | Lars Vogel |
| Tomcat installation overview | ||
| Revision 0.7 | 24.06.2009 | Lars Vogel |
| Update to Eclipse 3.5 (Galileo) | ||
| Revision 0.8 | 08.07.2009 | Lars Vogel |
| Fixed RCP issue, corrected fetch and open script | ||
| Revision 0.9 | 14.09.2009 | Lars Vogel |
| Applied improved RCP view code from Nikhil Milo | ||
| Revision 1.0 | 22.01.2010 | Lars Vogel |
| Fixed double-screenshot | ||
Eclipse Birt
This article describes how to use Eclipse BIRT for reporting on simple Java Objects (POJO's - Plan old Java Objects).
The article will also explain how to deploy the resulting BIRT report into a webcontainer (tomcat) and how to use it in an Eclipse RCP application.
Eclipse 3.5 (Eclipse Galileo) is used for this tutorial.
Table of Contents
Eclipse BIRT allows the creation of reports using various data sources.
These data sources define where the data is stored. Data sets defines the query for the report.
BIRT provides for example the following data sources:
Databases (via JDBC)
Text Files (cvs, XML)
WebServices (via WSDL-Files)
Scripting Data sources
In a Java program it is often convenient to use directly Java objects as a data source for reports. This article will focus on the usage of plain old Java objects (POJO) as data sources for BIRT reports.
Use the Eclipse Update Manager to install BIRT. This package can be found in the Galileo update site under "Business Intelligence, Reporting and Charting" -> BIRT Framework.
See Using the Eclipse Update Manager for details.
Create a new Java Project with the name "de.vogella.birt.stocks".
Create a new report "stock_report.rptdesign" via File -> New -> Other -> Business Intelligence and Reporting -> Report.



The new report is displayed in the "Report Design" perspective.
Delete now everything except the report header. The result should look like the following.

The report will display stock data. To demonstrate BIRT we use a Mock object for providing the data. The appendix demonstrates how to get real stock data via a Yahoo service.
Create package "de.vogella.birt.stocks.model" and then the following class. This class will represent the domain model.
package de.vogella.birt.stocks.model;
import java.util.Date;
/**
* Domain model for stock data
* @author Lars Vogel
*/
public class StockData {
private Date date;
private double open;
private double high;
private double low;
private double close;
private long volume;
public double getClose() {
return close;
}
public void setClose(double close) {
this.close = close;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getHigh() {
return high;
}
public void setHigh(double high) {
this.high = high;
}
public double getLow() {
return low;
}
public void setLow(double low) {
this.low = low;
}
public double getOpen() {
return open;
}
public void setOpen(double open) {
this.open = open;
}
public long getVolume() {
return volume;
}
public void setVolume(long volume) {
this.volume = volume;
}
}
Create the package "de.vogella.birt.stocks.daomock" and then the following class.
package de.vogella.birt.stocks.daomock;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import de.vogella.birt.stocks.model.StockData;
public class StockDaoMock {
public List<StockData> getStockValues(String company) {
// Ignore the company and always return the data
// A real implementation would of course use the company string
List<StockData> history = new ArrayList<StockData>();
// We fake the values, we will return fake value for 01.01.2009 -
// 31.01.2009
double begin = 2.5;
for (int i = 1; i <= 31; i++) {
Calendar day = Calendar.getInstance();
day.set(Calendar.HOUR, 0);
day.set(Calendar.MINUTE, 0);
day.set(Calendar.SECOND, 0);
day.set(Calendar.MILLISECOND, 0);
day.set(Calendar.YEAR, 2009);
day.set(Calendar.MONTH, 0);
day.set(Calendar.DAY_OF_MONTH, i);
StockData data = new StockData();
data.setOpen(begin);
double close = Math.round(begin + Math.random() * begin * 0.1);
data.setClose(close);
data.setLow(Math.round(Math.min(begin, begin - Math.random() * begin * 0.1)));
data.setHigh(Math.round(Math.max(begin, close) + Math.random() * 2));
data.setVolume(1000 + (int) (Math.random() * 500));
begin = close;
data.setDate(day.getTime());
history.add(data);
}
return history;
}
}
To use Java Objects (POJO's) as datasource in Eclipse BIRT you have to map the fields of your Java classes to JavaScript. This JavaScript is then used to access the Java Object.
The datasource connects your data with your report. Birt provides different types of datasources, we use the "Scripted Data Source". Go back to your stocks_report, use the "Report Design" perspective and select the "Data Explorer" View.
Create a new datasource, named "srcStocks" in your report.


The dataset defines the mapping for the datasource data and the birt data.
Create a new dataset named "dataSetSocks".


Press next and define the columns for your report.

Now we have to write the JavaScript for our dataset. Select the dataset and choose "open" as script. The open script is called before the first access to the dataset. We use this to load our List with the stock objects. To access a Java class you only have to use the following syntax: Packages.myJavaClass where myJavaClass is the full qualified Java class name.

count = 0;
// Create instance of
// the GetStockHistory class
gsh = new Packages.de.vogella.birt.stocks.daomock.StockDaoMock();
//Load the List
stock = gsh.getStockValues("Java");
Place the following coding in the fetch script.
if(count < stock.size()){
row["columnDate"] = stock.get(count).getDate();
row["columnOpen"] = stock.get(count).getOpen();
row["columnHigh"] = stock.get(count).getHigh();
row["columnLow"] = stock.get(count).getLow();
row["columnClose"] = stock.get(count).getClose();
row["columnVolume"] = stock.get(count).getVolume();
count++;
return true;
}
return false;
Check if your Script works by doubleclicking on the dataset -> Preview Result.

Switch from "Data Explorer" to the "Palette". Select the tab "Layout".

Drag and drop the table element on the report.

Define the following settings for the table.

Change back to the "Data Explorer". And drag and drop the dataset columns into the "Details row" of the table.

The result should look like the following.

Done. You can see a preview of the report if you click on the "Review" Tab. The result should look like the following:

Switch back to the Palette, select a chart and drag and drop it on your report.
Choose the Line Chart with the standard settings.

Press Next and select your data set.

At the next step we have to assign the columns to the axis. We assign the date to the x axis and the open value to the y axis via drag and drop.

Define 5 series in total. Assign the columns to these series by dragging the column to the Sum sign.

Currently the x axis shows first the newest date. Reverse the x axis by you have to sort the data ascending. Press the highlighted button.

Go to the next tab and give titles to your columns. Hide the last one.

The display of the dates use a long format, we would like to change this. Perform the following and choose "short" as date type of the x axis

Change the display of the lines via the following.

Press finish to include your chart into your report.
The following explains how to use BIRT reports in Tomcat. In general you have to:
Install the BIRT webviewer in Tomcat
Export your BIRT project into a .jar file
Move the .jar file to the birt-install-directory/WEB-INF/lib directory
Move the report design file into the root directory of birt in tomcat
Restart Tomcat
We will use a standalone Tomcat 6.0 which we assume is already installed. See Apache Tomcat Tutorial for details.
You need the "Deployment components of BIRT" http://download.eclipse.org/birt/downloads/ .
Copy the birt.war of this download into the Tomcat webappsfolder.
The Birt example should be available under http://localhost:8080/birt/.If you see something like this, your Tomcat an your Web Viewer should work correct.

To run your own reports you have to copy the .rptdesign file in the root of the birt folder in Tomcat. To make your Java classes available export your project into a jar file.



After that the jar file has to be copied to the Tomcat webapps/birt/WEB-INF/lib/ directory. Restart the Tomcat and navigate to your report.
Your report should be found under http://localhost:8080/birt/frameset?__report=stock_report.rptdesign

We can use the Birtviewer also in a local RCP Application, it isn't more than an browser view which shows a HTML Page generated by an integrated Webserver.
The following assumes that you are already familiar with Eclipse RCP development. See Eclipse RCP Tutorial in case you need an introduction.
Convert "de.vogella.birt.stocks" to a plugin project, via right mouse click -> Configure -> "Convert to plug-in project".
Create an new plugin project "de.vogella.birt.stocks.rcp". Select the template "RCP Application with a view".
Add the following plugins as dependendies to "de.vogella.birt.stocks.rcp".
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Rcp Bundle-SymbolicName: de.vogella.birt.stocks.rcp; singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: de.vogella.birt.stocks.rcp.Activator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.birt.report.viewer;bundle-version="2.5.0", org.eclipse.birt.report.engine.emitter.html;bundle-version="2.5.0", de.vogella.birt.stocks;bundle-version="1.0.0", org.eclipse.birt;bundle-version="2.5.0", org.eclipse.birt.chart.ui;bundle-version="2.5.0", org.eclipse.birt.chart.cshelp;bundle-version="2.5.0", org.eclipse.birt.chart.device.extension;bundle-version="2.5.0", org.eclipse.birt.chart.device.pdf;bundle-version="2.5.0", org.eclipse.birt.chart.device.svg;bundle-version="2.5.0", org.eclipse.birt.chart.device.swt;bundle-version="2.5.0", org.eclipse.birt.chart.engine.extension;bundle-version="2.5.0", org.eclipse.birt.chart.examples;bundle-version="2.5.0", org.eclipse.birt.chart.reportitem;bundle-version="2.5.0", org.eclipse.birt.chart.reportitem.ui;bundle-version="2.5.0", org.eclipse.birt.chart.ui.extension;bundle-version="2.5.0", org.eclipse.birt.core.script.function;bundle-version="2.5.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Copy your report to "stock_report_rcp.rptdesign" into this new project. Open this report and change the "open" JavaScript to the following.
count = 0;
/*
* load and init data reader
* import Platform from org.eclipse.core.runtime
*/
importPackage(Packages.org.eclipse.core.runtime);
/* load bundle with POJOs and data loading class */
myBundle = Platform.getBundle("de.vogella.birt.stocks");
/* load data reader class */
readerClass = myBundle.loadClass("de.vogella.birt.stocks.daomock.StockDaoMock");
/* create new instance of DataReader */
readerInstance = readerClass.newInstance();
/* read data */
stock = readerInstance.getStockValues("Java");
Use this code as View.java.
package de.vogella.birt.stocks.rcp;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.birt.report.viewer.utilities.WebViewer;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.Bundle;
public class View extends ViewPart {
public static final String ID = "de.vogella.birt.stocks.rcp.view";
public void createPartControl(Composite parent) {
String path = "";
try {
Bundle bundle = Platform.getBundle("de.vogella.birt.stocks.rcp");
path = new URL(bundle.getLocation()).getPath();
path = path .substring(6); //"file:/" 0 bis 5
path = path .replace("/", "\\");
path = path + "stock_report_rcp.rptdesign";
}
catch (MalformedURLException me){
System.out.println(me.getStackTrace());
}
Browser browser = new Browser(parent, SWT.NONE);
// Use the filename of your report
WebViewer.display(path, WebViewer.HTML, browser, "frameset"); }
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}
}
What is an report without the correct data? Correct, nothing! We want to display the newest data of our favorite stock. Yahoo! Finance provides automatically generated CSV files of all stocks on the market. To get this we only have to download a file from this link http://ichart.finance.yahoo.com/table.csv?s=JAVA . It gives you a csv file with the history of the stock. As you can see, this "service" has the parameter s=JAVA with the name of the stock.
The following code is using the Apache HttpClient library. The Apache HttpClient library allow you to simulate a browser and send and receive HTTP data. Download the necessary libraries from http://hc.apache.org/
As the time of the writing HttpClient requires also additional libraries, currently they are described here: http://hc.apache.org/httpclient-3.x/dependencies.html
Download all required libraries and add them add them to your classpath.
Interesting for you is that we need the method updateHistory of the GetStocksHistory class with a string parameter(stock name) , which returns us a ArrayList.
package de.vogella.stockticker;
import java.util.ArrayList;
public class StockHistory {
ArrayList<StockData> m_stockHistory;
public StockHistory() {
m_stockHistory = new ArrayList<StockData>();
}
public void add (StockData data) {
m_stockHistory.add(data);
}
}
package de.vogella.stockticker;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
public class GetStockHistory {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
NumberFormat nf = NumberFormat.getInstance(Locale.US);
NumberFormat pf = NumberFormat.getInstance(Locale.US);
StockHistory history = new StockHistory();
public ArrayList<StockData> updateHistory(String company) {
Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
to.set(2009, 01, 01);
from.set(2006, 01, 01);
System.out.println(to.toString());
StringBuffer url = new StringBuffer(
"http://ichart.finance.yahoo.com/table.csv" + "?s=");
url.append(company);
try {
HttpClient client = new HttpClient();
client.getHostConfiguration().setProxy("proxy", 8080); // Delete
// this Line
// if you
// don't use
// a proxy
client.getHttpConnectionManager().getParams().setConnectionTimeout(
5000);
System.out.println(url.toString());
HttpMethod method = new GetMethod(url.toString());
method.setFollowRedirects(true);
client.executeMethod(method);
BufferedReader in = new BufferedReader(new InputStreamReader(method
.getResponseBodyAsStream()));
// The first line is the header, ignoring
String inputLine = in.readLine();
while ((inputLine = in.readLine()) != null) {
if (inputLine.startsWith("<"))
continue;
String[] item = inputLine.split(",");
if (item.length < 6)
continue;
Calendar day = Calendar.getInstance();
day.setTime(df.parse(item[0].replace("\"", "")));
day.set(Calendar.HOUR, 0);
day.set(Calendar.MINUTE, 0);
day.set(Calendar.SECOND, 0);
day.set(Calendar.MILLISECOND, 0);
StockData data = new StockData();
data.setOpen(Double.parseDouble(item[1].replace(',', '.')));
data.setHigh(Double.parseDouble(item[2].replace(',', '.')));
data.setLow(Double.parseDouble(item[3].replace(',', '.')));
data.setClose(Double.parseDouble(item[4].replace(',', '.')));
data.setVolume(Long.parseLong(item[5]));
data.setDate(df.parse(item[0].replace("\"", "")));
history.add(data);
}
in.close();
return history.m_stockHistory;
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
public static void main(String[] args) {
// GetStockHistory gsh = new GetStockHistory();
// ArrayList<StockData> sd = gsh.getNewHistory();
//
// for(int i=0;i < sd.size(); i++)
// {
// System.out.println(sd.get(i).getDate());
// }
}
}
Thank you for practicing with this tutorial.
Please note that I maintain this website in my private time. If you like the information I'm providing please help me by donating.For questions and discussion around this article please use the www.vogella.de Google Group. Also if you note an error in this article please post the error and if possible the correction to the Group.
I believe the following is a very good guideline for asking questions in general and also for the Google group How To Ask Questions The Smart Way.
http://www.vogella.de/code/codeeclipse.html Source Code of Examples