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).