http://www.developer.com/

Back to article

Adding Charts to Web-Based J2EE Applications


December 23, 2004

Business applications typically manage data. Therefore, developers often need to provide components that enable users to analyze that data. One way to do this is by providing users access to text-based reports. Another option is to provide a view to the data through a series of graphical charts. Charts can be an extremely useful tool because they allow users to visually compare data elements, spotting trends and patterns not easily discernable through reports when dealing with large amounts of data. Much of today's business software is Web-based and delivered through a browser. Nevertheless, requirements for these applications, namely data analysis requirements, remain the same. Luckily, if you are developing software with J2EE technologies, there are some open-source options to assist you. This article will demonstrate how J2EE developers can quickly add visually-appealing, graphical charts to their work.

JFreeChart and Cewolf—A Powerful Combination

JFree.org is a Web site that hosts many useful open-source projects. JFreeChart is just one such project. It is managed by David Gilbert. JFreeChart consists of a number of Java libraries that generate graphical charts based upon a set of data.

Cewolf is another open-source project. Cewolf comes with its own set of libraries, as well as a collection of JSP tags. The Cewolf project, founded by Guido Laures, gives developers an easy way to display JFreeChart-built charts in a JSP page. In other words, Cewolf is a layer that rests upon JFreeChart. Cewolf provides data input to JFreeChart, then displays the resulting image in a browser, as dictated by the JSP tags. Both projects' libraries are necessary to achieve the desired goal. The most recent version of Cewolf, version 0.9.8, supports JFreeChart up through, not by coincidence, version 0.9.8.

Concepts and Terminology

Graphical charts display one or more data 'series'. In some cases, these series may then be grouped into one or more 'categories'. A series is simply a collection of data values that is defined by name. For example, if we were to poll individuals on their favorite season, then 'Spring', 'Summer', 'Fall', and 'Winter' become the series names. In charts, each series is assigned a unique color or pattern and it usually appears in a legend. It is possible to group series into categories. If our previously mentioned poll were to be conducted over the course of two calendar years, year becomes a category that groups two sets of data series, one for each year. Deciding on a particular chart to represent your data (pie, line, bar, and so forth) often depends not only on how you want to display your data, but also on the complexity of the data you need to represent.

Charts display data, usually from a database, so JFreeChart requires a data source to perform its work. JFreeChart defines a base Java interface, called Dataset, to provide this data. Two of the most common Datasets are the CategoryDataset and the PieDataset. As you would expect, a PieDataset provides data to create pie charts. Pie charts are the simplest type of chart. They display a value for data series, and how each value contributes to the total value for all series. CategoryDataset is an interface for a more complex set of data that represents one or more series grouped by categories.

Cewolf provides an interface called DatasetProducer. Developers implement this interface to provide data to JFreeChart from a Web application. It is a DatasetProducer's responsibility to provide requested data, in the form of a JFreeChart Dataset, so that a chart may be constructed.

Getting Started

In this section, you will focus on the technical details necessary to add a pie chart to an application. The first requirement for this task is some sample data. I have created employee and department tables for the examples. Here is a bit of SQL used to create data in an hsql database:

CREATE TABLE dept (
  dept_id                INT NOT NULL IDENTITY,
  name                   VARCHAR(30) NOT NULL,
  descrip                VARCHAR(200)
);

CREATE TABLE emp (
  emp_id                 INT NOT NULL IDENTITY,
  dept_id                INT NOT NULL,
  f_name                 VARCHAR(30),
  l_name                 VARCHAR(30),
  hire_date              DATE,
  CONSTRAINT fk_dept_id FOREIGN KEY (dept_id)
     REFERENCES dept (dept_id)
);

INSERT INTO dept (name,descrip)
       VALUES('IT', 'Information Technology');
INSERT INTO dept (name,descrip)
       VALUES('ACCT', 'Corporate Accounting');
INSERT INTO dept (name,descrip)
       VALUES('MRKT', 'Sales and Marketing');
INSERT INTO dept (name,descrip)
       VALUES('HR', 'Human Resources and Payroll');

INSERT INTO emp(dept_id,f_name,l_name,hire_date)
       VALUES(0,'Mike','Smith','2003-01-29');
INSERT INTO emp(dept_id,f_name,l_name,hire_date)
       VALUES(0,'Joe','Taylor','2003-04-15');
INSERT INTO emp(dept_id,f_name,l_name,hire_date)
       VALUES(0,'Jennifer','Betts','2003-05-07');
...
--(more employees...)
...

Employees may be hired into one of four departments. The date of hire for each employee is captured in the emp table. Here is the entire SQL script if you would like to use it to compare against the charts you will derive from it.

