jueves, 17 de julio de 2008

Agregar gráficas a paginas JSP usando JFreeCharts


JFreeCharts es una librería (open source) para java, para generar gráficas de forma practica y sencilla. La librería JFreeCharts fue diseñada para poderse usar tanto en aplicaciones web como de escritorio.

A continuación presentamos una forma de utilizar JFreeCharts para generar gráficas que serán incluidas en páginas JSP.

Para poder mostrar las gráficas en la página es necesario que se realicen dos HTTP Request esto es debido a la forma en que los Browsers parsean los HTML. El primer HTTP Request es el que genera el contenido de la página y el segundo es el que genera la imagen.

Ahora JSP solo puede enviar texto, así que es necesario crear un servlet para poder enviar la imagen.

Consideremos el siguiente flujo:

- Primero tenemos una clase java (En el caso de struts un action) que se encarga de cargar todos los datos necesarios para la generación de la JSP. En esta clase se cargan en session los datos que serán mostrados en las gráficas.

- Una vez cargados los datos, se genera la JSP. la cual instancia un constructor de gráficas.

- Por ultimo la JSP invoca al servlet para obtener la imagen.

Codigo:

Action: Graficar.java
En esta clase se cargan en session los datos que serán gráficados.


package com.ui.actions;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.data.general.DefaultPieDataset;

import com.ui.actions.BaseAction;



public class Graficar extends BaseAction {



public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response) throws Exception {

ActionForward forward=null;

crearImagenes(request);

forward = mapping.findForward("success");

return forward;

}

private void crearImagenes(HttpServletRequest request) {

DefaultPieDataset pieDataset = new DefaultPieDataset();

pieDataset.setValue( "US 44.3%", 44.3 );

pieDataset.setValue( "France", 12.1 );

pieDataset.setValue( "Japan", 10.0 );

pieDataset.setValue( "UK", 8.4 );

pieDataset.setValue( "Spain", 3.4 );

pieDataset.setValue( "Germany", 8.6 );

pieDataset.setValue( "Australia", 3.2 );

pieDataset.setValue( "China", 5.4 );

pieDataset.setValue( "Other", 1.4 );

request.getSession().setAttribute("imagenData3",pieDataset);

}

}







JSP: graficar.jsp
Esta es la página que mostrara las gráficas, es donde se invoca al constructor de graficas y al servlet.

<html>
<head>
<title>Gráficas</title>
</head>
<jsp:useBean id="myChartPie" scope="session" class="com.ui.servlets.graficas.PieChartGraphic" />
<body>
<h2>Gráficas

