miércoles, octubre 12, 2005

Hibernate, comienza el frio

¿Quién no ha hecho una aplicación en su vida que se conecte a una base de datos? Incluso quizás sea mejor pregunta: ¿Quién ha hecho una aplicación que no se conecta a una base de datos? Quizás a esta respuesta contestasen menos personas y nos ahorraríamos tiempo de contar manos en alza. Lo cierto es que para un programador, las bases de datos son fundamentales.
Casi desde el principio, en el mundo javero, se ha tenido en cuenta dicho hecho, y ya desde principios se diseñó JDBC para poder facilitar a los programadores el acceso a bases de datos. JDBC es una API que sirve para conectar a base de datos de manera independiente del tipo de base de datos uses.
Esto es extremadamente útil porque con un poco de elegancia en el diseño de la aplicación, puedes conseguir una aplicación que sea completamente independiente de la base de datos.
Hoy en día las bases de datos en su mayoría son bases de datos relacionales. Existen bases de datos orientadas a objetos pero en la práctica, las más usadas son las relacionales. Y lo cierto es que parece ser que esto va a seguir siendo así bastante tiempo (por lo menos no hay muestras de alguna tendencia que incite a pensar lo contrario).
Las bases de datos relacionales, tal y como indica su nombre, se basan en relaciones entre entidades. Concepto que dista mucho de lo que es la oop (abstracción, encapsulación, polimorfismo y herencia). El hecho de que exista dicha diferencia puede complicar la manera de conseguir que la aplicación persista correctamente los objetos de negocio en la base de datos.
Debido a esto se han creado frameworks de persistencia de objetos. Sirven para persistir los objetos de una forma transparente al programador.
¿Como funciona Hibernate? La verdad es que es bastante sencillo, como concepto, después las cosas se pueden complicar bastante si no se tiene un buen diseño de la base de datos. Si se quiere usar Hibernate se han de crear los objetos de negocio y sus relaciones. Después se deberá crear una serie de archivos xml que indican a hibernate qué objeto se guarda en qué tabla, indicando la relación entre propiedades del objeto y columnas de la tabla. Por ejemplo, yo tengo una clase Persona tal y como sigue:


package org.edvera.hibernateexample;

public class Persona {

private String nombre;
private String apellido;

public String getNombre()
{
return nombre;
}

public void setNombre(String nombre)
{
this.nombre = nombre;
}

public String getApellido()
{
return apellido;
}

public void setApellido(String apellido)
{
this.apellido = apellido;
}
}

Esta clase quiero que guarde sus datos en la tabla PERSONAS, que viene definida:

CREATE TABLE PERSONAS (
id int primary key auto_increment,
nombre varchar(32) not null,
apellido varchar(32) not null
);

Si quiero que hibernate me haga la persistencia (guardar) del objeto tendré que indicarle la relación entre el objeto y la tabla. Esto se hace mediante un archivo xml que llamaremos Persona.hbm.xml, como el que sigue:

<hibernate-mapping>
<class name="org.edvera.hibernateexample.Persona" table="PERSONAS">
<id name="id" column="id" type="int">
<generator class="native">
</generator>
</id>
<property name="nombre" type="java.lang.String" column="nombre"/>
<property name="apellido" type="java.lang.String" column="apellido"/>
</class>
</hibernate-mapping>


De esta forma ya tenemos mapeado el objeto con la base de datos. Nos queda crear otro archivo para configurar la conexión que ha de usar hibernate (hay varias maneras de hacerlo, yo voy a usar la más sencilla para mayor claridad). Este archivo se llama hibernate.cfg.xml y es el siguiente:


<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/bbdd</property>
<property name="connection.username">bbdd_user</property>
<property name="connection.password">bbdd_passwd</property>
<property name="connection.dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<!-- mapping files -->
<!-- ficheros relacionados con los productos -->
<mapping resource="org/edvera/hibernateexample/Persona.hbm.xml"/>
</session-factory>
</hibernate-configuration>


En este archivo se dan los datos para poder hacer la conexión (aquellos que son los elementos property de la session factory) así como los archivos de mapeos (nosotros solo tenemos uno que es el de Persona.hbm.xml).
Ahora que tenemos hibernate configurado y listo para servirnos, veamos como usarlo en el código. Vamos a hacer una clase con un método principal que usa hibernate para guardar en la base de datos una persona ejemplo.


