Creating Dynamic Charts With JFreeChart

JFreeChart is an open source charting library implemented in Java. It provides the capability to dynamically create sophisticated charts and incorporate them into Java applications. The library supports a variety of chart types, including pie, bar, line, area and other types of charts. It also provides support for more complex charts, such as Gantt charts, candlestick charts, stacked charts and polar charts.

In this article, I'll cover the basic steps involved in creating charts using the JFreeChart library, with an emphasis on how to incorporate them into web sites. Simply creating a chart image using the library is not enough. My goal is to show how charts can be produced as an integral part of a web page, emdedded directly within the page content area and surrounded by all the normal aspects of a functional web site, such as menus, banners, etc.

A simple pie chart generated by JFreeChart is shown below:

Pie Chart, generated with JFreeChart

To accomplish the goal of embedding charts into a web page, we're going to take a two-step approach. First, we'll concentrate on implementing a Java servlet that can generate a chart image using JFreeChart. Second, we'll show how that image can be incorporated into a web page. If you're unfamiliar with creating servlets, you can review my previous article on Java Servlets.

A Charting Servlet

Servlets are created by extending the javax.servlet.HttpServlet class, and providing an implementation for the appropriate methods. As shown in Listing 1, this servlet implements the doGet method, which in turn calls the doTestPieChart method.

Listing 1: ChartServlet Source Code

package keenertech.metrics.servlets;

import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.Color;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;

public class ChartServlet extends HttpServlet
{

   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response)
   throws IOException, ServletException
   {
      doTestPieChart(request, response);
   } // End Method

   /**
    * This method creates a test pie chart using internally
    * generated data. This method can be used to test the
    * basic JFreeChart setup and the basic servlet
    * configuration.
    *
    * @param   request   The HttpServletRequest request,
    *                    which contains lots of useful
    *                    information about the request.
    *
    * @param   response  The HttpServletResponse object,
    *                    which allows the output being sent
    *                    back to be tailored.
    */

   protected void doTestPieChart(HttpServletRequest request, 
                                 HttpServletResponse response)
      throws IOException, ServletException
   {
      OutputStream out = response.getOutputStream();

      try
      {
         DefaultPieDataset dataset = new DefaultPieDataset();
        	
         dataset.setValue("Graphic Novels", 192);
         dataset.setValue("History", 125);
         dataset.setValue("Military Fiction", 236); 
         dataset.setValue("Mystery", 547); 
         dataset.setValue("Performing Arts", 210);
         dataset.setValue("Science, Non-Fiction", 70);
         dataset.setValue("Science Fiction", 989); 
       	    	    
         JFreeChart chart = ChartFactory.createPieChart(
            "Books by Type",  // Title
            dataset,          // Data
            true,             // Yes, display the legend
            false,            // No, don't display tooltips
            false             // No, no URLs
         );
         chart.setBackgroundPaint(Color.white);
            
         response.setContentType("image/png");
         ChartUtilities.writeChartAsPNG(out, chart, 400, 300);
      }
      catch (Exception e)
      {
         System.out.println(e.toString());
      }
      finally
      {
         out.close();
      }

   } // End Method

} // End Class

The bulk of the work is done in the doTestPieChart method. I've set it up this way so that, theoretically, this servlet could be set up in the future to generate different types of charts based on incoming arguments. Each type of chart could be generated by a separate method.

Creating a chart with JFreeChart follows a simple sequence of steps:

  1. Create a Dataset object containing the data that's required for the chart. JFreeChart conveniently supports a variety of Dataset classes to support the different types of charts.

  2. Call the appropriate method in the ChartFactory class to generate the desired type of chart, passing in the Dataset and any required arguments. This call will generate an instance of the JFreeChart class, which is essentially a representation of your chart.

  3. Call various methods of the JFreeChart class as needed to customize the chart.

  4. Output the chart in some useful fashion, possibly by saving an image to a file or sending the image to a browser via an output stream.

In Listing 1, a DefaultPieDataset object is created and then populated with data. The DefaultPieDataset object is passed as an argument to the createPieChart method of the ChartFactory class.

Then some customization needs to be done. By default, the chart will have a gray background (which is ugly, trust me). So, the setBackgroundPaint method is called to set the background to white. As you might expect, there are also numerous other methods that can be used to customize other aspects of the chart.

