Saturday, April 5, 2008

Displaying Dynamically Generated JFreeChart in JSR 168 Struts Portlet


Getting Started


The sample portal application complies with JSR 168 Specification and uses Struts framework. Being a basic struts application, it has an index.jsp, action, form and a result.jsp. Pie chart is displayed in result.jsp with the data provided by user in index.jsp. A servlet is used to generate Pie Chart using JFreeChart and the generated image is returned in servlet’s outputstream so as to avoid the overhead of saving the image anywhere else in the application.

For generating and displaying JFreeCharts we need to include certain libraries which are available in JFreeChart web page. Place these jar files in your WEB-INF/lib folder:



  • jfreechart-*.jar

  • jcommon-*.jar


Note: Include jfreechart-*.jar, jcommon-*.jar in your java build path. Also, the class files must be put in the correct folder structure under our Portal application's /WEB-INF/classes directory.


Sequence Diagram


piechart-sequence

Figure 1: Sequence diagram for the sample JSR 168 Struts Portlet Application displaying Pie Chart

Steps in displaying dynamically generated JFreeChart in JSR 168 Portlet


Role of index.jsp, action and form class

Index.jsp is used to pass user specific data, in this example it is number of persons in various IBUs. Input fields are properly validated and once user submits the page, Action is invoked which stores the data from Form to PortletSession within Application Scope so that the helper Servlet can get the data. Action then forwards the control to result.jsp where the actual output is displayed.


Setting Pie Chart Data for PieDataSet in PortletSession

We need to pass data from ActionClass within Portlet context to the servlet in Application context. Normally, we cannot share data in Session even between Portlets. To achieve this sharing between a portlet and a servlet we use Application Scope when setting data in session. Following code snippet taken from action class serves this purpose.



ArrayList pieChartData = new ArrayList( );
/* Adding data used to generate Pie Chart into temporary arraylist */
pieChartData.add("No. of Employees in CMD");
pieChartData.add(Integer.toString(actionForm.getValueOfCMD( )));
pieChartData.add("No. of Employees in I");
pieChartData.add(Integer.toString(actionForm.getValueOfI( )));
pieChartData.add("No. of Employees in NAD");
pieChartData.add(Integer.toString(actionForm.getValueOfNAD( )));
pieChartData.add("No. of Employees in MEA");
pieChartData.add(Integer.toString(actionForm.getValueOfMEA( )));
pieChartData.add("No. of Employees in Other BUs");
pieChartData.add(Integer.toString(actionForm.getValueOfOthers( )));
/* * Storing the arraylist in session so that servlet rendering
* pie chart image can use it */

PortletSession session = request.getPortletSession( );
session.setAttribute("PieChartData",pieChartData,PortletSession.APPLICATION_SCOPE);

Creating a Servlet that generates JFreeChart PieChart with Data from PortletSession

In this application, HttpServlet’s doGet() method is used for the following purposes:-


  1. To retrieve data from Session

  2. To generate Pie Chart from the retrieved data and

  3. To write the generated chart in Servlet’s OutputStream


HttpSession object is used to retrieve data from session as given below



HttpSession session = request.getSession( );
ArrayList pieChartData = null;
pieChartData = (ArrayList)session.getAttribute("PieChartData");

JFreeChart is providing a bunch of APIs to create charts and customize them. Following block of code depicts the creation of sample pie chart with little customization.



/* Creating a piedataset */
final DefaultPieDataset data = new DefaultPieDataset( );
/* Storing the pie chart data in pie dataset */
for (int iIndex = 0; iIndex < pieChartData.size( ); iIndex++) {
data.setValue(pieChartData.get(iIndex).toString( ),Integer.parseInt(pieChartData.get(iIndex + 1).toString( ));
iIndex++;
}
/* Create a pie chart */
final boolean withLegend = true;
final JFreeChart chart = ChartFactory.createPieChart("Employee Survey",data, withLegend, true, true);

Returning Generated PieChart in Servlet’s OutputStream

Using JFreeChart API the chart is written to the OutputStream of the servlet as mentioned below.



OutputStream out = response.getOutputStream( );
response.setContentType("image/png");
ChartUtilities.writeChartAsPNG(out, chart, 200,200);


// Best Practice:
finally {
out.close( );
}

Creating a Servlet Mapping in web.xml

Once you are done with the Servlet the next and most basic thing one is the Servlet Mapping entry in web.xml as mentioned below.



<servlet>
<servlet-name>DrawPieChart</servlet-name>
<display-name>DrawPieChart</display-name>
<servlet-class>jsr168dynamicchartdisplay.helper.DrawPieChartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DrawPieChart</servlet-name>
<url-pattern>/DrawPieChart</url-pattern>
</servlet-mapping>

Getting the output in Result.jsp

Once the textual data are displayed in the result.jsp, PieChart Helper Servlet is hit through an <img> mark-up element from result.jsp which in turn returns the image in its OutputStream.



<IMG src = <%=response.encodeURL(request.getContextPath( )+ "/DrawPieChart")%> border = "0">

Screen Shots
piechart-indexpage1

Figure 2: Index Page showing input fields

piechart-resultpage2

Figure 3: Result Page showing Pie Chart along with other textual data

References


http://www.jfree.org/jfreechart/

http://www.object-refinery.com/jfreechart/index.html

Download WAR file (Without JARs) from here.

8 comments:

Irina said...

I have get JFreeChart for developers. I want to develop myself JFreeChart portlet in JSR 286. I have a problem to start in JSR 286.

Have you anything for me with souce codes to buy ?

Irina

Irina said...

JFreeChart Portlet in JSR 286 with source codes.

Irina
(irinakvi@hotmail.com)

Balaji Natarajan said...

Think the same code can be used in JSR 286 portlet architecture too. If you look at the sequence diagram, well you can apply this irrespective of JSRs. Let me know if you need any clarifications, mail to balajeenatarajan at gmail dot com.
thanks

gem said...

Hi ,
I am using Liferay Portal Server for my portal development. I need to display a chart on my jsp and have followed your example.

However I get an Invalid Path requested error while displaying the chart.

How do I resolve this?

Any Help would be appreciated.

Thanks
Gavin

gem said...

Hi ,
I am using Liferay Portal Server for my portal development. I need to display a chart on my jsp and have followed your example.

However I get an Invalid Path requested error while displaying the chart.

How do I resolve this?

Any Help would be appreciated.

Thanks
Gavin

Balaji Natarajan said...

Hi Gavin,
Did you give the servlet mapping correctly in web.xml? can you post your jsp code as well as the web.xml configuration snippet?

gem said...

Hi ,
I am not able to post the JSP code ...how do I attach the file?
Thanks

Gavin

Balaji Natarajan said...

Gavin, Pls send it to infybalaji at gmail dot com