Zenoss - Monitoreo de infraestructura TI

viernes, 4 de septiembre de 2009
Zenoss es un software opensource que permite realizar monitoreo remoto de equipos como servidores, routers, ups, etc.

El monitoreo permite saber si un equipo está andando (up) o no (down), permite saber los filesystem que tiene (discos duros, unidades externas, opticos, RAM, memoria caché, etc.) y la utilización (total, usado, libre), permite saber qué procesos y servicios están corriendo y además saber que aplicaciones están instaladas en el equipo.

Y para que quiero saber esto de forma remota ? simple e importante, hoy en día toda infraestructura TI es crítica para el negocio ya que sin ésta es muy dificil que el negocio funcione, la infraestructura TI es la base de los negocios de hoy y el mañana y es importante tener un control respecto a los equipos y los servicios que corren y que soportan a nuestro equipo de trabajo y el de nuestros clientes.

El monitoreo permite adelantarse a los problemas y generar directivas preventivas y correctivas de manera tal de asegurar la prestación y calidad de nuestros servicios.

Zenoss es una solución entre varias como Nagios u openNMS e incluso otras propietarias como BMC Performance Manager Portal y BMC Proactive Net.

La gracia de Zenoss es que es simple de usar y configurar, es mas escalable que Nagios y puede utilizar plugines de éste último. A modo personal puedo decir que se parece a BMC Performance Manager Portal y BMC Proactive Net en su forma de funcionar y los servicios y opciones que provee.

Zenoss permite manejar eventos provenientes de los equipos monitoreados y generar notificaciones de alertas según lo configure el administrador, por ejemplo, si el servicio SSH se cae o no se ha levantado, es un error crítico desde el punto de vista del servicio como tal, pero tal vez no impacte mi infraestructura de forma grave por lo que se puede configurar una notificación con una criticidad baja.

Zenoss permite monitorear utilizando SNMP, SSH, WMI. Actualmente SSH es el más débil de los 3 ya que su implementación aún no está completa, sin embargo ya existen packs que permiten obtener bastante información útil desde máquinas con Ubuntu, Fedora y openSUSE. Hay que mantenerse informado y actualizado ya que las posibilidades mediante SSH son muchas porque se pueden ejecutar comandos que nos pueden traer cualquier métrica que necesitemos.

Mediante WMI podemos obtener información útil de máquinas Windows como los servicios que están corriendo y el software instalado.

La información que viene desde SNMP es bastante y por lo general suficiente para saber que procesos corren o el % de utización de los recursos físicos.

Zenoss muestra, además, gráficas representativas de la utilización de recursos de CPU y memoria.

Al ser un software opensource, existe una comunidad que aporta con packs de monitoreo, llamados ZenPacks, que extienden la aplicación agregando soporte para más dispositivos, características nuevas o mejoras en performance a dispositivos ya soportados.

El negocio de Zenoss está en el soporte, como todo negocio basado en modelo opensource. Mantienen dos versiones del software, Zenoss Core y Zenoss Enterprise. La primera es la versión libre y gratis que se puede descargar y utilizar, la segunda es la versión pagada con soporte profesional. Ambas son capaces de lo mismo, solo que a la primera se le deben integrar los ZenPacks necesarios (viene listo para SNMP y SSH básico, se debe instalar el soporte para monitoreo WMI, lo cual es muy fácil de hacer).

Una característica realmente interesante es la funcionalidad de Thresholds predictivos que lo acerca a su rival BMC Proactive Net, funcionalidad que permite manejar umbrales dinámicos.

Un umbral dinámico permite manejar valores distintos de acuerdo a la realidad de nuestra organización, por ejemplo para un banco el día 30 sus servidores reciben una mayor carga pero eso es un comportamiento normal por lo que no es necesario alertar, pero si el mismo comportamiento ocurre un día 10 entonces si estamos frente a un problema. Esto no lo permite hacer BMC Performance Manager Portal ni Nagios, punto a favor a Zenoss.

