Cuando usar / no usar Hibernate

8 comentarios
No me gustan los fanáticos. Y menos aún en nuestro mundo del desarrollo de software. Que si Linux o Windows. Que si Java es lento. Que si los EJBs son un infierno. Que si servicios web o REST. Que si Java se muere. Que si PHP, Ruby, .Net, etc... Son debates que he leido muchas veces y parecen más una discusión política o religiosa que un debate técnico. Y uno de estos debates eternos es el de si usar Hibernate o JDBC a pelo. Tomando a Hibernate como la estrella de los mapeadores objeto-relacional (ORM).

Si hay algo cierto en nuestro mundillo es que pocas son las preguntas que pueden responderse con sí o no. No hay que ser tan soberbio para pensar que cómo uno hace las cosas es la mejor manera posible para todos los casos existentes. Es responsabilidad de un buen ingeniero software analizar objetivamente la conveniencia de usar una tecnología o no.

Analicemos la conveniencia de usar Hibernate. Vaya por adelantado que he usado y uso Hibernate con excelentes resultados para muchos, que no todos, de mis proyectos. Por eso empezaré por las razones a tener en cuenta para no usar Hibernate:
  • El modelo de datos ya existe, no se puede modificar y es complejo. Mapear el modelo de datos OO que has diseñado con un modelo de datos relacional existente no es sencillo. Mucho cuidado con los delete y con los triggers.

  • Una buena parte de las claves primarias del modelo de datos son compuestas. Las claves compuestas en Hibernate son un coñazo, hasta el típico Provincia-Municipio te puede complicar la vida unas horas.

  • Las operaciones de acceso a datos a realizar son en su mayoría de lectura. Vale, no tienes que escribir SQL, pero tienes que escribir HQL y no hay tanta diferencia.

  • El equipo no tiene experiencia en Hibernate ni tiempo para formarse. Aunque en los tutoriales parezca una tecnología mágica y sencilla, dominarla precisa de tiempo y esfuerzo. Muchas de las críticas vertidas sobre Hibernate, en especial en temas de rendimiento, vienen de personas que no le han dedicado el esfuerzo que precisa.

  • Es crítico optimizar las consultas realizadas sobre la base de datos. Por crítico me refiero a aplicaciones públicas de Internet con al menos cientos de usuarios concurrentes, donde los milisegundos y la latencia cuentan, nunca a comunes aplicaciones de gestión dentro de una intranet, donde se prefiere ahorrar en días o semanas de desarrollo antes que en unos milisegundos imperceptibles en ejecución.

En realidad el objetivo principal para usar Hibernate es recortar tiempo de desarrollo. Si todo o casi todo lo anterior no se da, será fácil cumplirlo. Pero además existen otros casos donde usar Hibernate es recomendable:
  • Todos (o casi todos) los dao deben implementar las operaciones CRUD (Create, Read, Update y Delete). En este caso sí que te puedes ahorrar mucho tiempo y mucho SQL.

  • La aplicación tiene formularios de búsqueda complejos. Reconozco que el api Criteria de Hibernate es una de mis debilidades.

  • La aplicación debe funcionar sobre diferentes bases de datos. Ésta sí es una buena razón para querer abstrarse del SQL.

  • Quieres tener la puerta abierta para usar caché sin complicarte. La integración de Hibernate con algunos sistemas de caché como EHCache es inmediata.

Autenticación HTTP Basic en cliente webservice con Axis2

1 comentarios
Es más que habitual encontrarse con que el uso de los servicios web está restringido. La forma más común y sencilla de implementar (y de romper) es la autenticación HTTP Basic, consistente en el típico par usuario, password.

Usar la autenticación HTTP Basic en un cliente webservice con Axis2 es inmediato. Supongamos que ya hemos generado el stub mediante wsdl2java y tenemos la url del endpoint más el par usuario, password. El código para inicializar el cliente webservice sería el siguiente:


Options options = new Options();
EndpointReference targetEPR = new EndpointReference(urlEndpoint);
options.setTo(targetEPR);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(usuario);
auth.setPassword(password);
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
stub._getServiceClient().setOptions(options);


También podriamos estar usando un cliente ServiceClient AXIOM a pelo. Una opción poco ortodoxa pero práctica para mensajes simples. En este caso sería todo igual salvo el último paso:


