Un gráfico bajo JSP con Cewolf en NetBeans

15.8.08. Por ooscarr (ooscarr)

Netbeans

Traduje las instrucciones del tutorial de la página de Cewolf y consideré que se merecía un post, digamos, para actualizarlo/corregirlo.

Primero, para qué sirve Cewolf

Cewolf puede ser usado dentro de una aplicación basada en Servlet/JSP para insertar gráficos complejos de todo tipo (p.e. lineales, de torta o pastel o circular o 100%, de barras, histogramas, diagramas de caja, etc.) en una página web. Además provee una completa librería de etiquetas (tags) para definir todas las propiedades del gráfico (colores, rayas, leyendas, etc.). De este modo el JSP que incluye el gráfico no queda lleno de código java. Todo es descrito con etiquetas XML válidas.

Cewolf está basado en JFreeChart y usa su motor de renderizado para renderizar la imagen del gráfico final al flujo de respuesta de los clientes. Ningún archivo es creado en el lado del servidor. Todo está basado en objetos de sesiones livianas y análisis de datos dinámico. Cewolf consiste de un servlet el cual maneja el renderizado de los gráficos y una librería de etiquetas (Tag Library) que traduce la definición del gráfico incluida en el JSP a una etiqueta img que consulta al servlet de renderizado para la obtención del gráfico apropiado.

Cewolf

Completamente gratis, libre y abierto

  • Licencia LGPL
  • Sin cargos
  • Sin restrictions
  • Todos los archivos fuentes documentados y disponibles
  • Soporte las 48 horas en los foros de SourceForge
  • Rápido desarrollo y ciclos de mejores versiones

100% Java

  • sin uso de librerías nativas
  • debería correr en todo servidor compatible con J2EE o en contenedores servlet
  • uso extenso de proyectos open source disponibles

Completa librería de etiquetas para gráficos

  • Sin necesidad de código java dentro del JSP
  • Descripción XML de un gráfico
  • Validación de etiquetas de gráficas en tiempo de diseño
  • Extensa documentación de las etiquetas

Enorme número de diferentes gráficas

  • Lineal [XY]
  • Torta [3D]
  • Barras horizontales [3D]
  • Barras [XY] Verticales [3D]
  • [3D] Barras verticales apiladas
  • De área [XY]
  • Gráfico disperso
  • Gráfico de velas
  • Alto Bajo
  • Gantt
  • Sobrepuestos
  • Combinados

Antes

Antes de empezar, asegúrate:

Hola, mundo

PASO 1: Instalamos las librerías

  1. Creamos un Nuevo proyecto de tipo Aplicación Web
    Captura de pantalla del asistente para crear un Nuevo proyecto en Netbeans
  2. Elejimos un nombre
    Captura de pantalla del asistente para crear una Nueva Aplicación Web
  3. Usamos una carpeta dedicada para los archivos JAR
    Use dedicated library folder for server JAR files
  4. Ahora, en la parte de los proyectos, seleccionamos Propiedades. Y en el panel de propiedades, sección Librerías presionamos el botón de Agregar JAR
    Libraries > Add JAR/Folder
  5. Aquí tenemos que abrir la carpeta del Cewolf recién descargada y dentro de la carpeta /lib/ seleccionar todos los archivos .jar que aparecezcan, marcar la opción Copiar a la carpeta de librerías y presionar Seleccionar.
    Copy to Libraries Folder
  6. OK
    Panel de Propiedades del proyecto en Netbeans para Mac OS X con el botón OK focalizado
    No se olviden también de agregar la librería JSTL con el botón Agregar Librería, o sino no va a funcionar nada.

PASO 2: Nos ponemos desagradables

Ahora que están las librerías, debemos preparar la aplicación.

Primero debemos mover o copiar la carpeta /etc/ que viene en Cewolf a nuestra carpeta /WEB-INF

Captura de pantalla que muestra cómo se arrastra una carpeta del panel Favoritos al panel de archivos del proyecto en Netbeans
Para ver nuestras carpetas locales en Netbeans, debemos seleccionar el menú Ventana > Favoritos (o Window > Favorites, si tienes el Netbeans en inglés).

web.xml

Ahora editamos el archivo web.xml que hizo un cameo en la imagen anterior, en el modo XML y le metemos el siguiente código antes que se cierre la etiqueta </web-app>