Otra característica importante es el soporte para monitoreo de infraestructura de servidores virtuales VMware ESX 4 (vSphere) ya que está acreditado por VMware.

También tiene integración con Remedy mediante el cual se pueden generar tickets de soporte.

La comunidad alrededor de Zenoss es muy amable, tuve la oportunidad de hacer preguntas y comentarios a los desarrolladores de Zenoss mediante el IRC y no tuvieron ningún problema en responder y aclarar mis dudas. Zenoss tiene a nuestra disposición un blog, foros, noticias y el IRC para hacer preguntas en vivo.

La instalación es muy simple de realizar, solo requiere que esté instalado MySQL.

Primero hay que descargar el instalador de acá, está para 32 y 64 bits (solo para linux).

Luego le damos permisos al ejecutable
chmod +x instalador

y lo ejecutamos desde consola


Presionamos next


Seleccionamos el lugar de instalación


Ingresamos el nombre la contraseña del usuario administrador de MySQL


Presionamos next


Esperamos unos minutos


Y ya tenemos Zenoss listo


Con eso ya la instalación está completa.

Para ingresar simplemente abrimos un navegador web e ingresamos la siguiente URL:
http://localhost:8080

y se abrirá la pantalla inicial de configuración de Zenoss


Pinchamos Step 1 y veremos la siguiente pantalla en donde debemos ingresar la contraseña del usuario "admin" e ingresamos un nuevo usuario de monitoreo


Ahora podemos agregar máquinas para monitorear


Seleccionamos la opcion Manually find devices e ingresamos el IP de la máquina que queremos, en este caso un Linux por SNMP y luego pinchamos submit


Si pinchamos Devices (al lado derecho en la pestaña Classes) podemos ver que en Server aparece un dispositivo agregado con color azul (que significa que se encontró el dispositivo)


Si pinchamos la elipse azul podemos ver el detalle del evento


Si pinchamos el nombre del dispositivo podemos ir a la página de monitoreo del mismo


Como ven, instalar y agregar un elemento al monitoreo es muy simple de realizar y solo se requiere que el servicio SNMP esté activo en el dispositivo a monitorear (Windows, Linux, *NIX, etc.).

Los invito a darle una oportunidad y probar Zenoss, realmente es muy muy muy bueno, una excelente alternativa para monitorear infraestructura que no tiene nada que envidiarle a sus rivales directos. Mas adelante iré agregando tips para usar este super software de monitoreo.

Saludos !!!

JKiltro reproductor de audio 1.0.1

domingo, 23 de agosto de 2009
Hoy he subido la versión 1.0.1 de JKiltro Reproductor de Audio, el cual es un pequeño software desarrollado en Java con el IDE NetBeans 6.7.1.

Este reproductor de audio se basa en varios proyectos open source para reproducir sonido, los cuales son:
Mediante el uso de los proyectos antes mencionados, JKiltro Reproductor de Audio puede reproducir archivos en los formatos aiff, ape, au, mp3, ogg, flac y wav, además permite editar la metadata de los archivos ape, mp3, ogg y flac.

JKiltro Reproductor de Audio mantiene una lista única de reproducción y contiene los controles básicos de reproducción:
reproducir, detener, pausa, anterior, siguiente, volumen, panning, saltar posición, agregar a la lista, eliminar de la lista, vaciar lista

además permite saltarse la reproducción a cualquier pista de la lista simplemente presionando doble click o la tecla espacio sobre la canción que se quiere escuchar.

También tiene la opción de repetir la reproducción desde el inicio con solo marcar un cuadro con un ticket.

Otra característica que lo hace interesante es que contiene un pequeño previsualizador al momento de elegir la carpeta o archivos justo antes de seleccionarlos y agregarlos a la lista de reproducción, de manera que se puede escuchar y así estar seguros de agregarlos o no a la lista.

Lo mejor de todo este proyecto es que puede ser utilizado en sus propias aplicaciones ya que pueden agregar el panel principal a su propio contenedor (JFrame, JPanel) con solo crear una instancia:
PanelPrincipalReproductorAudio reproductor = new PanelPrincipalReproductorAudio();

