2 de septiembre de 2010

Spring 3 - Parte 1: Introducción

En la actualidad el desarrollo de aplicaciones empresariales, aunque es más sencillo ya que hay muchas herramientas, APIs, y Frameworks; los cuales aunque son opcionales, el aprender a usarlos nos ayudará a desarrollar nuestras aplicaciones en menos tiempo y a que estas sean más robustas y contengan menos errores.

También se vuelve un poco más complicado porque nuestras aplicaciones deben ser capaces de conectarse con otras aplicaciones y servicios. Además, como desarrolladores, somos los responsables de coordinar cada una de las partes de nuestra aplicación para que todo funcione correctamente.

Por si no fuera suficiente, debemos tomar en cuenta que debemos darle mantenimiento a nuestras aplicaciones, y que en algunos casos será necesario que cambiemos módulos o capas enteras de la misma para mejorarla; como por ejemplo sustituir nuestras consultas JDBC con Hibernate en los casos en los que sea prudente.

Afortunadamente existen super-frameworks que nos ayudan haciéndose cargo de todas o casi todas las “complicaciones” mencionadas anteriormente. Spring es el más popular de estos super-frameworks Java. Nos proporciona varios módulos los cuales abarcan la mayor parte de las cosas que debemos hacer en cualquiera de las capas de nuestras aplicaciones, desde plantillas para trabajar con JDBC o invocación de Web Services y JMS, pasando por sus propias soluciones, ORM o MVC (web), hasta integración con otros frameworks, como Struts 2, Hibernate, JSF, etc. Todo esto de una forma elegante y haciendo uso de muchos buenos principios de programación. Además Spring maneja la infraestructura de la aplicación, por lo que nosotros solo deberemos preocuparnos de la lógica de la misma (y de la configuración de Spring).

En esta serie de tutoriales aprenderemos como usar Spring, en su versión 3, para facilitarnos la vida en el desarrollo de nuestras aplicaciones Java. Para aprender a usar Spring de forma correcta hay que ver muuucha teoría, así que en este primer tutorial hablaremos solo de los conceptos básicos de Spring y explicaré cada una de las partes, junto con su teoría correspondiente, en el post correspondiente.

Spring es, como lo definen sus autores, un framework ligero para construir aplicaciones empresariales. Aunque Spring se encuentra dividido en distintos módulos, cada uno de los cuales se encarga de partes diferentes de nuestra aplicación, no deja de ser un monstruo, ya que es tan grande que alguien podría nunca usar todos estos módulos en aplicaciones pequeñas o medianas; pero en aplicaciones grandes o realmente grandes puede ahorrarnos mucho trabajo ya que puede coordinar todas las partes de la aplicación. Esta separación en módulos nos permite usar solo las partes que necesitamos, sin tener la carga de los que no usemos.

Spring está diseñado para no ser intrusivo, esto significa que no es necesario que nuestra aplicación extienda o implemente alguna clase o interface de Spring (si no lo queremos), por lo que nuestro código de lógica quedará libre y completamente reutilizable para un proyecto sin Spring, o por si debemos quitarlo de una aplicación que ya lo esté usando. Gracias a esto es posible usar un POJO o un objeto Java para hacer cosas que antes solo podían hacerse con EJBs. Sin embargo la utilidad de Spring no es solo para el desarrollo de aplicaciones web, o no solo en el servidor. Cualquier aplicación Java puede beneficiarse del uso de Spring.

Además, si usamos Spring de la forma correcta (lo cual no es difícil) nuestra aplicación quedará dividida en capas bien delimitadas, y con buenas prácticas de programación.

El núcleo de Spring está basado en un principio o patrón de diseño llamado Inversión de Control (IoC por sus siglas en inglés). Las aplicaciones que usan el principio de IoC se basan en su configuración (que en este caso puede ser en archivos XML o con anotaciones como en Hibernate) para describir las dependencias entre sus componentes, esto es, los otros objetos con los que interactúa. En este caso “inversión” significa que la aplicación no controla su estructura; permite que sea el framework de IoC (en este caso Spring) quien lo haga.

Por ejemplo, supongamos que tenemos una clase “AlmacenUsuario”, que depende de una instancia de una clase “UsuariosDAO” para realizar su tarea. “AlmacenUsuario” crea una instancia de “UsuariosDAO” usando el operador “new” u obtiene una de algún tipo de Fabrica. Usando la técnica de IoC, una instancia de “UsuariosDAO”, o una subclase de esta, es proporcionada a “AlmacenUsuario” en tiempo de ejecución por el motor de Spring. En este caso “UsuariosDAO” también podría ser una interface y Spring se encargará de proporcionarnos una instancia de una clase que implemente esa interface. Esta inyección de dependencia en tiempo de ejecución ha hecho que a este tipo de IoC se le dé el nombre más descriptivo de inyección de dependencia (DI por sus siglas en inglés). El concepto importante es que los componentes no saben cuál implementación concreta de otros componentes están usando; solo ven sus interfaces.