ServiceClient serviceClient = new ServiceClient();
serviceClient.setOptions(options);

Cómo generar un cliente webservice con Ant y Axis2

2 comentarios
Crear un cliente webservice con Axis2 es relativamente sencillo. En el pasado ya realicé un tutorial donde expliqué cómo hacerlo con ayuda del plugin Codegen Wizard de Axis2 para Eclipse. Crear un cliente webservice con Ant también es muy sencillo a poco que sepas algo de Ant, una herramienta indispensable antes o después.

El proceso consiste en ejecutar la herramienta WSDL2Java de Axis2 sobre un fichero WSDL para generar el código Java del Stub y las clases OXM (mapeador objeto-XML) de los mensajes del servicio web para posteriormente copiar el código generado al proyecto. Y todo con un simple script de Ant.

Requisitos

Será necesario tener instalado Axis2, basta con bajarse la versión Standard y descomprimirla, y Ant, el propio eclipse ya lleva incorporada una versión de Ant.

Definición de propiedades

El script usará las siguientes propiedades:
  • axis2.home: directorio donde está instalado Axis2.
  • output.wsdl2java.dir: directorio donde el wsdl2java generará el código.
  • src.dir: directorio dentro del proyecto donde se copiará el código generado.
  • wsdl.uri: ruta hasta el fichero wsdl.
  • stub.package.name: nombre del paquete para la clase Stub.
  • xsd.namespacetopackages: equivalencia entre los namespaces de los schemas xsd que definen los mensajes y los correspondientes paquetes donde generar las clases OXM.
  • synconly: booleano para indicar si queremos generar un Stub sólo para peticiones síncronas y no asíncronas.

Las propiedades pueden definirse en el propio script o externalizarse a un fichero de propiedades (todas menos src.dir). Un ejemplo de lo primero:
<property name="axis2.home" value="/deps/axis2-1.4.1" />
<property name="output.wsdl2java.dir" value="build/codegen" />
<property name="src.dir" value="src" />
<property name="wsdl.uri" value="resources/wsdl/myWsdl.wsdl" />
<property name="stub.package.name" value="ws.client" />
<property name="xsd.namespacetopackages" value="http://myService/xsd=ws.client.xsd" />
<property name="synconly" value="true" />

Definición del task wsdl2java

El task wsdl2java no es un task incluido en la distribución de Ant, por tanto hay que importar su definición. Para ello hay que cargar en el classpath los jars de Axis2 y luego hacer la definición.

<path id="axis2.classpath">
<fileset dir="${axis2.home}/lib">
<include name="**/*.jar" />
</fileset>
</path>

<taskdef name="wsdl2java" classname="org.apache.axis2.tool.ant.AntCodegenTask"
classpathref="axis2.classpath" />

Ejecutar WSDL2Java

Finalmente llega el momento de definir el target que ejecutará el wsdl2java. Antes preparará el directorio de salida y después copiará el código generado al proyecto. Aquí está:

<target name="run-wsdl2java-client"
description="Genera un cliente webservice apartir de un wsdl">

<mkdir dir="${output.wsdl2java.dir}" />
<delete dir="${output.wsdl2java.dir}" includeemptydirs="true" />

<wsdl2java
output="${output.wsdl2java.dir}"
wsdlfilename="${wsdl.uri}"
synconly="${synconly}"
unpackClasses="true"
serverSide="false"
databindingName="adb"
packageName="${stub.package.name}"
namespacetopackages="${xsd.namespacetopackages}"
/>

<copy todir="${src.dir}" overwrite="true">
<fileset dir="${output.wsdl2java.dir}/src">
<include name="**/*.java"/>
</fileset>
</copy>
</target>

El parámetro unpackClasses="true" indica que las clases OXM deben generarse como clases independientes y no como clases internas de la clase Stub.
El parámetro serverSide="true" indica que queremos generar un cliente webservice.
El parámetro databindingName="adb" indica el motor databinding XML a usar para generar las clases OXM. En este caso es ADB (Axis DataBinding). No está parametrizado, este script sólo funciona con ADB.

Si se usa XMLBeans se genera además código Java para todos los tipos de datos XSD y unos ficheros binarios usados por las clases OXM. Cada cosa va en un directorio diferente y todos deben incluise en el classpath del proyecto. Lo ideal es compilar tanto las clases OXM como las clases de tipos XSD y crear un jar con los fuentes, los class y estos ficheros binarios para añadirlo al directorio lib del proyecto.

Ha sido fácil y rápido, ¿no? Ya sólo queda probarlo. En el directorio samples del Axis2 encontrareis varios ficheros wsdl para probar. Para ejecutar el script Ant a mi me encanta la vista Ant del Eclipse.

El arte de la gestión de equipos

2 comentarios
En nuestro mundo de desarrollo de software formarte en tecnología es sencillo y barato. Ya sea un nuevo lenguaje de programación, el último framework o herramienta, existe una gran cantidad de material didáctico disponible de gran calidad, o bien en forma de libros o directamente en internet. Sólo hay que poner un poco de interés y un ordenador donde experimentar y poner en práctica las supuestas bondades de una tecnología, sin más costes y, sobretodo, con riesgos cero.

Otro tema diferente es ya la gestión de equipos. Primero, porque se trata de una disciplina que tiene, en mi opinión, más de arte que de ciencia, debido sobretodo al componente psicológico que tiene siempre tratar con personas. Lo que funciona con uno, no tiene porqué funcionar con otros.

Segundo, no se puede practicar. Puedes leer todo lo que quieras, planificar y meditar sobre lo que vas a hacer. Pero no puedes practicar o experimentar. Llegado el momento tendrás que actuar y tus acciones no se pueden deshacer. No hay ctrl-Z y no sabes si algo funcionará hasta que lo hagas. Riesgos todos.

Tercero, la formación no es gratis. Lo más barato son los libros (al menos yo no conozco nada gratis de calidad). De seminarios, cursos, etc. mejor no hablamos. Y aunque libros hay muchos, no es fácil encontrar uno bueno. Unos desprenden un cierto tufillo a libro de autoayuda, otros se centran en una metodología en concreto y otros evitan por completo la parte psicológica, en especial el carácter distinto de, nosotros, los informáticos.
Me pasa mucho, no se si soy demasiado escéptico, que no puedo evitar preguntarme por los méritos del autor, si sus teorías son fruto de auténticos casos de éxito y cuáles serían las personalidades de sus compañeros, clientes, jefes, etc.

Así que, además de libros sobre el tema, siempre estoy atento para aprender de lo que me rodea, como éxitos y errores de antiguos jefes, errores propios, experiencias de compañeros/amigos y otros. Algunos de estos otros, estoy seguro que os sorprenderían. Uno de los últimos ha sido el libro El arte de la guerra, de Sun Tzu, que compré en un puesto de la feria del libro de mi ciudad.


Antes de que paseis a divagar sobre lo que fumo, os dejo algunas frases inspiradoras:

El mando ha de tener como cualidades: sabiduría, sinceridad, benevolencia, coraje y disciplina.
Una definición de liderazgo concisa pero completa de hace más de 2500 años.


Una vez comenzada la batalla, aunque estés ganando, de continuar por mucho tiempo, desanimará a tus tropas y embotará tu espada. [...] Nunca es beneficioso para un país dejar que una operación militar se prolongue por mucho tiempo.
Ya entonces tenian claras las ventajas de las iteraciones cortas.


Cuando hay entusiasmo, convicción, orden, organización, recursos, compromiso de los soldados, tienes la fuerza del ímpetu, y el tímido es valeroso. Así es posible asignar a los soldados por sus capacidades, habilidades y encomendarle deberes y responsabilidades adecuadas. El valiente puede luchar, el cuidadoso puede hacer de centinela, y el inteligente puede estudiar, analizar y comunicar. Cada cual es útil.
Estar bien organizado nos hace mejores a todos, en especial a los de menos talento. Saber ver y aprovechar los puntos fuertes de tus compañeros es vital para la salud de los proyectos y del propio equipo.


Los que anticipan, se preparan y llegan primero al campo de batalla y esperan al adversario están en posición descansada; los que llegan los últimos al campo de batalla, los que improvisan y entablan la lucha quedan agotados. [...] La dificultad de la lucha armada es hacer cercanas las distancias largas y convertir los problemas en ventajas.
Otra habilidad básica en un perfil senior es la de anticiparse a posibles problemas, en especial los tiempos muertos por la no disponibilidad de recursos o sistemas externos.