But where is "Color.white" defined? In this instance, JFreeChart is taking advantage of colors that have already been defined in java.awt.Color. AWT stands for the Abstract Window Toolkit, which is a library of user interface components and utilities that's been around for over a decade. Except for its convenient color definitions for some of the more commonly used colors, AWT isn't otherwise pertinent for generating charts targeted for web pages.

The code below retrieves a reference to the output stream of the response object. We can use that output stream to send an image back to the browser.

     OutputStream out = response.getOutputStream();

Now comes the tricky part. We've generated the chart object, but we need to create an image of the chart and send it back as part of the response. First, the setContentType method is used to inform the browser that we're sending back an image, not an HTML file. Next, we use the writeChartAsPNG method from the ChartUtilities class to write a PNG image of the chart to the output stream of the response, specifying a width of 400 and a height of 300.

     response.setContentType("image/png");
     ChartUtilities.writeChartAsPNG(out, chart, 400, 300);

When deployed, this servlet can be accessed using a URL like:

http://www.yourwebsite.com/servlet/ChartServlet

The servlet will generate the JFreeChart chart displayed earlier in this article. But it doesn't embed the chart image into the content of a full-featured web page. That will be the next step.

Embedding a Chart

It turns out that embedding a JFreeChart chart within a web page is almost absurdly easy, as shown in Listing 2. To embed a chart, use a regular HTML "img" tag, with the "src" attribute of the tag set to the URL of the charting servlet.

Listing 2: HTML Page With Embedded Chart

<html>
<head>
   <title>Test Chart</title>
</head>
<body>

<div align=center>
<img src="/servlet/ChartServlet" width=400 height=300 border=0>
</div>

</body>
</html>

The charting servlet will generate the chart, sending the image of the chart back to the user's browser. The chart will typically appear a second or so after the rest of the web page appears.

Simple. In fact, look closely at the code in Listing 2. That's straight HTML. Your web page doesn't have to be in any particular language in order to make use of an embedded chart; it just has to have access to the charting servlet.

This can be useful in creating hybrid solutions. A client may have a vital web site implemented in PHP, but that PHP site can still use charts created by a Java-based servlet as long as the servlet is accessible to the site.

This also points out a potential security issue. Anybody that can reference the servlet can generate a chart. It may be desirable to place a security check on such requests before generating a chart and sending it back to the requester. This is easy to do, since the servlet has full access to the request object.

A Multi-Chart Servlet

It would be painful, though feasible, to create a different servlet for every chart that we wanted to implement. Listing 3 shows a revised version of the doGet method that I've used to create a servlet that can generate multiple types of charts depending on the needs of the user.

Listing 3: The Revised doGet Method

   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response)
   throws IOException, ServletException
   {
      String strChartType = request.getParameter("type");
      
      if (strChartType != null)
      {
         if (strChartType.equals("Test1"))
         {
            doTestPieChart(request, response);
         }

         if (strChartType.equals("Test2"))
         {
            doTestBarChart(request, response);
         }

      }
   } // End Method

Now you can see why I separated the generation of my original pie chart into a separate method. In the code above, the doGet method checks the "type" parameter to determine what type of chart to generate. In this solution, it is expected that the "type" parameter would be passed as a URL parameter.

Also, in real life, you'd probably want to add some error handling to this solution, perhaps passing back a graphic that says "Unknown Chart Type" if a bad chart type was provided.

Conclusion

The JFreeChart library provides an effective way to create sophisticated and eye-catching charts dynamically. While I've illustrated how JFreeChart can be used to embed graphics into web sites, it should be equally obvious that JFreeChart can also be used effectively in applets and Java applications.

JFreeChart is a highly functional, mature, and flexible technology that can be easily incorporated into real-world applications. Even better, as an open source technology, you can "take it with you" wherever you go.

References

There are a number of relevant references available online concerning JFreeChart:

  • JFreeChart Home Page
    http://www.jfree.org/jfreechart
    The Home page for the JFreeChart application; the web site is managed by JFreeChart's original creator, David Gilbert.

  • Generated API Documentation
    http://www.jfree.org/jfreechart/api/gjdoc/index.html
    Documentation for the JFreeChart API, generated directly from the comments contained in the source files. This is invaluable if you're doing any serious customization of charts.

  • Visualize Your Oracle Database Data with JFreeChart
    http://www.oracle.com/technology/pub/articles/marx-jchart.html
    A great article, released Sept 2007, that illustrates the creation of several different types of charts using JFreeChart. Also discusses producing charts using database queries, XML, etc.