El uso de interfaces y DI son mutuamente benéficos, ya que hace más flexible y robusta nuestra aplicación y es mucho más fácil realizar pruebas unitarias. Pero la complejidad de escribir código que maneje las dependencias entre los componentes de una aplicación diseñada para usar interfaces puede llegar a ser mucho y esto, además, hace que los desarrolladores tengamos que escribir aún más código.

Afortunadamente, usando DI reducimos la cantidad de código extra que debemos escribir, para un diseño basado en interfaces, casi a cero.

En el contexto de DI, Spring actúa como un contenedor que proporciona las instancias de las clases de nuestra aplicación todas las dependencias que necesita, pero en una forma no intrusiva y automática. Todo lo que debemos hacer es crear un archivo de configuración que describa las dependencias; Spring se hará cargo del resto.

Como dije antes: Spring es un contenedor ya que no solo crea los componentes de nuestra aplicación, sino porque contiene y maneja al ciclo de vida y configuración de estos componentes. En Spring, podemos declarar cómo debe ser creado cada uno de los objetos de nuestra aplicación, cómo deben ser configurados, y cómo deben asociarse con los demás.

La implementación de DI de Spring se enfoca en el acoplamiento débil: los componentes de nuestra aplicación deben asumir lo menos posible acerca de otros componentes. La forma más fácil de lograr este bajo acoplamiento en Java es mediante el uso de Interfaces. Como cada componente de la aplicación solo está consciente de la interface de otros componentes, podemos cambiar la implementación del componente sin afectar a los componentes que usan el nuevo componente. Hablaré un poco más de esto cuando veamos los ejemplos.

El uso de DI tiene como beneficios, además de lo que ya he mencionado arriba, los siguientes:

  • Reduce el código pegamento: Esto quiere decir que reduce dramáticamente la cantidad de código que debemos escribir para unir los distintos componentes. Aunque algunas veces esté código puede ser tan simple como usar el operador “new” para instanciar un nuevo objeto, otras puede ser más complejo, como realizar una búsqueda de dicha dependencia en un repositorio a través de JNDI, como en el caso de los recursos remotos. En esto caso, el uso de DI puede reducir de forma dramática la cantidad de código pegamento (o glue code) proporcionando búsquedas automáticas.
  • Externaliza dependencias: Como es posible colocar la configuración de dependencias en archivos XML podemos realizar una reconfiguración fácilmente, sin necesidad de recompilar nuestro código. Gracias a esto es posible realizar el cambio de la implementación de una dependencia a otra (como en el ejemplo de Hibernate que mencioné antes)
  • Las dependencias se manejan en un solo lugar: Toda la información de dependencias es responsabilidad de un solo componente, el contenedor de IoC de Spring, haciendo que este manejo de dependencias más simple y menos propenso a errores.
  • Hace que las pruebas sean más fáciles: Nuevamente, como nuestras clases serán diseñadas para que sea fácil el reemplazo de dependencias, podemos proporcionar mocks o dummies, que regresen datos de prueba, de servicios o cualquier dependencia que necesite el componente que estamos probando.

Como podemos ver, el uso de DI nos proporciona muchos beneficios, pero no sin sus correspondientes desventajas. En particular, es difícil ver qué implementación particular de una dependencia está siendo usada para qué objeto, especialmente para alguien que no está familiarizado con esta forma de trabajo.

¿Y por qué tanto hablar de DI? Pues porque estos dos conceptos (IoC y DI) son los puntos centrales alrededor del cual gira todo en Spring, así que es mejor entenderlos desde el principio ^_^.

Como dije: Spring está dividido en alrededor de 20 módulos y colocados en los siguientes grupos:

  • Contenedor Central (Core Container)
  • Acceso a Datos / Integración
  • WEB
  • AOP (Programación Orientada a Aspectos)
  • Instrumentación
  • Pruebas

Estos grupos se muestran en la siguiente imagen:



A lo largo de estos tutoriales trataré de explicar la mayor cantidad de módulos. Pero como dije antes: Spring es en realidad un monstruo. Así que probablemente cuando termine de explicarlos todos, ya habrá salido una nueva versión, así que me centraré solo en los más importantes y en su integración con otros frameworks que comencemos a usar en otros tutoriales.

En general, estas son algunas de las características de Spring:

  • Simplificación de la programación orientada a aspectos.
  • Simplificación del acceso a datos.
  • Simplificación e integración con JEE
  • Soporte para planificación de trabajos.
  • Soporte para envió de mail.
  • Interacción con lenguajes dinámicos (como BeanShell, JRuby, y Groovy).
  • Soporte para acceso a componentes remotos.
  • Manejo de Transacciones.
  • Su propio framework MVC.
  • Su propio Web Flow.
  • Manejo simplificado de excepciones.