y ya tienen un reproductor de audio (y editor de metadata) empotrado.

Si no les gusta la interfaz gráfica entonces pueden crearse una propia sin preocuparse por la lógica que maneja la reproducción y edición de los archivos de audio gracias al diseño MVC, simplemente utilizan una instancia del controlador del panel principal en su propio panel con la GUI.
ControladorPanelPrincipalReproductorAudio controlador = new ControladorPanelPrincipalReproductorAudio();
Una buena forma de entender el código fuente es partir mirando la clase PanelPrincipalReproductorAudio.java, leer y tracear los métodos asociados a los eventos de cada botón, lo cual es muy útil al crearse una interfaz gráfica propia y hacer uso del controlador (que ya es capaz de encargarse de toda la lógica importante de la reproducción y edición).

El proyecto substance lo usé para permitir elegir un theme para la aplicación pero eso no tiene nada que ver con la reproducción de audio, sin embargo es un proyecto muy interesante que le da belleza a las aplicaciones java.

Aún quedan cosas por hacer, por ejemplo agregar un equalizador, JLGui trae uno pero falta integrarlo a mi proyecto.

Lo he probado en Mandriva Spring 2009 y Windows XP SP3 y funciona bien.
En el caso de Linux, si se quiere compartir el recurso de audio con otras aplicaciones se debe usar pulse audio y OpenJDK, de otra forma la aplicación les tomará el recurso de audio y no permitirá a otras aplicaciones utilizarlo.

A continuación les dejo algunas capturas de pantalla:


Desde aća pueden descargar el código fuente (proyecto NetBeans 6.7.1) y desde acá pueden descargar los binarios para usar la aplicación y probarla.

Espero les sea de utilidad.

Saludos !!!

Me titulé de Ingeniero Civil en Computación e Informática !!!

lunes, 29 de junio de 2009
Estimados lectores de mi blog,

Hace tiempo que no levantaba una entrada en mi blog ya que me he visto muy ocupado con varios temas (trabajo, universidad, familia, etc), pero me comprometo a seguir manteniendo el blog con mas entradas y aportes.

Hoy quiero compartir mi alegría con ustedes y contarles que he obtenido mi título de Ingeniero Civil en Computación e Informática, después de 6 años de sacrificio tanto propio como de mi familia y amigos que estuvieron acompañandome por este camino que elegí.

Quiero decirle a quienes están estudiando que sigan adelante, que se puede lograr, se puede llegar a la meta !!!, sigan estudiando, aprendiendo, aplicando y compartiendo conocimiento, que gracias a estos principios es que cada día crecemos mas como personas y profesionales.

Un saludo a todos.

Exposición Web Service con NetBeans 6.5.1 y Glassfish 2.1

domingo, 24 de mayo de 2009
Tiempo atrás hice un tutorial bastante detallado sobre como crear y consumir web services usando NetBeans y Glassfish. Hoy traigo lo mismo pero con un ejemplo mucho mas sencillo y fácil de entender y digerir.

Esta entrada trata sobre la exposición de un Web Service, en otra entrada explicaré cómo consumirlo.

El ejemplo expone dos métodos a través de Web Service para validar la existencia de un usuario (getUsuario) y para modificar sus datos (setUsuario).

Los datos del usuario están en un archivo XML para mantener el ejemplo sencillo y simple. La estructura del XML es la siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<raiz>
<usuario id="1" user="metalklesk" passwd="metalklesk" activo="true" />
<usuario id="2" user="klesk" passwd="klesk" activo="false" />
</raiz>

como se puede ver a continuación:


El archivo se llama usuarios.xml y debe crearse (o copiarse) en el directorio home del usuario (en el caso de Windows creo que es el directorio del usuario dentro de Mis Documentos, corríjanme si me equivoco y en el caso de Linux es /home/usuario).

Una vez listo ya podemos crear el Web Service. Para esta tarea utilizaremos un contenedor EJB.