Comments

David Keener By rob on Wednesday, June 30, 2010 at 10:07 AM EST

I am using a servlet to produce JFreeCharts.

Your example and that of JFreeChart's is simple and easy to follow. However, why do I have to write the resulting image to a file on the server and then return to the client and make the client retrieve a disk file from the server (via the URL)?

The ChartUtilities has a method that produces the image as a java.awt.imagel.BufferedImage. I would like to return this image directly as a serializable object. This would allow a chart to be produced with one call to the server.

Is their a way to do that? Isn't the performance hit of writing the image to disk, returning, making a request for the URL, and retrieving the image from the disk again about 1000 times the cost of simply returning a BufferedImage?




David Keener By dkeener on Wednesday, June 30, 2010 at 10:10 AM EST

Hi Rob. You just need to look at the code in my online article a little more closely. I've already solved that problem, and without having to resort to a BufferedImage.

The code writes the image to an output stream, i.e. - the response itself. The basic steps are:

1. Get an instance of the output stream for the response.
2. Use JFreeChart to create the chart object.
3. Set the mime type of the response.
4. Write the chart image to the output stream.

Here's the relevant code, with a few of the intervening bits removed for clarity (but the full code is in the article):

OutputStream out = response.getOutputStream(); // Do JFreeChart magic here to create the chart response.setContentType("image/png"); ChartUtilities.writeChartAsPNG(out, chart, 400, 300);

So, you see, the code is not writing the image out to a file, it's writing it out AS the response that is going to be sent back. The "setContentType" method sets the mime type of the response so that the browser will properly interpret what the response is.

Otherwise, yes, I agree, the performance hit for writing out an actual file would be painful. Plus the necessity for cleaning up graphic files periodically.

That's why I'd like to think that my JFreeChart article is fairly decent...it's one of the few articles on the web that gives you a real production-caliber solution to producing an embedded chart using JFreeChart.

I hope this helps you out....




David Keener By rob on Wednesday, June 30, 2010 at 10:13 AM EST

Yes. Congratulations. Yours is different in that the ChartUtilities is writing to the response stream (inside the method there is a BufferedImage though).