package org.edvera.hibernateexample;

import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;


public class HibernateExample {

public static void main (String args[])
{
Configuration configuration = new Configuration(); //Objeto que guardará la configuración de hibernate
try
{
//Leemos el archivo de configuración de hibernate (que deberá estar en el classpath
configuration.configure();
//Creamos la factoria de sesiones
SessionFactory sessionFactory = configuration.buildSessionFactory();
//Obtenemos una sesion
Session session = sessionFactory.openSession();
//Creamos la persona y la dotamos de información
Persona persona = new Persona();
persona.setNombre("Perico");
persona.setApellido("ElDeLosPalotes");
//Usamos la sesion de hibernate para persistir el objeto Persona
session.save(persona);
//Nos aseguramos de que se guardan los datos de la sesión en la base de datos
session.flush();
//Cerramos la sesión
session.close();
}
catch (Exception e)
{
//Excepcion no esperada.
}
}
}


Como se puede ver, a pesar de la simpleza y poca utilidad del código, el resultado es un código más limpio, sin necesidad de usar sentencias sql en cosas tan triviales.
De todas maneras las cosas no son tan sencillas con hibernate como parecen. Hay que tener en cuenta de que hibernate guarda los datos del objeto en la sesión, y que hasta que no se hace un flush no se persisten realmente los datos. El hecho de que la sesión se interponga entre los datos y la base de datos obliga a tener mucho cuidado en como se gestionan las sesiones. Puesto que una sesión debe pertenecer a un único Thread y un único Thread no debería de tener más de una sesión porque en caso contrario no se puede asegurar la integridad de los datos (dos threads usando la misma sesión podrían estar poniendo en peligro los datos).
Espero que este artículo sirva como primer acercamiento a esta tecnología y que el lector, después de haberlo leido, tenga una noción de lo que son los famosos frameworks de persistencia así como una idea general de para qué sirve hibernate. Por supuesto no he hablado ni del 10% de lo que puede hacer Hibernate, pero no pretendo quitarle trabajo a los chicos de JBoss (XD).

viernes, octubre 07, 2005

Struts, ¿buscas trabajo?


Como os podreis imaginar, no le estoy preguntando a un señor llamado struts si está buscando trabajo. La verdad es que en España, Struts está de moda. Es el MVC orientado a la web más utilizado en el mundo javero.
¿Y qué es eso de MVC? Estas siglas responden a Model-View-Controller (modelo, vista, controlador), que es uno de los famosos patrones de diseño del Gang of Four.
Un patrón de diseño es una solución elegante a un problema recurrente. Ante determinados problemas que siempre están presentes en el desarrollo de un programa y gracias a la experiencia de haberse enfrentado una y otra vez a los mismos se consiguen soluciones lo suficientemente abstractas como para ser usadas en muchos desarrollos. Ejemplos de este tipo de soluciones son el patrón Iterator, Facade, Singleton, MVC, etc...
Existen distintos tipos de patrones de diseño según su objetivo. Así tenemos patrones de diseño de creación, estructurales y comportamiento
En el caso del MVC, se trata de un patrón de comportamiento compuesto por tres partes diferenciadas:
- Modelo: son los datos de negocio. Un ejemplo sencillo, tenemos una aplicación web de registro de usuarios. La clase que se encarga de representar los datos del usuario así como las clases que sirven para tratar esos datos, son el modelo.
- Vista: La vista, como indica su nombre, son las clases que se encargan de mostrar en pantalla los datos, formularios y demás elementos para que el usuario trate con la aplicación.
- Controlador: el controlador es el que se encarga de gestionar las entradas del usuario, actuar con el modelo y seleccionar la vista adecuada al usuario en cada momento.Como ya he dicho antes, Struts es un framework basado en ese patrón. Como en todos los frameworks, en Struts hay muchas cosas ya hechas, pero no todas... Para poder desarrollar una aplicación en Struts vamos a tener que tocar en medidas diferentes los tres componentes del patrón.
En el caso de la vista, el trabajo es completamente nuestro. Podemos hacer uso de sistemas de plantillas para facilitarnos la vida (los tiles ya están incluidos en struts por defecto). Por lo general, la vista contará con un montón de páginas jsp, taglibs, html, etc...El modelo también es trabajo completamente nuestro. De nosotros depende tener un modelo limpio que nos permita conectarlo al controlador sin ensuciar su lógica. En general el modelo suelen ser JavaBeans, clases de acceso a la fuente de datos (DAOs, EJBs, etc...).
Y, por último está el controlador, que es lo que nos dan casi completamente hecho. El controlador en Struts se basa en archivos de configuración xml (struts-config.xml, validator.xml, tiles-def.xml, etc...) que cuanto mejor conozcamos más trabajo nos ahorrarán. Pero no todo es xml en el controlador de Struts, hay también que programar. En los casos más sencillos tendremos que programar un clase que herede de org.apache.struts.action.Action y después deberemos añadirla al archivo de configuración de struts-config.xml). En casos en los que los formularios sean lo suficientemente complejos (y no podamos usar los fantásticos DynaActionForm) también tendremos que programar una clase que herede de org.apache.struts.action.ActionForm.
Por lo general, esto será todo el trabajo que tengamos que hacer en una aplicación de struts más o menos sencilla. Aunque Struts tiene mucha más potencia, le puedes añadir plugins, tiene su propia gestión de excepciones, ofrece librerias de etiquetas muy útiles, un framework de validación (validator) y un largo etceterá.
Struts es útil para hacer el trabajo al que está destinado. Pero no podemos olvidarnos de que hay tecnologías emergiendo con fuerza y que serán posibles rivales de Struts (o quizás se puedan complementar, he visto por ahí un plugin de Spring para struts), como puede ser Spring o directamente las nuevas Java Server Faces desarrolladas en gran parte por el propio creador de Struts.

Xdoclet Java todavía más fácil


Una de las cosas que más me gustó de Java cuando lo conocí fué la elegancia que se desprende del lenguaje. El hecho de que sea un lenguaje orientado a objetos con gestión de excepciones y sin necesidad de usar punteros por parte del programador, es algo que todos los que nos hemos peleado con el código agradecemos profundamente (sí sí... sé que muchos de los nerds que me podrían leer me dirian que los punteros son muy útiles... y no les falta razón... si es que los que somos unos inútiles somos los humanos, que tendemos a equivocarnos).
Pero las cosas no podían ser todas de color de rosa, Java fué creciendo y con él también crecieron las tecnologías que le rodeaban. Todavía me acuerdo del primer servlet que programé (allá por el año 98) que después instalé en el JRun sin demasiadas complicaciones. La realidad ha cambiado y ahora los servlets se supone que han de estar comprendidos en una aplicación web. Y aquí es donde se empieza a complicar la cosa. Ya no basta con implementar una interfaz, ahora hay que crear un descriptor de despliegue (deployment descriptor).
Se ha pasado de desarrollar aplicaciones standalone a aplicaciones hospedadas en contenedores. Las ventajas son muchas, simplificación de la programación al tener un montón de servicios disponibles para las aplicaciones de negocio. Desde la seguridad, la transaccionalidad, las trazas, etc... son servicios facilmente accesibles para los desarrolladores sin necesidad de tener que programarlos uno mismo. La desventaja mayor podría ser el hecho de que para poder acoplar dicha aplicación en el contenedor, tenemos que crear el famoso descriptor de despliegue.
Hasta ahora los descriptores de despliegue han sido unos archivos xml que basicamente definen como se debe de conectar el componente que se ha desarrollado en el contenedor que lo va a alojar. De esta manera, estamos haciendo uso de los servicios que nos proporciona el servidor sin tener que programar practicamente nada.
Pero si se va a tener un descriptor de despliegue para una aplicación, suena razonable pensar que se ha de estar tocando dicho descriptor constantemente según se vaya avanzando en dicha aplicación. Resultando una tarea pesada el estar constantemente revisándolo, preocupándose por su validez tanto semántica como sintáctica. Y aquí es donde comienza el meollo de la cuestión...
Volviendo a la elegancia de java, una de las cosas que más me gusta de java son sus fantásticos Javadocs. Siempre que he tenido que alejarme de java para usar otro lenguaje me he encontrado con que la documentación de ese lenguaje solía ser, en el 99% de los casos, peor de lo que normalmente es en el mundo java. Eso se debe a que Sun se preocupó mucho de hacer la tarea de documentación algo rápido y productivo para los desarrolladores (que tanto odiamos estar comentando cosas que a veces ni siquiera hemos hecho nosotros).
Javadoc es una herramienta incluida en todo jdk que sirve para leer el código fuente de una aplicación java y producir la documentación de la misma. El proceso es sencillo, basta con poner unos comentarios (que empiezan por /** y terminan por */) junto con unas etiquetas especiales (siempre empiezan por @).
Así, por ejemplo, si queremos producir la documentación de una clase bastaría con poner lo siguiente:

/**
* Clase de ejemplo para el uso de javadocs
* @author Eduardo de Vera
* @version 1.0
*/
public class ClaseDocumentada {

/**
* Metodo de ejemplo para javadoc
* @param parametro que le pasamos a la documentación
* @return String de retorno
*/
public String method (String parametro)
{
return parametro;
}
}

Si esta clase la pasamos por la herramienta javadoc, nos producirá un bonito archivo html con los comentarios formateados. Queda fuera de este artículo explicar paso a paso como crear javadocs, pero estoy seguro de que hay mucha información en la red para poder hacerlo.
Bien, llegados a este punto el lector se estará preguntando qué tipo de cacao estoy montando entre descriptores de despliegue y javadocs (con toda la razón del mundo porque aparentemente no tienen nada que ver).
Y es aquí donde llega la unión de ambas cosas: XDoclet. Xdoclet amplia el conjunto de etiquetas especiales javadoc (@algo) para poder crear, además de documentación, archivos de despliegue. Ahora todo lo que comprende a nuestra aplicación está en un único punto, el código fuente. Eso nos da una ventaja tremenda puesto que no tenemos que estar saltando de archivo en archivo sintentando seguir la lógica del contenedor. Ahora tenemos todo lo que involucra a una clase (servlet, ejb, action, hibernate pojo, etc...) en un único archivo (el código fuente de la clase) disponible con un simple click.
Después solo tenemos que pasar Ant o Maven con su extensión de Xdoclet y, casi por arte de magia, se nos crearán los archivos de despliegue, se compilará la aplicación y se nos empaquetará lista para entregarla al cliente.
Para ver lo sencillo que puede ser hacer un servlet que será contenido en una aplicación web, bastaría con ver el siguiente ejemplo:

package org.etux.servlets;

import javax.servlet.http.*;
import java.io.IOException;

/**
* @web.servlet description="Descripción del servlet" display-name="Nombre del servlet a mostrar" name="ServletEjemplo"
* @web.servlet-mapping url-pattern="/servletEjemplo"
*
* Comentarios normales del javadoc
* @author Eduardo de Vera
* @version 1.0
*/
public class ServletEjemplo
{
protected void doPost(HttpServletRequest request, HttpServletResponse) throws ServletException, IOException {
//logica del servlet
}

protected void doGet(HttpServletRequest request, HttpServletResponse) throws ServletException, IOException {
//logica del servlet
}
}

Una vez que pasasemos el archivo por el xdoclet (usando ant o maven) obtendríamos un web.xml con los siguientes datos:


...
<servlet>
<servlet-name>ServletEjemplo</servlet-name>
<display-name>Nombre del servlet a mostrar</display-name>
<description><!--[CDATA[Descripción del servlet]]--></description>
<servlet-class>org.etux.servlets.ServletEjemplo</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ServletEjemplo</servlet-name>
<url-pattern>/servletEjemplo</url-pattern>
</servlet-mapping>
...


Obviamente no hemos usado todas las etiquetas disponibles para los servlet, pudiéndose poner parámetros de inicialización de los servlets, por ejemplo. También hay que destacar que esto es xdoclet aplicado a servlets, pero la lista de tecnologías para las que se usa xdoclet no para de crecer, siendo las más destacadas ejb, servlets, struts, hibernate, jdo, jmx, spring, etc...

Maven izando el mundo