In your Web application, you will need to include a number of libraries, including those from Cewolf and JFreeChart. By downloading the Cewolf distribution, you will receive all the necessary jar files. You should not need to download additional JFreeChart files. Place these jar files in your WEB-INF/lib folder:

jfreechart-0.9.8-demo.jar Jfreechart-0.9.8.jar Jcommon-0.8.0.jar Commons-logging.jar Cewolf.jar
Batik-xml.jar Batik-util.jar Batik-syggen.jar Batik-dom.jar Batik-awt-util.jar

Cewolf relies on a Java servlet, called CewolfRenderer, to render charts. This servlet accepts two input parameters. I will discuss these parameters below. For now, include the following servlet and servlet mapping definitions in your WEB-INF/web.xml:

<servlet>
    <servlet-name>CewolfServlet</servlet-name>
    <servlet-class>de.laures.cewolf.CewolfRenderer</servlet-class>

    <!-- sets storage implementation -->
    <init-param>
        <param-name>storage</param-name>
        <param-value>de.laures.cewolf.storage.
                     TransientSessionStorage</param-value>
    </init-param>
    <!-- sets overlib.js location relative to webapp -->
    <init-param>
        <param-name>overliburl</param-name>
        <param-value>etc/overlib.js</param-value>
    </init-param>
</servlet>


<servlet-mapping>
    <servlet-name>CewolfServlet</servlet-name>
    <url-pattern>/cewolf/*</url-pattern>
</servlet-mapping>

The Cewolf distribution includes a JavaScript library (overlib.js) in its etc/ folder. The two most popular browsers are Internet Explorer and Mozilla. This script is used to render tooltips in the Mozilla browser as its mechanism for doing this differs from the former. Add the etc folder to the root of your Web application.

Cewolf, by default, stores all images in a user's HttpSession object. The TransientSessionStorage class, specified in the servlet's storage initialization parameter, takes care of this. Another option is to store the image on the file system. To do this, replace TransientSessionStorage with the FileStorage class (of the same package) in the param-value tag of the storage parameter. All chart images will be created as PNG type images (though other image types are possible). PNG files are high-quality images supported by most Web browsers.

Now that the wiring of your application is complete, you need to code your Java class and JSP to generate the data and display the data, respectively. First, consider the Java file. As mentioned earlier, Cewolf defines a DatasetProducer interface that defines methods used to provide data to JFreeChart. Here is the DatasetProducer interface:

Object produceDataset(Map params) Method that returns the data (as a Dataset) for rendering. Typically, you would access your database here, either directly or indirectly, to provide this data.
boolean hasExpired(Map params, Date since) This method can be used to interrogate the last time the data was produced and determine whether produceData needs to be invoked again.
String getProducerId() Method that uniquely identifies a type of DatasetProducer.

The produceDataset method is the key method in this group because it provides the necessary data for your charts. In this example, you are generating a simple pie chart that will display the number of employees hired for each department. You will access the database to run a query against your emp and dept tables. Look at the code for EmployeesByDept.java. As you can see, it implements DatasetProducer. For your simple example, you return false from hasExpired, meaning, as is, the Dataset will never expire. In a real application, you would supply the logic to determine this.

EmployeesByDept accesses a database, with help from a utility class, and returns an instance of DefaultPieDataset, the default Dataset implementation for producing a pie chart. The query executed depends on the existence of an input parameter. You'll look at that in a bit. For the time being, you are not passing a parameter, so the SQL query it runs is as follows:

SELECT COUNT(emp_id), dept.name
   FROM emp, dept
   WHERE emp.dept_id = dept.dept_id;

With the head count it obtains from each series (each department, in this case, is one series of data), the chart will be created by JFreeChart and displayed at the time your JSP file is requested. View piechart.jsp to see how Cewolf tags are used to accomplish this.

In piechart.jsp, there are two parent tags at work: chart and img. The chart tag is responsible for overall chart configuration. Included are tags and attributes for specifying they type of chart to be rendered, a title for the chart, background color, and more. The most important piece of information within the chart tag is recorded in a nested tag:

<cewolf:data>
     <cewolf:producer id="pieChartView" />
</cewolf:data>

The data tag specifies the Dataset to be used when rendering the chart. Object pieChartView is an instance of EmployeesByDept that you declare at the top of the page:

<jsp:useBean id="pieChartView" class="examples.EmployeesByDept"/>

The other parent tag just below chart is named img. This tag specifies how the chart is to be displayed. It contains attributes to control the graphic: height, width, border, and so on. The chart and img tags are linked to one another through the chart 'id' attribute and the img 'chartid' attribute. In this case, you've given your chart an id of 'pieExample'. These tag definitions produce the following pie chart image:

This is a good start, but you can improve upon this example. Many charts like to include text (in addition to the text inside the legend) to describe each data series. You have the ability to add text to the image itself. Another capability you have with JFreeChart and Cewolf is to include text as a tool tip. Now, add a tool tip that displays when a user's mouse hovers over a particular series on the image. To accomplish this, you need to obtain an instance of type PieToolTipGenerator that implements a method called generateToolTip. The easiest way to do this is to add an inner class to EmployeesByDept.java. Here is the updated Java file, in which you added the following code:

  /**Inner Class to generate tool tips for data.*/
  PieToolTipGenerator pieTG = new PieToolTipGenerator() {
    public String generateToolTip(PieDataset dataset,
                                  Comparable section, int index) {
        return String.valueOf(dataset.getValue(index) +
                              " employees total" );
    }
  };
  public PieToolTipGenerator getPieTG() {
     return this.pieTG;
  }