<!--String getChartViewer(HttpServletRequest request, HttpServletResponse response, String databean, int width, int height, String valueAxisLabel, String title, String categoryAxisLabel, boolean urls, boolean legend, boolean tooltips, boolean orientacionHorizonal, float R, float G,float B) { -->

<%String chartViewer3 = myChartPie.getChartViewer(request, response, "imagenData3",350,250,"value axis label2","Lu","categoria axis label",false,true,false,true,200,200,255);%>

<img src="<%=chartViewer3%>" border=0 usemap="#imageMap">
</body>
</html>



En el código de la página hay que prestar atención sobretodo a estas lineas:

Se crea un bean en session, AreaChartGrafic que es el encargado de generar la gráfica.

<jsp:useBean id="myChart" scope="session" class="com.servlets.graficas.AreaChartGraphic" />

Se define una variable string con el resultado de la invocación al bean antes definido, en esta invocación se pueden especificar ciertos parámetros que serán usados en la creación de la página el mas importante es el correspondiente a "databean" (3ro)que contiene el nombre de la variable en session, correspondiente los datos cargados en el action.

<!--String getChartViewer(HttpServletRequest request, HttpServletResponse response, String databean, int width, int height, String valueAxisLabel, String title, String categoryAxisLabel, boolean urls, boolean legend, boolean tooltips, boolean orientacionHorizonal, float R, float G,float B) { -->

<%String chartViewer3 = myChartPie.getChartViewer(request, response, "imagenData3",350,250,"value axis label2","Lu","categoria axis label",false,true,false,true,200,200,255);%>

Imprime la imagen de la gráfica en la pantalla
<img src="<%=chartViewer3%>" border=0 usemap="#imageMap">


Clase básica de graficadores: BasicGraphic.java
Esta clase abstracta permite abstraer toda la lógica necesaria para la invocación a los graficadores y su comunicación con el Servlet.

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.plot.PlotOrientation;

/***
*
* @author Ricardo
*
*/
public abstract class BasicGraphic {

protected HttpServletRequest request;
protected HttpServletResponse response;
protected String databean;
protected int width;
protected int height;
protected String valueAxisLabel;
protected String title;
protected String categoryAxisLabel;
protected boolean urls;
protected boolean legend;
protected boolean tooltips;
protected boolean orientacionHorizonal;
protected int R;
protected int G;
protected int B;
protected Object dataset;
protected PlotOrientation orientacion;
protected Color backgroundcolor;
/***
*
* @param request
* @param response
* @param databean Nombre de la variable en session que contiene los datos a graficar
* @param width Ancho que tendra la imagen
* @param height Alto de la imagen
* @param valueAxisLabel Etiqueta del eje de valores
* @param title Titulo de la grafica
* @param categoryAxisLabel Etiqueta del eje de categorias
* @param urls
* @param legend
* @param tooltips
* @param orientacionHorizonal Grafica horizontal o vertical
* @param R Componente RED del color de fondo
* @param G Componente GREEN del color de fondo
* @param B Componente BLUE del color de fondo
* @return Ruta al servlet que generara el mapping de la grafica notar que se le pasa como parametro el nombre de la variable en session que contiene el chart.
*/
public String getChartViewer(HttpServletRequest request, HttpServletResponse response, String databean, int width, int height, String valueAxisLabel, String title, String categoryAxisLabel, boolean urls, boolean legend, boolean tooltips, boolean orientacionHorizonal, int R, int G,int B) {
this.request=request;
this.response=response;
this.databean=databean;
this.width=width;
this.height=height;
this.valueAxisLabel=valueAxisLabel;
this.title=title;
this.categoryAxisLabel=categoryAxisLabel;
this.urls=urls;
this.legend=legend;
this.tooltips=tooltips;
this.orientacionHorizonal=orientacionHorizonal;
this.R=R;
this.G=G;
this.B=B;
this.backgroundcolor = new Color(R,G,B);
HttpSession session = request.getSession();
dataset = session.getAttribute(databean);
orientacion=null;
if (orientacionHorizonal ==true){
orientacion = PlotOrientation.HORIZONTAL;
}else{
orientacion = PlotOrientation.VERTICAL;
}
JFreeChart chart = crearJFreeChart();
ChartRenderingInfo info = null;
try {
//Create RenderingInfo object
response.setContentType("text/html");
info = new ChartRenderingInfo(new StandardEntityCollection());
BufferedImage chartImage = chart.createBufferedImage(width, height, info);//640,400
// putting chart as BufferedImage in session,
// thus making it available for the image reading action Action.
session.setAttribute("chartImage"+databean, chartImage);
PrintWriter writer = new PrintWriter(response.getWriter());
ChartUtilities.writeImageMap(writer, "imageMap", info,true);
writer.flush();
}
catch (Exception e) {
Log.getInstance().write(AreaChartGraphic.class.getName(), "getChartViewer" , e);
}
String pathInfo = "http://";
pathInfo += request.getServerName();
int port = request.getServerPort();
pathInfo += ":"+String.valueOf(port);
pathInfo += request.getContextPath();
String chartViewer = pathInfo + "/servlet/ChartViewer?sessionChart=chartImage"+databean;
return chartViewer;
}
protected abstract JFreeChart crearJFreeChart();
}


Graficadores: PieChartGraphic.java
Los graficadores son clases que extienden a BasicGraphic que implementan la función crearJFreeChart dependiendo del estilo de gráfica que se requiere.
import org.jfree.chart.*;
import org.jfree.data.general.DefaultPieDataset;
/***
*
* @author Ricardo
*
*/
public class PieChartGraphic extends BasicGraphic{

public PieChartGraphic() {
}

protected JFreeChart crearJFreeChart() {
JFreeChart chart = ChartFactory.createPieChart(title, (DefaultPieDataset)dataset, legend, tooltips, urls);
chart.setBackgroundPaint(this.backgroundcolor);
return chart;
}
}



import org.jfree.chart.*;
import org.jfree.data.general.DefaultPieDataset;
/***
*
* @author Ricardo
*
*/
public class PieChartGraphic extends BasicGraphic{
public PieChartGraphic() {
}

protected JFreeChart crearJFreeChart() {
JFreeChart chart = ChartFactory.createPieChart(title, (DefaultPieDataset)dataset, legend, tooltips, urls);
chart.setBackgroundPaint(this.backgroundcolor);
return chart;
}
}


Servlet: ChartViewer.java
Por ultimo esta el servlet el encargado de generar el maping de la imagen.

package com.ui.servlets.graficas;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.keypoint.PngEncoder;

/***
*
* @author Ricardo
*
*/
public class ChartViewer extends HttpServlet {

private static final long serialVersionUID = 1L;

public void init() throws ServletException {
}

//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ChartViewer");
Log.getInstance().write(ChartViewer.class.getName(), "doGet", Log.ENTER, Level.INFO);
String sessionChart = request.getParameter("sessionChart");

// get the chart from session
HttpSession session = request.getSession();
BufferedImage chartImage = (BufferedImage) session.getAttribute(sessionChart);
// set the content type so the browser can see this as a picture
response.setContentType("image/png");

// send the picture
PngEncoder encoder = new PngEncoder(chartImage, false, 0, 9);

response.getOutputStream().write(encoder.pngEncode());
Log.getInstance().write(ChartViewer.class.getName(), "doGet", Log.EXIT, Level.INFO);
}

//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

//Process the HTTP Put request
public void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}

//Clean up resources
public void destroy() {
}
}


tener en cuenta que para que el Servlet funcione hay que acoplarlo al sistema para esto hay que agregar al Web.xml las siguientes lineas:

<servlet>
<servlet-name>ChartViewer
<servlet-class>com.servlets.graficas.ChartViewer
</servlet>

<servlet-mapping>
<servlet-name>ChartViewer
<url-pattern>/servlet/ChartViewer
</servlet-mapping>


Una ves realizado todos los pasos descriptos podemos generar gráficas dinámicas fácilmente desde nuestras paginas JSP.

5 comentarios:

CSSeductor dijo...

Hola, me gustaria, que pusieras algo de como configurar el JFreechart, por que no entiendo como le hacen para configurarlo, gracias, por favor ayudame pronto que es para el miercoles gracias

Anónimo dijo...

Hola, me gustaria saber de donde sacaste el package
com.ui.actions;

Kerwin Arias dijo...

Hola Amigo me gustaria saber donde sacastes el paquete Log.getInstance(), Log.ENTER y Log.EXIT

rbedat dijo...

El paquete Log fue creado por mi extendiendo Log4J

Marcos_tam dijo...

Que tal Compañero...
Antes que nada gracias por tu explicacion. Abusando de tu confianza, tendras los archivos que generaste.
Con que linea anexaste la grafica al JSP?? es este?
img src="<%=chartViewer3%>" border=0 usemap="#imageMap"

Gracias por todo!!!