<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>
 <!-- turn on or off debugging logging -->
 <init-param>
  <param-name>debug</param-name>
  <param-value>true</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
 <servlet-name>CewolfServlet</servlet-name>
 <url-pattern>/cewolf/*</url-pattern>
</servlet-mapping>

Para probar, prueba ejecutar la aplicación web (o presionar el botón Play) y visitar la carpeta /cewolf como en el siguiente ejemplo:

http://localhost:8080/ejemplo/cewolf?state

Y debería aparecer:

Cewolf servlet up and running.
Requests served so far: 0

O sino, te equivocaste de puerto (prueba el :8084).

PASO 3: Java

Con Cewolf, todavía se debe escribir la parte de los datos de JFreeChart con código Java. Lo que sucede es que una clase se encarga de preparar los datos y a través de un bean se accede a ellos desde la JSP.

  1. Para crear la clase, vamos a Nuevo archivo > Java > Java Class
    Panel de nuevo archivo de Netbeans en Mac OS X
  2. Le ponemos un nombre a la clase, en este caso NumeroDeVisitas; y al paquete (Package) le podríamos llamar de.laures.cewolf.datos
    Captura de pantalla del panel de nueva clase java en Netbeans para Mac OS X
  3. Luego de presionar el botón Finalizar, el archivo debería aparecer dentro de la carpeta Source Packages en nuestro proyecto.

    Captura de pantalla con el árbol de archivos en Netbeans mostrando el archivo ejemplo > Source Packages > de.laures.cewolf.datos > NumeroDeVisitas.java

Códigos fuentes

Y en ese archivo escribamos, por ejemplo, el siguiente código java que he traducido especialmente para ti:

NumeroDevisitas.java
package de.laures.cewolf.datos;

import java.io.Serializable;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import de.laures.cewolf.DatasetProduceException;
import de.laures.cewolf.DatasetProducer;
import de.laures.cewolf.links.CategoryItemLinkGenerator;
import de.laures.cewolf.tooltips.CategoryToolTipGenerator;

/** 
 * Un ejempplo de productor de datos.
 * @author  Guido Laures
 * Traducido por Oscar Fernández
 */

public class NumeroDeVisitas implements DatasetProducer,
 CategoryToolTipGenerator, CategoryItemLinkGenerator, Serializable{

 private static final Log log=LogFactory.getLog(NumeroDeVisitas.class);

 // Estos valores normalmente no se deberían escribir
 // sino producidos por algún tipo de fuente de datos
 // como una base de datos o un archivo
 private final String[] categories={"Lun","Mar","Mié","Jue","Vie","Sáb","Dom"};
 private final String[] seriesNames={"Portada","Noticias","Foros","Buscador"};

 //Produce datos aleatorios
 public Object produceDataset(Map params) throws DatasetProduceException{
  log.debug("produciendo datos.");
  DefaultCategoryDataset dataset=new DefaultCategoryDataset(){
   // @see java.lang.Object#finalize()
   protected void finalize() throws Throwable {
    super.finalize();
    log.debug(this +" terminado.");
   }
  };
  for(int series=0;series<seriesNames.length;series ++){
   int lastY=(int)(Math.random()*1000+1000);
   for(int i=0;i<categories.length;i++){
    final int y=lastY+(int)(Math.random()*200-100);
    lastY=y;
    dataset.addValue(y,seriesNames[series],categories[i]);
   }
  }
  return dataset;
 }

 /**
  * Estos datos producidos son invalidados después de 5 segundos.
  * Por este método el productor puede influenciar el comportamiento
  * de caché de Cewolf de la forma que quiera.
  */
 public boolean hasExpired(Map params,Date since){
  log.debug(getClass().getName()+"hasExpired()");
  return(System.currentTimeMillis()-since.getTime())>5000;
 }

 // Retorna un ID único para este DatasetProducer
 public String getProducerId(){
  return "NumeroDeVisitas DatasetProducer";
 }
 
 // Retorna un link target para un item de datos especial.
 public String generateLink(Object data,int series,Object category){
  return seriesNames[series];
 }

 // @see java.lang.Object#finalize()
 protected void finalize() throws Throwable{
  super.finalize();
  log.debug(this+" finalized.");
 }

 /**
  * @see org.jfree.chart.tooltips.CategoryToolTipGenerator#generateToolTip(CategoryDataset, int, int)
  */
 public String generateToolTip(CategoryDataset arg0,int series,int arg2){
  return seriesNames[series];
 }
}
index.jsp

Ya. Ahora que la parte complicada está hecha, para llamar al gráfico desde la JSP, escribimos:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri='/WEB-INF/etc/cewolf.tld' prefix='cewolf' %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
  <title>Hola, mundo</title>
 </head>
 <body>
  <jsp:useBean id="visitas" class="de.laures.cewolf.datos.NumeroDeVisitas"/>
  <cewolf:chart 
   id="line"
   title="Estadísticas de visitas al sitio"
   type="line"
   xaxislabel="Página"
   yaxislabel="Número de Visitas">
   <cewolf:data><cewolf:producer id="visitas"/></cewolf:data>
  </cewolf:chart>

  <h1>Hola, mundo!</h1>
  <p><img src="<cewolf:imgurl
      chartid="line"
      renderer="cewolf"
      width="400"
      height="300"></cewolf:imgurl>"
   alt="Gráfico" /></p>
 </body>
</html>

Para que funcione, se debe poner atención a las partes marcadas del código.

¡Y listo!

Ahora al visitar la página recién editada, debería aparecer algo así:

ver index.jsp.
* Las líneas del gráfico lineal pueden ser diferentes, ya que, como se vio en el código java, corresponden a datos aleatorios que cambian cada vez que se refresca la página.
** La página es de referencia

Algo más útil

Algo más útil sería obtener los datos desde una base de datos o algún otro servicio. Eso lo veré en otro capítulo. Se me acabó el tiempo. Chao.

Referencias

Etiquetas: ,

0 comentarios (RSS ATOM) :

Página principal

Publicidad