The new and improved piechart.jsp includes a second pie chart with many enhancements. Near the top of the page, you obtain an instance of your PieToolTipGenerator:

<% pageContext.setAttribute("pieChartViewToolTips",
                            pieChartView.getPieTG()); %>

An additional tag, map, needs to be included within the img tag in order to use tool tips:

<cewolf:map tooltipgeneratorid="pieChartViewToolTips"/>

While adding tool tips to this second pie chart, I modified the JSP tags to include additional features. The chart image is now of type 'pie3d' and the chart's legend is now generated separately from the chart. More importantly, you now pass an input parameter, inputYear, using the producer tag (nested within the chart tag). The ability to parameterize a chart is the key to providing users with dynamic charts. In a typical application, these parameter values might be input from an HTML form that a user submits to customize his or her chart:

<cewolf:producer id="pieChartView" >
  <cewolf:param name="year" value="<%=(Serializable)inputYear%>"/>
</cewolf:producer>

In EmployeesByDept, you check for an input parameter. If a parameter is supplied, you filter our data by year. Figure 1 shows the JSP page displaying both pie charts. Note that the second chart displays the tool tip text '6 employees total' over the series that represents HR employees. Here's the 3-dimensional pie chart graphic (without a legend, which was a separate image in this example):

Figure 1. 3-D Pie Chart

More Advanced Charts

You have thus far seen examples of pie charts. More complex types of charts can show one or more series within one or more categories. JFreeChart's CategoryDataset interface represents data containing series grouped within categories.

I have created a second Java class in the file EmployeesByDeptAndQtr.java. Like the previous class, EmployeesByDeptAndQtr also implements Cewolf's DatasetProducer interface. As its name implies, this class executes a database query that will display head counts for each department, categorized by the quarter of the employee's hire date. Here's the query sent to the database:

SELECT COUNT(emp_id), QUARTER(emp.hire_date) quarter, dept.name
   FROM emp, dept
   WHERE emp.dept_id = dept.dept_id
   GROUP BY dept.name,QUARTER(emp.hire_date);

With the returned DefaultCategoryDataset, you can create a number of chart types. Each of these charts consists of an x and a y plot. The x plot plots data horizontally; the y plot plots data vertically. Depending on the type of chart used, one plot will display value points, the other categories. As with the pie chart, the data series will be color coded and included in a chart legend. You will display three of them: a horizontal bar, a vertical bar, and a line chart. The bar charts differ in how they map their x and y coordinates. A line chart displays a different type of graphic. It identifies distinct data points, connected by a line that runs across the chart.

The content of categorychart.jsp should look familiar as it uses many of the same constructs as piechart.jsp. It declares a DatasetProducer instance, and then lists a set of JSP tags to manage the charts. This JSP file contains separate tags for chart types 'horizontalBar3D', 'verticalBar3D', and 'line'. All three charts represent the same CategoryDataset (provided by the DatasetProducer). Only two new tag attributes are introduced: xaxislabel and yaxislabel. Figure 2 shows the resulting Web page. Below are the three chart images produced in greater detail:





Figure 2. Various Category Charts

Conclusion

This article's intended purpose was to provide you with an introduction to creating graphic charts using JFreeChart and Cewolf. I strongly encourage you to visit each site and explore the additional chart types and chart enhancements that are available to you. Extensive documentation of JFreeChart is available for purchase. Both projects have community forums to help answer questions. Also, both sites offer on-line Javadocs that document source code. By combining JFreeChart and Cewolf, J2EE developers have a useful, and easy to use, tool that can be used to satisfy user's data analysis requirements.

About the Author

Michael Klaene is a Senior Consultant with Sogeti LLC. He has spent over 7 years in IT, specializing in J2EE and Oracle analysis and development.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date