Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Creating Dynamically Generated Charts in Portlets

 
By Sandeep Soni and Marina Sum, June 6, 2006  

A picture is worth a thousand words, as they say. Indeed, graphics—rather than HTML tables—are often a better choice to represent structured data on Web pages. However, with conventional imaging tools, such as Photoshop, you cannot effectively generate images on the fly from data that changes frequently. What you need is a way to create images programmatically—and that's where JFreeChart, an open-source graphing and charting library, comes in handy.

This article shows you, through a sample application, how to create a simple portlet that complies with Java Specification Request (JSR) 168 and that renders a time-series chart with the JFreeChart library.

Contents
 
Project Setup
portlet.xml File
Event Flow and Sequence Diagram
doView() Method
Conclusion
References

 
Project Setup

First, set up a standard portlet or Web application project in your favorite IDE, such as Sun Java Studio Creator. As an example, see the article, Creating Portlets in Sun Java Studio Creator 2.

Download the source code for the sample application. Here, the main portlet class, ChartPortlet, supports the view mode in which the portlet shows a dynamically generated chart.

portlet.xml File

Next, create the portlet.xml file, as follows. Note the items of interest that are shown in bold and the explanations in the comments.

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app version="1.0"
    xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
    <portlet>
    <description xml:lang="EN">A simple chart portlet</description>
    <portlet-name>ChartPortlet</portlet-name>
    <display-name xml:lang="EN">ChartPortlet</display-name>
    <!-- This is the main portlet class, which will render the view of the
portlet -->
    <portlet-class>
        com.sun.portal.sample.portlets.ChartPortlet
    </portlet-class>

    <expiration-cache>-1</expiration-cache>
    <!-- We mark this portlet to support the view mode by default -->
    <supports>
        <mime-type>text/html</mime-type>
	<portlet-mode>view</portlet-mode>
    </supports>
    <supported-locale>en</supported-locale>
    <resource-bundle>portlet</resource-bundle>

    <portlet-info>
        <title>ChartPortlet</title>
	<short-title>ChartPortlet</short-title>
	<keywords>ChartPortlet</keywords>
    </portlet-info>
    </portlet>

</portlet-app>
 
Event Flow and Sequence Diagram

Now define the portlet's operations. The JFreeChart library supports numerous graphics: bar charts, pie charts, line charts, time-series charts, scatter plots, histograms, simple Gantt charts, Pareto charts, bubble plots, dials, thermometers, and others. For this sample project, plot a time-series chart, which is basically a line chart of one or more series of data plotted against a time axis.

Figure 1 illustrates the sequence of events that render the HTML page that contains the dynamically generated chart.

Figure 1: Sequence of Events
Figure 1: Sequence of Events
 

Now follow the chain of events. ChartPortlet resides on a portal server, such as Sun Java System Portal Server. When the portal server renders the complete view, it calls the portlet's doView() method. In that method, you perform the following:

  1. Connect to the data source to find out if new data is available and, if so, fetch them. In the sample portlet, you generate the data from a private, hard-coded method of the portlet. Real-life scenarios would probably query a data source and determine if there is new data to be plotted.

  2. Call the API of the JFreeChart library to generate a time-series chart.

  3. Use the Java 2D API from the javax.imageio package to save the chart as an image in the Web application's /tempImages directory with a time-stamped name.

  4. Generate and save a URL for the image as a portlet request parameter named CHART_PORTLET_IMAGE_URL.

  5. Obtain a request dispatcher to the /index.jsp file in the Web application and forward the request to that index page.

Following is the content of the /index.jsp file.

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineobjects />
<%--
    The CHART_PORTLET_IMAGE_URL variable would have been set by the portlet to
the image generated for this request
--%>
<% String imageURL =
(String)renderRequest.getAttribute("CHART_PORTLET_IMAGE_URL"); %>
<img src="<%=imageURL %>"/>
 
doView() Method

Now that you can see how the whole process works, look at the doView() method in ChartPortlet, as follows. The comments of interest are shown in bold.

public void doView(RenderRequest portletRequest, RenderResponse portletResponse)
throws PortletException, IOException {
    // Set the content type to text/html

    portletResponse.setContentType("text/html");

    PortletContext context = getPortletContext();
    JFreeChart chart = ChartFactory.createTimeSeriesChart("Bug Counts And Trends", // title
	"Months", // X-axis label
	"Number of Bugs", // Y-axis label
	createDataset(), // Get Data.
	true, // Create legend?
	true, // Generate tooltips?
	false // Generate URLs?
	);

    BufferedImage bi = chart.createBufferedImage(300, 300);

    // Generate a name for the image saved under /tempImages subdirectory of this
    //Web application.
    String relativeImagePath = "/tempImages/" + System.currentTimeMillis() + ".jpg";
    String destfile = context.getRealPath(relativeImagePath);

    // Call the save method to save the image to a file.
    save(bi, destfile);

    // Set the URL of the generated image as a portlet request attribute and
    // forward the request to the index.jsp file that displays the image.
    portletRequest.setAttribute("CHART_PORTLET_IMAGE_URL", 
                                portletRequest.getContextPath() + relativeImagePath);
    PortletRequestDispatcher rd = context.getRequestDispatcher("/index.jsp");
    rd.include(portletRequest, portletResponse);
}

private void save(BufferedImage bi, String destFilename) {
    try {
        // Get Writer and set compression
	Iterator iter = ImageIO.getImageWritersByFormatName("JPG");
	if (iter.hasNext()) {
	    ImageWriter writer = (ImageWriter) iter.next();
	    ImageWriteParam iwp = writer.getDefaultWriteParam();
	    iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
   	    iwp.setCompressionQuality(0.95f);
     	    MemoryCacheImageOutputStream mos = 
	        new MemoryCacheImageOutputStream(new FileOutputStream(destFilename));
	    writer.setOutput(mos);
	    IIOImage image = new IIOImage(bi, null, null);
	    writer.write(null, image, iwp);
	}
    } catch (Exception e) {
	e.printStackTrace();
    }
}
 
Conclusion

Plotting dynamic graphics with JFreeChart on Sun Java System Portal Server is a breeze! Give it a try.

References
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.
The Portal Post
 
Sandeep SoniSandeep Soni, a staff engineer at Sun's India Engineering Center in Bangalore, joined Sun in February 2004. He has been serving as the technical lead for Sun Java System Secure Remote Access. Currently, Sandeep focuses on evangelizing the future direction of Sun Java System Portal Server and developing its new capabilities.
 
Marina SumMarina Sum is a staff writer for Sun Developer Network. She has been writing for Sun since 1989, mostly in the technical arena. Marina blogs on Sun products, technologies, events, and publications.