Abrimos NetBeans 6.5.1 -> New project -> Java EE -> EJB module


como nombre ingresamos EJBModuleWebService y seleccionamos Glassfish como servidor de aplicaciones.

Una vez listo creamos una clase java a la cual llamaremos Usuario y la agregamos al package org.modelo (como no existe, se creará al ingresarlo en la misma pantalla de creación de la clase). La clase Usuario tendrá el siguiente código:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.modelo;

/**
*
* @author metalklesk
*/
public class Usuario {

private int id;
private String user;
private String passwd;
private boolean activo;

public boolean isActivo() {
return activo;
}

public void setActivo(boolean activo) {
this.activo = activo;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getPasswd() {
return passwd;
}

public void setPasswd(String passwd) {
this.passwd = passwd;
}

public String getUser() {
return user;
}

public void setUser(String user) {
this.user = user;
}
}

Ahora crearemos la clase AccesoDatos en el mismo package. Esta clase tendrá el siguiente código:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.modelo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
*
* @author metalklesk
*/
public class AccesoDatos {

private Document documento = null;
private String archivo = System.getProperty("user.home") + "/usuarios.xml";
private static AccesoDatos datos = new AccesoDatos();

private AccesoDatos() {
try {
documento = (Document) (((DocumentBuilderFactory.newInstance()).newDocumentBuilder()).parse(new File(archivo)));
} catch (SAXException ex) {
Logger.getLogger(AccesoDatos.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(AccesoDatos.class.getName()).log(Level.SEVERE, null, ex);
} catch (ParserConfigurationException ex) {
Logger.getLogger(AccesoDatos.class.getName()).log(Level.SEVERE, null, ex);
}
}

public static AccesoDatos getInstance() {
return datos;
}

public Usuario getUsuario(String user, String passwd) {
Element raiz = (Element) documento.getDocumentElement();
NodeList hijos = raiz.getElementsByTagName("usuario");
Usuario usuario = null;

for(int i=0; i<hijos.getLength(); i++) {
Element elemento = (Element) hijos.item(i);
String x = elemento.getAttribute("user");
String y = elemento.getAttribute("passwd");

if(x.equalsIgnoreCase(user) && y.equalsIgnoreCase(passwd)) {
usuario = new Usuario();
usuario.setId(Integer.parseInt(elemento.getAttribute("id")));
usuario.setUser(x);
usuario.setPasswd(y);
usuario.setActivo(Boolean.parseBoolean(elemento.getAttribute("activo")));

break;
}
}

return usuario;
}

public boolean setUsuario(Usuario usuario) {
Element raiz = (Element) documento.getDocumentElement();
NodeList hijos = raiz.getElementsByTagName("usuario");
boolean respuesta = false;

for(int i=0; i<hijos.getLength(); i++) {
Element elemento = (Element) hijos.item(i);
int id = Integer.parseInt(elemento.getAttribute("id"));

if(id == usuario.getId()) {
elemento.setAttribute("id", String.valueOf(id));
elemento.setAttribute("user", usuario.getUser());
elemento.setAttribute("passwd", usuario.getPasswd());
elemento.setAttribute("activo", String.valueOf(usuario.isActivo()));

respuesta = actualizarUsuarios();
break;
}
}

return respuesta;
}

private boolean actualizarUsuarios() {
documento.getDocumentElement().normalize();

try {
DOMSource source = new DOMSource(documento);
StreamResult result = new StreamResult(new FileOutputStream(archivo));

TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.transform(source, result);

return true;
} catch (TransformerException ex) {
Logger.getLogger(AccesoDatos.class.getName()).log(Level.SEVERE, null, ex);
return false;
} catch (FileNotFoundException ex) {
Logger.getLogger(AccesoDatos.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
}

Una vez listo ya podemos crear el Web Service, para eso hacemos click derecho en el proyecto -> New -> Web service


Ingresamos como nombre UsuarioWebService y lo agregamos al package org.modelo.


Una vez listo, ingresamos el siguiente código con los métodos a exponer en el Web Service:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.modelo;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.ejb.Stateless;

/**
*
* @author metalklesk
*/
@WebService()
@Stateless()
public class UsuarioWebService {

/**
* Web service getUsuario
* @param user
* @param passwd
* @return
*/
@WebMethod(operationName = "getUsuario")
public Usuario getUsuario(@WebParam(name = "user")
String user, @WebParam(name = "passwd")
String passwd) {
AccesoDatos datos = AccesoDatos.getInstance();

return datos.getUsuario(user, passwd);
}

/**
* Web service getUsuario
* @param usuario
* @return
*/
@WebMethod(operationName = "setUsuario")
public Boolean setUsuario(@WebParam(name = "usuario")
Usuario usuario) {
AccesoDatos datos = AccesoDatos.getInstance();

return datos.setUsuario(usuario);
}

}

Ya con eso estamos listos con la exposición del Web Service, ahora para probarlo podemos ejecutar la aplicación haciendo click derecho -> Run y luego expandimos la carpeta Web Services, damos click derecho el web service UsuarioWebService y pinchamos la opción Test Web service, lo cual abrirá una ventana del navegador web predeterminado en NetBeans.

Espero les sea de utilidad y como siempre me pueden dejar un comentario con su dirección de correo y les reboto el proyecto NetBeans comprimido.

Saludos !!!

Gráficos JMaki-Dojo, Servlets y Java Beans

viernes, 22 de mayo de 2009
Hace unos días estuve "jugando" con Java y JMaki para crear gráficos (charts). Buscando en la red encontré el proyecto jmaki-charting, el cual permite generar gráficos Dojo de tipo Area, Linea, Barra y Torta.

Desgraciadamente, los ejemplos de gráficos Dojo están malos, si entran en la página de ejemplos y pinchan un enlace de gráficos Dojo verán lo siguiente:


Asi es que me propuse crear un ejemplo que si funcione y de eso se trata esta entrada.

La gracia del ejemplo que explicaré a continuación es que se hace uso de clases java para la creación de los gráficos. De ésta manera se pueden crear gráficos a partir de datos obtenidos dinámicamente de una base de datos o cualquier fuente que se quiera. Si bien el ejemplo usa datos "duros" fácilmente se podrían modificar las clases y traer los datos de una base de datos.

También se muestra en el ejemplo la carga de los gráficos sin la necesidad de cargar una página jsp nueva, simplemente se refresca el área correspondiente y lo demás sigue igual lo que impacta positivamente en la velocidad de carga y experiencia del usuario.

Manos a la obra. Lo primero que necesitamos es NetBeans 6.5.1 con el JDK 1.6 update 13 (con ésta versión realicé el ejemplo). Una vez instalado hay que descargar los módulos de JMaki, para eso ir a Tools -> Plugins y seleccionar los dos plugines de JMaki.

Una vez reiniciado NetBeans hay que descargar el módulo jmaki-charting, abrir NetBeans e ir a Tools -> Palette -> Add jmaki library y seleccionar el módulo previamente descargado. Una vez listo ya se pueden utilizar los gráficos Dojo en NetBeans a través de la paleta.

La aplicación es web y explicaré la lógica que hay detrás de todo. Lo primero es entender como funciona la aplicación.

Básicamente se tiene un menú donde puedes elegir el tipo de gráfico. Éste menú es un combobox Dojo, el cual se arrastra desde la paleta al index.jsp. Cuando se arrastra un combobox dojo se genera con valores por default, pero eso no es muy útil, lo mejor es cargar los datos desde un Java Bean. El java Bean utilizado es el siguiente:

package org.beans;

import org.modelo.Parametros;

/**
*
* @author metalklesk
*/
public class BeanListaCharts {

public String getValues() {
StringBuffer buffer = new StringBuffer();

buffer.append("[");
buffer.append("{label:'Area', value:'" + Parametros.AREA + "'},");
buffer.append("{label:'Barra', value:'" + Parametros.BAR + "'},");
buffer.append("{label:'Linea', value:'" + Parametros.LINE + "'},");
buffer.append("{label:'Torta', value:'" + Parametros.PIE + "'}");
buffer.append("]");

return buffer.toString();
}
}

Luego hay que ingresar la siguiente línea en el jsp para hacer uso del Bean:

<jsp:useBean id="BeanListaCharts" class="org.beans.BeanListaCharts"/>

Y luego hay que pasar del siguiente código (que viene por default al arrastrar un combobox Dojo)

<a:widget name="dojo.combobox"
value="[
{label : 'Alabama', value : 'AL'},
{label : 'California', value : 'CA'},
{label : 'New York', value : 'NY', selected : true},
{label : 'Texas', value : 'TX'}
]" />

a la siguiente forma:

<a:widget name="dojo.combobox" value="${BeanListaCharts.values}" publish="/miCombo" />

Si se fijan, el value lo rellenamos con el método getValues del Java Bean. Eventualmente esos datos podrían provenir de una base de datos.

El publish es para publicar un evento asociado al combobox. Lo que sigue es programar el evento a nuestro gusto. Esto se hace en el archivo glue.js utilizando un subscribe, en ese archivo agregamos lo siguiente (al final):

jmaki.subscribe("/miCombo/onSelect", function(args) {
/*
*Se debe cargar el grafico desde una pagina (o servlet) externa pero dentro del dominio
*e insertarla mediante el injector.
**/
var url_ = jmaki.webRoot + '/ServletGeneradorCharts?tipoChart=' + args.value;
var injector = new jmaki.Injector();
injector.inject({url:url_, injectionPoint:"chart"});
});


Aquí utilizamos un Injector para agregar código html dinámico en una parte específica de la página, sin tener que recargar todo de nuevo en una página nueva. El Injector recibe como parámetros la dirección de la página a cargar y el lugar de la página actual en la cual será insertada.

En este caso llamamos a un servlet al cual le pasamos como parámetro el valor recogido de la selección en el combobox.

El método processRequest del servlet luce de la siguiente manera:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

String contexto = request.getContextPath();

String seleccion = request.getParameter("tipoChart");
String chart = "No existe ese tipo de gráfico.";

if(seleccion.equalsIgnoreCase(Parametros.PIE)) {
PieChartDojoJMaki pie = new PieChartDojoJMaki();
//si no le pasamos los parámetros requeridos, se genera un pie de ejemplo
//con valores predeterminados.
chart = pie.getValor();

out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/base.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/excanvas.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/PlotKit_Packed.js"></script>");
out.println("<link rel="stylesheet" type="text/css" href="" + contexto + "/resources/jmaki/charting/resources/jmaki-charting.css" />");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/pie/component.js"></script>");
out.println("<script type="text/javascript">jmaki.addWidget({widgetDir:'" + contexto + "/resources/jmaki/charting/pie',name:'jmaki.charting.pie',value:" + chart + ",uuid:'jmaki_charting_pie'});</script>");
out.println("<div id="jmaki_charting_pie" class="jmCPie">");
out.println("<canvas id="jmaki_charting_pie_chart" class="jmCPie"></canvas>");
out.println("</div>");
out.close();
} else if(seleccion.equalsIgnoreCase(Parametros.AREA)) {
AreaChartDojoJMaki area = new AreaChartDojoJMaki();
//si no le pasamos los parámetros requeridos, se genera un pie de ejemplo
//con valores predeterminados.
chart = area.getValor();

out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/base.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/excanvas.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/PlotKit_Packed.js"></script>");
out.println("<link rel="stylesheet" type="text/css" href="" + contexto + "/resources/jmaki/charting/resources/jmaki-charting.css" />");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/area/component.js"></script>");
out.println("<script type="text/javascript">jmaki.addWidget({widgetDir:'" + contexto + "/resources/jmaki/charting/area',name:'jmaki.charting.area',value:" + chart + ",uuid:'jmaki_charting_area2'});</script>");
out.println("<div id="jmaki_charting_area2" class="jmCPie">");
out.println("<canvas id="jmaki_charting_area2_chart" class="jmCPie"></canvas>");
out.println("</div>");
out.close();
} else if(seleccion.equalsIgnoreCase(Parametros.BAR)) {
BarChartDojoJMaki bar = new BarChartDojoJMaki();
//si no le pasamos los parámetros requeridos, se genera un pie de ejemplo
//con valores predeterminados.
chart = bar.getValor();

out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/base.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/excanvas.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/PlotKit_Packed.js"></script>");
out.println("<link rel="stylesheet" type="text/css" href="" + contexto + "/resources/jmaki/charting/resources/jmaki-charting.css" />");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/bar/component.js"></script>");
out.println("<script type="text/javascript">jmaki.addWidget({widgetDir:'" + contexto + "/resources/jmaki/charting/bar',name:'jmaki.charting.bar',value:" + chart + ",uuid:'jmaki_charting_bar'});</script>");
out.println("<div id="jmaki_charting_bar" class="jmCPie">");
out.println("<canvas id="jmaki_charting_bar_chart" class="jmCPie"></canvas>");
out.println("</div>");
out.close();
} else if(seleccion.equalsIgnoreCase(Parametros.LINE)) {
LineChartDojoJMaki line = new LineChartDojoJMaki();
//si no le pasamos los parámetros requeridos, se genera un pie de ejemplo
//con valores predeterminados.
chart = line.getValor();

out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/base.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/excanvas.js"></script>");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/resources/plotkit/PlotKit_Packed.js"></script>");
out.println("<link rel="stylesheet" type="text/css" href="" + contexto + "/resources/jmaki/charting/resources/jmaki-charting.css" />");
out.println("<script type="text/javascript" src="" + contexto + "/resources/jmaki/charting/line/component.js"></script>");
out.println("<script type="text/javascript">jmaki.addWidget({widgetDir:'" + contexto + "/resources/jmaki/charting/line',name:'jmaki.charting.line',value:" + chart + ",uuid:'jmaki_charting_line'});</script>");
out.println("<div id="jmaki_charting_line" class="jmCPie">");
out.println("<canvas id="jmaki_charting_line_chart" class="jmCPie"></canvas>");
out.println("</div>");
out.close();
} else {
//si el tipo de gráfico no corresponde, notifico al usuario.
out.println("<font color="#f00">" + chart + "</font>");
out.close();
}
}