La versión 3 de Spring es una versión revisada y mejorada de la versión estable anterior (2.5), que incluye nuevas características, entre las que se incluyen:

  • Soporte para Java 5: Proporciona configuración basada en anotaciones y soporta características como varargs y generics, además la parte web es compatible con las versiones 1.4 y 5 de Java EE. Debido a esta nueva característica, ahora es necesario tener el JRE versión 5 o superior.
  • Lenguaje de Expresiones (SpEL): En esta nueva versión se incluye un lenguaje de expresiones que puede ser usando cuando se definen beans, tanto en XML como con anotaciones y también da soporte a través de todos los módulos de Spring.
  • Soporte para Servicios Web REST: Ahora Spring soporte servicios web de tipo REST.
  • Soporte para Java EE6: Ofrece soporte de características como JPA 2.0, JSF 2.0 y JRS 303 (validaciones de Beans).
  • Soporte para bases de datos embebidas: Un soporte conveniente para bases de datos embebidas como HSQL, H2 y Derby.
  • Soporte para formateo de datos mediante anotaciones: Ahora los campos de fecha, divisas, etc., serán formateados automáticamente y convertidos usando anotaciones.
  • Nueva organización de los módulos: Los módulos han sido revisados y separados en diferentes paquetes, mas organizados, de acuerdo a su funcionalidad. Para que se den una idea, estos son los nuevos paquetes:
    • org.springframework.aop
    • org.springframework.beans
    • org.springframework.context
    • org.springframework.context.support
    • org.springframework.expression
    • org.springframework.instrument
    • org.springframework.jdbc
    • org.springframework.jms
    • org.springframework.orm
    • org.springframework.oxm
    • org.springframework.test
    • org.springframework.transaction
    • org.springframework.web
    • org.springframework.web.portlet
    • org.springframework.web.servlet
    • org.springframework.web.struts

A lo largo de estos tutoriales veremos algunos de estos paquetes. Aunque este post, como ya se habrán dado cuenta es solo de teoría, crearemos la librería para NetBeans de Spring que estaremos usando en esta serie de tutoriales.

Así que lo primero que haremos es abrir el NetBeans. En realidad el NetBeans 9 ya tiene una biblioteca de Spring 3, la 3.0.2.



Pero han salido actualizaciones desde esta versión (actualmente la versión más nueva es la 3.0.4). Así que lo que haremos es crear una nueva biblioteca que hará uso de los jars que necesitamos (y los cuales iremos incrementando en cada tutorial).

Bajamos la última versión de Spring de su página de descargas. También necesitaremos el archivo “commons-logging-api-1.1.1.jar” que podemos encontrar en la página de descarga de commons-logging, en el archivo "commons-logging-1.1.1-bin.zip”, tal y como lo hicimos en los tutoriales de JasperReports.

Una vez que hayamos bajado el archivo de Spring, lo descomprimimos y veremos que tiene un subdirectorio “dist” el cual contiene todos los jars de Spring para cada uno de sus módulos. Vamos al NetBeans y nos dirigimos al menú “Tools -> Libraries”.



En la ventana que se abre presionamos el botón “New Library...”:



En esta nueva ventana colocamos como nombre de la biblioteca "Spring3" y como tipo dejamos "Class Libraries":



Ahora que tenemos nuestra biblioteca , presionamos el botón “Add Jar/Folder” para agregar los nuevos archivos que conformarán la biblioteca:



Agregamos a la biblioteca los siguientes archivos:

  • org.springframework.asm-3.0.4.RELEASE.jar
  • org.springframework.beans-3.0.4.RELEASE.jar
  • org.springframework.context-3.0.4.RELEASE.jar
  • org.springframework.core-3.0.4.RELEASE.jar
  • org.springframework.expression-3.0.4.RELEASE.jar
  • commons-logging-api-1.1.1.jar (que bajamos aparte)

Con estos es suficiente para hacer nuestros hola mundo iniciales :D. Una vez seleccionados estos archivos, nuestra biblioteca debe verse así:



Presionamos el botón “OK” y nuestra biblioteca estará lista para ser usada… en los siguientes tutoriales ^_^.

Por el momento hemos cubierto una muy pequeña parte de la teoría con respecto a Spring 3, que iremos ampliando en los siguientes posts, así que no desesperen, pronto comenzaremos a usar este framework, que muchas alegrías (y dolores de cabeza) nos dará a más de uno.

No olviden dejar cualquier comentario, duda o sugerencia en la sección de comentarios.

Saludos.

Entradas Relacionadas: