25 March, 2008

Curso J2EE (4ª semana) - EJB

Logo JavaComo aventuraba en el anterior post de esta serie, esta semana hemos comenzado con ejb. Después de una introducción donde se repasaron las complejidades de ejb2 y su posterior evolución a ejb3, nos centramos únicamente en ejb3 y en desarrollar algún que otro ejemplo utilizando como contenedor a jboss.

EJB forma parte de j2ee desde su versión 1.1 y mediante su especificación se detalla cómo los servidores de aplicaciones proveen objetos desde el lado del servidor. Utilizando ejb creamos componentes que encapsulan lógica de empresa y estos pueden ser de 3 tipos: de entidad, de session (con estado y sin estado) y dirigidos por mensajes.

Los componentes desarrollados bajo la especificación ejb deben ser desplegados en un contenedor de ejb para su uso. Este contenedor no es mas que una aplicación que normalmente reside en el servidor de aplicaciones y que provee de servicios a nuestros componentes (persistencia, transacciones, seguridad, servicios de red, etc).

No debemos confundir Enterprise Java Beans con Java Beans. Mientras que los primeros son componentes que almacenan lógica de empresa y deben ser desplegados en un contenedor de ejb con el que se comunica para hacer uso de sus servicios, los segundos utilizan una arquitectura para desarrollar componentes con fines generales agrupando datos y funcionalidades comunes y pueden ser ejecutados en cualquier entorno java.

Ejb2 es complejo (múltiples descriptores de despliegue para un ejb, creación de múltiples interfaces, múltiples callbacks usualmente inutilizados). Ejb3 simplifica notablemente el desarrollo, ahora los ejb son POJOs, simplifica la configuración mediante el uso de anotaciones en lugar de descriptores de despliegue, soporte de inyección de dependencias, mejoras en el lenguaje de consultas EJB-QL, no necesitamos tener interfaces de componentes para los ejb’s.

En la web de jboss tenemos una interesante colección de ejemplos ejb3.

Y en la misma web un completo manual sobre ejb3.

A ver si el próximo día dejo algún ejemplillo que hoy estoy un poco vago :-).

10 March, 2008

Curso J2EE (3ª semana) - Hibernate

Logos Hibernate y JavaComenzamos los dos días de esta semana con una pequeña introducción por las principales características de los principales frameworks de persistencia: EJB, JDO, Hibernate, JPA.

Pero una vez pasada esta breve introducción la chicha fué hibernate, que nos ocupó prácticamente los dos días completos.

Hibernate como todo ORM surge por la necesidad de solucionar la existencia de 2 paradigmas diferentes: Modelo de objetos - Modelo relacional. Hibernate es libre, lleva mucho tiempo en el mercado y ha alcanzado un gran estado de madurez, utiliza ficheros xml para mapear las relaciones entre BD y objetos aunque en su última versión 3.0 incluye el uso de anotaciones como alternativa. Hibernate nos ahorra escribir mucho código, emplea POJOS para leer y escribir de la BD y cuenta con un potente lenguaje de consultas "HQL" para aquellas situaciones mas particulares o complejas. Como principal inconveniente un rendimiento necesariamente más bajo que utilizando unas buenas consultas jdbc.


Para comenzar con hibernate necesitaremos el driver jdbc de nuestro motor de BD y el hibernate.jar. A partir de aquí creando los ficheros de configuración ya podemos comenzar a realizar ejemplos básicos.

Debemos saber que el fichero principal de configuración de hibernate es hibernate.cfg.xml que tendrá una estructura como esta, en la que por ejemplo especificamos los parametros de nuestra conexión:

  1. <hibernate-configuration>
  2.   <session-factory>
  3.     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  4.     <property name="connection.url">jdbc:mysql://localhost:3306/library</property>
  5.     <property name="connection.username">root</property>
  6.     <property name="connection.password">admin1</property>
  7.     <property name="connection.pool_size">1</property>
  8.     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  9.     <property name="current_session_context_class">thread</property>
  10.     <property name="show_sql">true</property>
  11.     <property name="hbm2ddl.auto">none</property>
  12.     <mapping class="net.jsanroman.hibernate.model.Post"></mapping>
  13.   </session-factory>
  14. </hibernate-configuration>