La energía de la mañana está llena de ardor, la del mediodía decae y la energía de la noche se retira.
Las tareas que requieran más atención dejalas para primera hora. Nunca fijes una reunión a última hora o la gente estará más pendiente de irse a su hora que otra cosa. Al menos a mi me pasaba.


A menos que tu corazón esté totalmente abierto y tu mente en orden, no puedes esperar ser capaz de adaptarte a responder sin límites, a manejar los acontecimientos de manera infalible, a enfrentarte a dificultades graves e inesperadas sin turbarte, dirigiendo cada cosa sin confusión.
Evita los prejuicios y deja los problemas personales en casa.


No presiones a un enemigo desesperado.
A veces un tirón de orejas a tiempo hace milagros, pero no abuses o nunca más te servirá con nadie. Nunca obligues a nadie a nada, intenta que lo decidan ellos, aunque sólo sea porque no tenian otra opción (pero al menos tenian 1 opción).


Las consideraciones de la persona inteligente siempre incluyen el analizar objetivamente el beneficio y el daño. Cuando considera el beneficio, su acción se expande; cuando considera el daño, sus problemas pueden resolverse.
Aplicable a decisiones tecnológicas y detección/contingencia de riesgos pero también respecto a tu relación con el resto del equipo.


Las murmuraciones describen la expresión de los verdaderos sentimientos; las faltas de disciplina indican problemas con los superiores. Cuando el mando ha perdido la lealtad de las tropas, los soldados se hablan con franqueza entre sí sobre los problemas con sus superiores.
Los rumores, cotilleos, etc. son el síntoma y no la causa de una situación de mal rollo en un equipo.


Ser violento al principio y terminar después temiendo a los propios soldados es el colmo de la ineptitud.
Esta me encanta.


Mándalos con humanidad y benevolencia, unifícalos de manera estricta y firme. Cuando las órdenes se dan de manera clara, sencilla y consecuente a las tropas, éstas las aceptan. Cuando las órdenes son confusas, contradictorias y cambiantes las tropas no las aceptan o no las entienden.Cuando las órdenes son razonables, justas, sencillas, claras y consecuentes, existe una satisfacción recíproca entre el líder y el grupo.
Lo difícil es hacerlo...


Estas son las seis maneras de ser derrotado. La comprensión de estas situaciones es la responsabilidad suprema de los generales y deben ser consideradas. La primera es no calibrar el número de fuerzas; la segunda, la ausencia de un sistema claro de recompensas y castigos; la tercera, la insuficiencia de entrenamiento; la cuarta es la pasión irracional; la quinta es la ineficacia de la ley del orden; y la sexta es el fallo de no seleccionar a los soldados fuertes y resueltos.
Más habilidades básicas a dominar: estimar, priorizar, formación, planificar, controlar, negociar y seleccionar.


Cuida de tus soldados como cuidas de tus queridos hijos, y morirán gustosamente contigo. Pero si eres tan amable con ellos que no los puedes utilizar, si eres tan indulgente que no les puedes dar órdenes, tan informal que no puedes disciplinarlos, tus soldados serán como niños mimados y, por lo tanto, inservibles.
Ser responsable de un equipo es un cargo a veces muy solitario, no se debe caer en el error de intentar hacerse el simpático o ir de colega porque a la larga acaba fatal.

Esto es todo, si os pica la curiosidad, el libro está disponible, gratis y en español en este enlace desde el portal de la aplicación saiku de gestión de proyectos (no la he probado).

Qué driver JDBC usar para cada versión de Oracle Database

3 comentarios

Una de mis fuentes favoritas de expedientes X en el desarrollo aplicaciones es la integración con base de datos en entornos de pruebas y producción. Me ha pasado de todo, uno de los peores fue un firewall que mataba en silencio conexiones inactivas. Pero la gran mayoría han sido problemas aparentemente sin explicación por culpa de la versión del driver JDBC utilizado. Saber qué driver JDBC instalar en tu servidor de aplicaciones no debe tomarse a la ligera.

En las grandes organizaciones es bastante habitual encontrarse con Oracles 8 y 9, cuyas inversiones aún están amortizándose. No es que sea una queja, son robustas bases de datos con unas fantásticas herramientas.
A la hora de definir el entorno de desarrollo preguntas qué versión de Oracle y de Java usan bajo qué versiones de Oracle y Java debe funcionar la aplicación, te bajas el driver JDBC thin adecuado para las versiones mínimas (si te lo pasan mucho mejor!) y ala, a trabajar. [ACTUALIZADO 28082008]