El servlet recibe el parámetro seleccionado por el usuario a través del request.getParameter y dependiendo del valor construye un gráfico. Para obtener los valores del widget se hace uso de las clases

  • AreaChartDojoJMaki
  • BarChartDojoJMaki
  • LineChartDojoJMaki
  • PieChartDojoJMaki
Cada una de éstas clases se especializa en construir un gráfico en particular, utilizando la notación definida por JMaki (Dojo en este caso). En el ejemplo se utilizan datos duros, pero al igual que el caso del combobox, fácilmente se pueden adaptar para hacer uso de una base de datos.

A continuación se puede ver el código de la clase que define un gráfico de area:

package org.modelo;

import java.util.ArrayList;

/**
*
* @author metalklesk
*/
public class AreaChartDojoJMaki {

private ArrayList<String> xEtiquetas;
private ArrayList<String> yEtiquetas;
private ArrayList<String> datos;

/**
* Constructor sin parámetros. Inicia valores predeterminados para construir un
* gráfico de ejemplo.
*/
public AreaChartDojoJMaki() {
xEtiquetas = new ArrayList<String>();
xEtiquetas.add("{label : 'Enero'}, ");
xEtiquetas.add("{label : 'Febrero'}, ");
xEtiquetas.add("{label : 'Marzo'}, ");
xEtiquetas.add("{label : 'Abril'}, ");
xEtiquetas.add("{label : 'Mayo'}, ");
xEtiquetas.add("{label : 'Junio'}, ");
xEtiquetas.add("{label : 'Julio'}, ");
xEtiquetas.add("{label : 'Agosto'}, ");
xEtiquetas.add("{label : 'Septiembre'}, ");
xEtiquetas.add("{label : 'Octubre'}, ");
xEtiquetas.add("{label : 'Noviembre'}, ");
xEtiquetas.add("{label : 'Diciembre'}");

yEtiquetas = new ArrayList<String>();
yEtiquetas.add("{ label : '0', value : 0}");
yEtiquetas.add("{ label : '10s', value : 10}");
yEtiquetas.add("{ label : '20s', value : 20}");
yEtiquetas.add("{ label : '30s', value : 30}");
yEtiquetas.add("{ label : '40s', value : 40}");
yEtiquetas.add("{ label : '50s', value : 50}");

datos = new ArrayList<String>();
datos.add("{id : 'marcador', label : 'Dataset 1', values : [25, 45, 25, 45, 50, 25, 35, 25, 25, 20, 35, 45] }");
datos.add("{label : 'Dataset 2', values : [20, 40, 30, 35, 45, 20, 25, 15, 20, 25, 30, 40] }");
datos.add("{label : 'Dataset 3', values : [15, 35, 15, 40, 30, 15, 20, 10, 15, 20, 30, 35] }");
datos.add("{label : 'Dataset 4', values : [10, 25, 10, 5, 20, 5, 15, 5, 10, 15, 25, 30] }");
}

/**
* Recibe los datos que construyen el gráfico. Se pueden ingresar varios conjuntos de datos (datasets) y la forma
* en que se ingresa cada uno es de la siguiente manera:
* "{label : '$titulo_dataset', values : [$valor1, $valor2, ..., $valorN]}", sin las comillas.
* @param datos
*/
public void setDatos(ArrayList<String> datos) {
this.datos = datos;
}

/**
* Recibe las etiquetas para la coordenada X. El formato de cada etiqueta debe ser de la siguiente forma:
* "{label: '$valor'},", sin las comillas.
* @param xEtiquetas
*/
public void setXEtiquetas(ArrayList<String> xEtiquetas) {
this.xEtiquetas = xEtiquetas;
}

/**
* Recine las etiquetas para la coordenada Y. El formato de cada etiqueta debe ser de la siguiente forma:
* "{label : '$titulo', value : $valor}"
* @param yEtiquetas
*/
public void setYEtiquetas(ArrayList<String> yEtiquetas) {
this.yEtiquetas = yEtiquetas;
}

/**
* Retorna el contenido de la etiqueta value del componente jmaki.charting.area.
* @return
*/
public String getValor() {
StringBuffer buffer = new StringBuffer();

buffer.append("{");
//valores de la coordenada x
buffer.append("xAxis : { labels : [ ");
for(int i=0; i< xEtiquetas.size(); i++) {
buffer.append(xEtiquetas.get(i));
}
buffer.append("]},");
//valores de la coordenada y
buffer.append("yAxis : { labels : [");
for(int i=0; i< yEtiquetas.size(); i++) {
buffer.append(yEtiquetas.get(i) + ", ");
}
buffer.append("]},");
//aqui agrego marcadores en algunos puntos.
buffer.append("markers : [{ targetId : 'marcador', label : '{value}', " +
"index : 5}, { targetId : 'marcador', label : '{value}', index : 6}, " +
"{ targetId : 'marcador', label : '{value}', index : 8}],");
//datos que construyen el grafico
buffer.append("data : [ ");
for(int i=0; i<datos.size(); i++) {
buffer.append(datos.get(i) + ", ");
}
buffer.append("]");

buffer.append("}");

return buffer.toString();
}
}

Como se pude ver, no es necesario utilizar objetos JSON, un simple String con la estructura adecuada basta para generar un chart o widget JMaki en general.

A continuación se pueden ver imágenes del ejemplo funcionando.



Como siempre pueden dejar un comentario con su dirección de correo y les envío el ejemplo completo (proyecto en NetBeans 6.5.1 comprimido) para que lo corran y vean en sus equipos.

Saludos !!!