Esquema classes (Configuration, SessionFactory, Session) HibernateLa comunicación con el motor de Hibernate la haremos mediante un objeto Session, pero para obtenerlo utilizaremos 2 classes mas: SessionFactory (que contiene los metadatos e información de clases java), Configuration (para la configuración de hibernate: ficheros de mapeo, dialecto de bd..., también inicia hibernate y nos da el acceso al SessionFactory).



Un ejemplo muy sencillo:

  1. private  SessionFactory factory = new Configuration().configure().buildSessionFactory();
  2. Session sess = factory.openSession();
  3. Transaction tx;
  4. try {
  5.   tx = sess.beginTransaction();
  6.   //do some work
  7.   ...
  8.   tx.commit();
  9. }
  10. catch (Exception e) {
  11.   if (tx!=null) tx.rollback();
  12.   throw e;
  13. }
  14. finally {
  15.   sess.close();
  16. }

Ahora que ya tenemos configurada la conexión con nuestro motor de BD a través de hibernate, nos toca crear nuestro modelo de objetos y mapear los xml para asociarlos al modelo de BD. Hibernate utiliza Java Reflection para acceder a las propiedades de nuestros objetos, por lo que cada propiedad debe tener sus correspondientes getters y setters, y cada clase de nuestro modelo su propio constructor vacío.Una vez tenemos nuestro modelo de objetos construido debemos crear un fichero xml por cada objeto (si mapeamos la relación con la BD a través de anotaciones no sería necesario) por convención lo llamaremos NombreObjetoAMapear.hbm.xml. En este enlace tenemos toda la información sobre la sintaxis necesaria en estos xml para poder mapear cualquier tipo de relación. No nos olvidemos de que todos estos xml de mapeo deben referenciarse en el hibernate.cfg.xml de la siguiente forma:

  1. <mapping class="net.jsanroman.hibernate.model.Post">

A partir de aquí ya podemos comenzar a investigar y hacer todas las pruebas necesarias para conocer hibernate mas a fondo: consultas de selección, actualizacion, insercción, eliminación, con HQL, components (misma fila BD a varios objetos; varias filas BD a un objeto), tipos de relaciones (many-to-one; one-to-many; one-to-one; many-to-many), el atributo cascade (save_update; all-delete-orphan), utilizar anotaciones en lugar de xml, etc.

Como conclusión comentar que me ha gustado trabajar con hibernate, me parece mucho mas productivo que la utilización de DAOS al ahorrarnos escribir una buena cantidad de código repetitivo, y la curva de aprendizaje para comenzar a obtener resultados es realmente baja. Para situaciones complejas siempre podemos utilizar su lenguaje de consultas HQL o el propio SQL.

Creo que la semana que entra le tocará a EJB, ya os contaré.

5 March, 2008

Cuidadín con las stables, cake

Logo CakePHPEsta noche he soñado con el bug que soluciona este changeset (https://trac.cakephp.org/changeset/3983).

Resulta que hasta ayer había estado probando la beta de cakephp y todo era una maravilla. Ayer mismo me bajé la stable para comenzar a trabajar en el proyecto final y dejarme de pruebas, la primera en la frente. Nada mas crear mi controlador y mi modelo para el scaffolding aparece el primer error, algo como:

Notice: Trying to get property of non-object in /home/javi/proyectos/php/cakephp/cake/libs/controller/controller.php on line 666

Me aseguré de que había bajado la estable, de las compatibilidades con mi sistema, no encontré mucha información por internet, así que nada me puse a bucear, le seguí el rastro, desde el controller.php pasé al model_php5.php luego al inflector.php al object.php ¿y donde terminé? pues en el class_registry.php.

Resulta que class_registry.php es la clase contenedora de los objectos que representan nuestro modelo. Estos se almacenan en esta clase en un array, ya sabeis clave=>valor. Hasta aquí todo bien. Pero en el controller.php en la linea 666 parece que el objecto que se estaba intentando cargar no existía, estaba vacío. Bien bien ya casi estaba. Solo nos quedaba comprobar como almacenábamos el objecto y como lo recuperábamos. Pero ya era tarde, mi cabeza ya no pensaba, así que decidí dejarlo para hoy, ERROR, mis sueños con el cake casi no me dejan dormir.

Esta mañana con la cabeza fresca lo he encontrado. Resulta que el objecto se estaba almacenando con una clave y se estaba recogiendo con otra diferente. Esto solo pasaba cuando tu modelo tenia varias palabras (ej: BiciCarreras). ¿Demasiado obvio verdad?, si seguro que no era esto, algo estaría haciendo yo mal. Pues NO.

El cake cuando recupera un objecto pasa la clave del mismo por este filtro $key = Inflector::underscore($key); que convierte la clave a minúsculas e incluye un "_" entre palabra y palabra, en nuestro caso nos quedaría (bici_carreras). Pues bien cuando lo almacenaba no pasaba la clave por este filtro y lo único que hacía era convertir la cadena a minúsculas $key = strtolower($key);, con lo que nos almacenaba el objecto con la clave (bicicarreras).

El bug está corregido para la beta 1.2 lo podéis comprobar en este changeset https://trac.cakephp.org/changeset/3983 pero no para la stable 1.1. ¿Curioso? no, tocapelotas.

4 March, 2008

CakePHP + Scaffolding

Logo CakePHPHace aproximadamente un mes que me había animado a conocer un poco mas a fondo cakephp, un framework MVC en y para php. Pero como tantas otras veces me había quedado a medias presionado por la carga de trabajo por aquel entonces. Ahora ha surgido de nuevo la oportunidad y parece que será la definitiva.

Una de las características mas cool (y lo dicen ellos en su manual "Cake's Scaffolding is Pretty Cool"), es lo que ellos llaman Scaffolding, un sistema mediante el cual tu simplemente defines un controlador que trabaja sobre un modelo y cake te crea toda la interfaz de gestión (crear, editar, eliminar elementos) de esa tabla.

Si utilizas una nomenclatura de tablas y campos clave estándar para cake, no necesitaras ni tan siquiera definir un modelo, simplemente será suficiente con crear por ejemplo este código:

  1. <?php
  2. class BiciController extends AppController
  3. {
  4.   var $scaffold;
  5.   //var $uses = array('Auto'); // Si quisieras utilizar un modelo y este tuviera un nombre diferente de Bici
  6. }
  7. ?>

en un fichero bicis_controller.php en la raiz de app/controllers.

Si utilizas tu propia nomenclatura o heredas un diseño de BD ya creado, tienes diferentes variables para configurarlo, en este caso necesitarás crear el BicisController anterior y además el modelo Bici:

  1. <?php
  2. class Bici extends AppModel
  3. {
  4.   var $name         = "Bici";
  5.   var $useTable  = "bicis"; // Aquí podríamos indicar que tabla está utilizando este modelo
  6.   var $primaryKey        = "idbici"; // Si la clave principal de nuestra tabla car es diferente de id
  7. ?>

y lo almacenamos como bici.php en app/models.

Seguro que estáis pensando que para este caso tan sencillo claro que está muy bien, pero, ¿y cuando tenemos un modelo de datos mas complejo con diferentes tipos de relaciones?. Pues también tenemos opciones. Cake soporta 4 tipos de relaciones entre tablas: hasOne, hasMany, belongsTo y hasAndBelongsToMany. Como ejemplo imaginemos que la Bici definida en el modelo anterior es de un solo color. Esta relación la definimos así en la clase modelo Bici:

  1. <?php
  2. class Bici extends AppModel
  3. {
  4.   var $name         = "Bici";
  5.  
  6.   var $belongsTo = array('Color' =&gt;
  7.     array('className'    =&gt; 'Color',
  8.     'conditions'   => '',
  9.     'order'        => '',
  10.     'foreignKey'   => 'color_id'
  11.   )
  12. );
  13. ?>

y debemos definir el modelo del Color:

  1. <?php
  2. class Color extends AppModel
  3. {
  4.   var $name         = "norma";
  5.   var $displayField = "titulo"; // El campo que se mostrará en el select que nos permitirá relacionar el car con el color
  6. }
  7. ?>

Para terminar decir que cakephp es mucho mas que scaffolding. Esta es una forma de crear una interfaz sencilla y de una forma muy rápida, pero cake nos permite crear nuestras propias interfaces, nuestra propia lógica de negocio, validaciones, etc.
Para mas información ya sabéis www.cakephp.org

3 March, 2008

Curso J2EE (1ª, 2ª semana) - eclipse, tomcat, ant, jsp, jstl, jdbc

Logo JavaEste post será el primero de una serie dedicada a contaros lo que voy haciendo en este cursillo al que estoy asistiendo, como os comentaba hace 2 días.

Principalmente me servirán a mi como referencia, por lo que dejaré bastantes enlaces sobre las herramientas que vamos utilizando, y posiblemente en ocasiones los pasos necesarios para realizar determinadas tareas o algún que otro ejemplo de código.

Estas 2 primeras semanas han sido de introducción al mundillo para ir entrando en materia y conocernos un poco, aunque ya se han visto herramientas interesantes:

Hemos comenzado a trabajar con el tomcat 5.5, ya sabeis no? las aplicaciones se recargan automáticamente en webapps sin dar de alta contextos ni ná, cuidadito con los jsp's y la caché almacenada en work, iniciamos/paramos en bin/startup bin/shutdown, mas adelante supongo que veremos como configurar los dominios virtuales, las variables de inicio en catalina.sh. Del tomcat creo que no mucho mas.

Hemos utilizado eclipse como IDE. Yo para trabajar con j2ee siempre me había sentido mas cómodo con netbeans pero ahora ya le estoy cogiendo el truquillo.

Vimos el ciclo de vida de todo servlet:

  1. public void init(ServletConfig config) throws ServletException {
  2. public void service(ServletRequest request, ServletResponse response)
  3. public void destroy() {
  4. public String getServletInfo() {
  5. public ServletConfig getServletConfig() {

Probamos a cargar recursos para internacionalizar nuestras aplicaciones:

  1. String lang = request.getParameter("lang");
  2. Locale locale = new Locale(lang);
  3. ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
  4. String titulo = bundle.getString("titulo");

La sintaxis del web.xml.

En un principio compilamos los servlets desde la línea de comandos pasándole en el classpath la librería de servlets:

  1. java -classpath servlet.jar HolaMundo.java

Luego hemos utilizado ant para automatizar un poquito mas esto y nos creamos un build.xml con una serie de tareas para crear directorios de proyecto, compilar, mover ficheros necesarios a proyecto tomcat, parar-arrancar tomcat, etc:

  1. <!-- Tareas de ejemplo de arranque/parada de tomcat desde ant -->
  2. <target name="tomcat-start">
  3. <java jar="${tomcat.home}/bin/bootstrap.jar" fork="true">
  4. <jvmarg value="-Dcatalina.home=${tomcat.home}"></jvmarg>
  5. </java>
  6. </target>
  7. <target name="tomcat-stop">
  8. <java jar="${tomcat.home}/bin/bootstrap.jar" fork="true">
  9. <jvmarg value="-Dcatalina.home=${tomcat.home}">
  10. <arg line="stop"></arg>
  11. </jvmarg>
  12. </java>
  13. </target>

A continuación hemos hecho un breve repaso por la historia de los jsp's, como se diseñaron para separar la capa de presentación, los problemas que todavía persistían con la inclusión de los scriptles y la primera solución con los javabeans, posteriormente con la generación de tlds propios y el gran avance con las librerias de tld's jstl.

Ya para ir finalizando las 2 semanitas, nos contaron la historia de la persistencia en java y su evolución (a esta parte todavía le queda mucha chicha, supongo que esta semana nos tocará comenzar con algo de ejb, jdo, orm, hibernate, jpa).
Hablamos de los 4 tipos de drivers jdbc en java (Tipo 1 puente jdbc-odbc, Java binario, 100% java protocolo nativo, 100% java protocolo nativo independiente). Hemos hablado de patrones (DAOFactory, Façade) para hacer frente a la diversidad de servidores de BD con drivers diferentes, con tipos diferentes, con sintaxis sql diferente.

Y esto ha sido todo durante estas 2 intensas y productivas semanas. Esperemos que esta lo sea todavía mas, ya os contaré.

Powered by WordPress
Bajo licencia Creative Commons
Contacto sanroman.javier at gmail.com