Llevo ya unos meses usando Maven, esta magnífica herramienta para el control de proyectos. La definición exacta de este software es, según sus creadores:
"a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information".
Que traducido es "software para la administración de proyectos y herramienta de asimilación, se basa en el concepto de objeto de modelo de proyecto, pudiendo administrar la construcción, el reporte y la documentación del mismo desde una pieza central de información".
Yo la verdad, es que cuando leí esta definición me quedé a cuadros, realmente no tenía ni idea de lo que significaba. Sabía que tenía que dedicarle un poco de tiempo, estos chicos de la Apache Software Foundation siempre me sorprenden con sus productos y tenía el presentimiento de que este no sería un caso aparte. Después de haber estado un tiempo usándolo, me puedo atrever a explicar un poco en qué consiste Maven.
Maven es una aplicación que está una capa por encima de Ant. De hecho, Maven hace uso de Ant para poder realizar muchas de sus tareas. Los de la ASF vieron que cada vez que quieres construir un proyecto java con Ant tienes que estar repitiendo el archivo de construcción (build.xml), en muchos casos dicho archivo no varia de un proyecto a otro, así que decidieron hacer una herramienta que nos ahorrase ese trabajo extra del cual uno se aburre a la tercera vez que lo hace (es cierto que las dos primeras son emocionantes por la sensación de poder que da Ant).
Una de las cosas que diferencian a Maven de Ant es que las cosas están bastante más definidas cuando te pones a usar Maven. Por ejemplo, Maven tiene predeterminadas plantillas que te permiten construir un proyecto en pocos minutos. Estas plantillas son archivos en jelly (una herramienta para convertir xml en código ejecutable) que hacen la vida más fácil a los programadores. En Ant se tenía toda la libertad del mundo para tener la disposición de directorios que se quisiese y, aunque parezca contradictorio, a veces la libertad en los desarrollos puede llevar al caos en un equipo grande. Los chicos que han diseñado esta herramienta se han dado cuenta de que después de unos cuantos años de desarrollos en java, que para determinado tipo de proyectos hay determinadas tipos de estructuras que son las más optimas (comodas o como se quiera llamarlas).
Si Ant tiene tareas (tasks) como unidades de trabajo, Maven tiene fines (goals). El concepto es muy parecido aunque la manera de llevarlo a cabo es distinto. Los que nos hemos tenido que crear nuestros build.xml sabemos que las tareas de ant las define el escritor del archivo, con Maven no se pierde esa potencia pero se ahorra mucho trabajo porque Maven ya viene con un montón de goals predefinidos, sin necesidad de que la persona encargada de la construcción y ensamblaje de la aplicación tenga que escribir una sola línea. Esto se debe a que, igual que ocurre con la estructuras, hay muchas tareas comunes que se pueden simplificar.
Pero Maven no solo sirve para compilar y empaquetar. También puedes hacer que los test de junit corran en el proceso de construcción, haciendo más fácil la vida de los seguidores de la programación extrema, y en concreto, de los desarrolladores inmersos en la integración contínua.
Se puede usar para realizar documentación del proyecto (javadocs) así como reportes que conciernen al desarrollo del proyecto, desde datos relacionados con los desarrolladores involucrados (gracias a la conexión con alguno de los controles de versiones más populares) hasta datos acerca de la calidad del código por medio de herramientas como pmd. Y, todo ello, se puede ver traducido a una web en la que se encuentran todos los recursos, datos, documentos del proyecto.
Parece ser que Maven es la herramienta que se impondrá en el desarrollo de proyectos java. Y quizás no solo java, después de haber visto como mocosoft vuelve a plagiar a la comunidad de software libre/abierto creando su mAnt, me atrevo a decir que ya están tardando en copiarlo para su paupérrima plataforma "net".
Sé que me he dejado cosas en el tintero pero realmente creo también que hay mejores sitios para aprender las profundidades de un proyecto tan interesante como es Maven.

Bienvenidos y bienvenidas

Al final, no pude evitar introducirme en el mundo de los blogs. Como informático que soy siempre estaba pensando en hacerme mi propia web y tener allí mi propio blog. Pero siempre encuentro razones para ponerme a programar otras cosas, así que he decidido venirme hasta aquí para poder comunicarme con el mundo exterior.
Siempre que se inicia algo en la vida, uno se encuentra lleno de ideas acerca de como afrontarlo, de qué le gustaría hacer con esa nueva puerta que se abre. Y en esas me encuentro yo, pero prefiero no decir nada ahora para no crear falsas esperanzas.
Como blog personal, intentaré transmitir mis inquietudes, conocimientos y experiencias. Creo que, para que el visitante se haga una idea de qué se va a poder encontrar aquí, debería de enumerar algunas de las cosas que ocupan mi cabeza cotidianamente.
Como ya he dicho soy informático, analista programador java, amante del software libre (tanto por su superioridad tecnológica como por la ética), seguidor de la política (tanto nacional como internacional). Se quedan muchas cosas en el tintero, pero estoy seguro de que con el tiempo se podrá formar una imagén más o menos nítida de la persona que soy.