Ésta es la teoría. A la hora de ponerla en práctica, te vas a la página para descargar los drivers JDBC Oracle y te encuentras con que existe un enlace para cada cada gran versión de Oracle Database. La impresión que te llevas es que si tienes, pej un Oracle 9.2.0.6, tienes que seleccionar el enlace de Oracle 9.2.x drivers. Bueno, esto es correcto pero sólo en parte.

Si consultamos la matriz de interoperabilid entre drivers y database veremos que todas las versiones de los drivers JDBC funcionan para todas las versiones de Database desde la versión 9.2.x. Para más información, en especial para versiones anteriores, se puede consultar la FAQ de JDBC.

Entonces, ¿por qué tanta versión?

Las diferencias entre las versiones del driver JDBC radican principalmente en las funcionalidades JDBC que implementan y en las versiones Java bajo las que funcionan.

Así por ejemplo, la versión 11 del driver JDBC thin Oracle sólo está disponible para Java 5 y 6, si quieres usar auto-generated keys tendrás que usar una versión 10 o superior y si quieres tener soporte completo para tipos LOB (CLOBs y BLOBs) olvídate del classes12.jar.

Lo más recomendable es utilizar la última versión del driver JDBC compatible con tu versión de Java.

Quiero creer

Hasta aquí la parte sencilla. Las sorpresas vendrán cuando tu aplicación pase de tu entorno controlado de desarrollo a uno de pruebas del cliente y empiecen a sucederse los expedientes X con tareas de acceso a la base de datos.

Mi consejo es comprobar la versión del driver JDBC instalada en el servidor de pruebas. Si es una versión antediluviana seguramente ya tienes la causa. La solución es convencer al responsable de Sistemas del cliente de actualizar el driver JDBC pero esto será una dura prueba para tus habilidades de negociación...

Lectura recomendada: Spring in Action 2

3 comentarios

Uno de mis propósitos profesionales para este año 2008 era conocer a fondo Spring y a estas alturas de año puedo decir que lo he cumplido. A día de hoy ya son 2 los proyectos que hemos iniciado usando Spring como framework principal. Sin duda ha sido todo un acierto. Podría dedicar muchas líneas a elogiar las virtudes del framework, pero sería repetir lo que puede encontrarse en internet y en literatura sin problemas.

Sí quiero aprovechar para recomendar uno de los libros que leí durante mi fase de autoformación y que para mí está unos puntos por encima del resto de literatura sobre Spring. Se trata de Spring in Action Second Edition, de Craig Walls. Es un libro muy completo, prueba de ello son sus más de 700 páginas y el tiempo que ha pasado en mi mesita de noche sin volverse un tostón. Sin duda se hace muy ameno de leer, el inglés es sencillo, los ejemplos son muy didácticos y el estilo es muy alegre.

Leyéndolo se puede aprender sin mucho esfuerzo lo que son las bases de Spring, la inyección de dependencias y la programación orientada a aspectos, además de otros temas imprescindibles en cualquier libro de Spring, como la integración con bases de datos (JDBC, JPA, Hibernate, iBATIS, transacciones y cachés), cómo usar EJBs, JNDI, JMX y JMS con Spring, integración con los frameworks web Struts, Struts2, Tapestry y JSF, planificación de tareas con Quartz, Testing y por supuesto su propio módulo web Spring MVC y Spring Web Flow.

Hasta aquí lo que puede encontrarse más o menos, mejor o peor contado, con más profundidad o menos en cualquier otro libro de Spring. Todo es cuestión de gustos. Pero Spring in Action 2 además incluye capítulos para los nuevos proyectos de Spring Web Services y Security (Acegi Security) para los que no es tan fácil encontrar documentación de calidad. Y también un capítulo no muy común sobre cómo usar DWR en Spring que me vino de maravilla al ser el framework Ajax con el que trabajamos.

Sin duda un gran libro para conocer Spring, todo está muy bien explicado y con unos ejemplos estupendos. Y para los más curiosos, desde la web se pueden descargar 2 capítulos gratis.