My problem is a little different. I am accessing the servlet from GWT (Google's Java AJAX). It makes all requests as a HTTP request for specific data and receives things back as serialized objects (Its own version of serialization). This means that I never see the response as a stream from the servlet.

However, this gives me some ideas on how I might do it. I will try to take the outputstream and turn it into an html object (serializable).

Thanks for your guidance. If I can return the favor, just ask.




David Keener By ambika nair on Wednesday, July 21, 2010 at 07:28 PM EST

Hi, Can I use JFree charts with dynamic datas? I need to generate charts in servlets,but my values are dynamic. Will this work?


David Keener By dkeener on Thursday, July 22, 2010 at 11:21 AM EST

Hi Ambika. Yes, you can use JFreeChart with dynamic data. I only used static data in the article because I wanted to focus on what was necessary to use the JFreeChart library.

The key aspect here is creating the populated DataSet object that JFreeChart expects. Once you've learning the basics of interacting with JFreeChart, the real work in creating a new chart is assembling the data that's required and populating one of JFreeCharts DataSet objects. The information about the library collection that I hard-coded in the code samples could just as easily come from a database.




David Keener By Varun on Friday, November 26, 2010 at 10:12 AM EST

Hi! David, I am able to get the image using the method you provided above. It really helped me a lot. But whenever the image is generating on the web page, all other components are not visible. I mean the image is not embedding into the web page it showing only image in the web page. Can you please suggest me a solution. I am need of it. Thank you, David.


David Keener By MikeJ on Monday, February 14, 2011 at 03:00 PM EST

Thanks David! This was described/presented in a very straight forward manner allowing beginners to start using the jfreechart classes within a short period of time. Thanks for taking the time to provide the notes. If one servlet it handling all the requests, would it be more beneficial to generate multiple servlets for various "chart types" should the website have many vistors all utilizing the services at the same time? What's your view on a site that would require supporting 100+ users all making requests to the jfreechart via servlets at the same time?


David Keener By dkeener on Friday, February 25, 2011 at 07:13 AM EST

One web server (and servlet) on a reasonable platform should be able to support 100+ simultaneous users (assuming that your chart generation tasking isn't over-the-top in terms of CPU intensity. In practice, you'd have to have a LOT of users in order to get 100+ simultaneous requests.

In practice, this is more of a code organization issue. Our goal is to write useful, effective and maintainable code. If you only have 5 chart types, throw 'em all in the same servlet. If you've got a 100, it's probably time to organize the code a little better, e.g. - with similar charts in the same class, and maybe with a base class that provides common functionality, etc.




David Keener By dkeener on Friday, February 25, 2011 at 07:17 AM EST

To Varun: There must have been something wrong with your HTML, because the technique shown for embedding the servlet-generated image has worked everywhere that I've tried (even in all the various flavors of IE).


David Keener By Peng Jia on Wednesday, March 30, 2011 at 11:08 AM EST

Hi David,

I am working on a web app request me to update jfreechart on jsp page dynamically. I referred to your examples and they gave me great help. However, I still have a problem to refresh the chart.

In my app, I use ajax to refresh the page every second and at the end of my jsp, I use

   <form action="" method="get">
      <IMG src="GraphGen" alt="free chart">
   </form>

to redirect to servlet named GraphGen.java to response to HttpServletRequest.

This is my problem: every time the page is loaded I can see the chart as a png image, but the image is not refreshed. I tried to make break point at:

   <IMG src="GraphGen" alt="free chart">

And it seems to me that line of code is traversed but there is no HttpServletRequest since the doGet, doPost code is not executed.

Please help me on this one.

Thanks!

The following is the code snippet that I put in my jsp:

<body id="ReloadThis">
   <script type="text/javascript">
      function Ajax(){
         var xmlHttp;
         try{
            xmlHttp=new XMLHttpRequest();// Firefox, Opera 8+, etc
         }
         catch (e){
            try{
               xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); // IE
            }
            catch (e){
               try{
                  xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
               }
               catch (e){
                  return false;
               }
         }
      }

   xmlHttp.onreadystatechange=function(){
      if(xmlHttp.readyState==4){
         document.getElementById('ReloadThis').innerHTML=xmlHttp.responseText;
         setTimeout('Ajax()',1000);
      }
   }

      xmlHttp.open("GET","http://localhost:8080/Sample/hello.htm",true);
         xmlHttp.send(null);
      }

      window.onload=function(){
         setTimeout('Ajax()',1000);
      }
   </script>

<h1>Chamber Information: 10.192.70.213</h1>

<form action="" method="post">
<br/>
<table style = "border: 6px outset;">
   <tr>
      <td style = "background-color: black;">
         <p class = "big" style = "color: cyan;">
         <!-- JSP expression to insert date/time -->
         <%= new java.util.Date() %>
         </p>
      </td>
      <td style = "background-color: black;">
         <p class = "big" style = "color: cyan;">
         <!-- JSP expression to insert date/time -->
         <%
         int temp = connect.getStatus().getTempActual();
         String tempStr = temp/100 + "." + Math.abs(temp%100) + '\u2103';
         %<
         Controller Temperature:          <%= tempStr%>
         </p>
      </td>
   </tr>
</table>
<br/>
</form>
<form action="" method="get">
   <IMG src="GraphGen" alt="free chart">
</form>




David Keener By ishan on Tuesday, August 16, 2011 at 03:20 AM EST

Hi,

How can I refresh my graphs?

As in once the graph is generated and then I try to generate graphs with different values it still displays the same graph unless I press F5 on the page...

Can there be some solution for this problem? I am using the Struts framework...




David Keener By Yusril on Friday, July 06, 2012 at 06:43 AM EST

Thanks sir,your article is very help full to me :D


David Keener By Priya on Saturday, July 28, 2012 at 06:04 PM EST

Great post.If we use Jfreechart to create pie charts in Servlet, then it is wise to use a jsp page or html to render the pie chart as explained in this post. Since servlets are static by nature, you need to reload them periodically to have your pie chart updated. Just refresh the jsp or html page at regular intervals. Take a look at this tutorial, http://programmingfree.blogspot.in/2012/07/jfreechart-create-auto-refreshing-pie.html it updates pie chart periodically by refreshing jsp page using response.setIntHeader("Refresh",5).


Leave a Comment

Comments are moderated and will not appear on the site until reviewed.

(not displayed)