SPRING

Liberado Spring 3.2

Novedades que trae la versión 3.2:
  • Mejorado el soporte para Java SE 7 dentro del framework así como mejoras para CGLIB 3.0, ASM 4.0 y AspectJ 1.7.
  • Mejoras en la concurrencia en todo el framework, evitando el uso de sincronización siempre que sea posible - en particular para los beans con ámbito prototype.
  • Se permite las anotaciones @Autowired y @Value para ser usadas como meta-anotaciones (para construir anotaciones de inyección customizadas combinadas con qualifiers específicos).
  • Soporte para anotaciones de definición @Bean customizadas en clases @Configuration (combinadas con qualifiers específicos, @Lazy, @Primary, etc).
  • Procesamiento de MVC asíncrono en Servlet 3.0, con métodos manejadores Spring MVC siendo capaces de devolver Callables y DeferredResults.
  • Inclusión de proyectos de testing Spring MVC formerly-standalone, permitiendo la primera clase de testeo en aplicaciones Spring MVC.
  • Soporte para la carga de WebApplicationContexts en el TestContext y otras mejoras para las pruebas de aplicaciones web.
  • Apoyo para JCache 0,5 (JSR-107) como backend para la abstracción de la caché de Spring.

Para más detalles, en particular las muchas mejoras de Spring MVC, échale un vistazo al link New Features and Enhancements in Spring Framework 3.2 de la documentación.

Lo nuevo de Spring 3.1

Aquí os dejamos las novedades que trae la versión 3.1:
  • Soporte para Hibernate 4.0.
  • Soporte para Quartz 2.0.
  • Soporte para configurar el contenedor de Servlets 3.0 mediante código (en lugar de usar web.xml).
  • Soporte para “consumes” and “produces” en la anotación @RequestMapping para especificar el content-type.
  • Equivalentes en código para espacios de nombres de Spring XML.
  • Soporte completo de TestContext framework para clases con la anotación Configuration.

Libro recomendado

Desde aquí recomiendo la lectura del libro "Spring. Tercera Edición" (Anaya Multimedia) de Craig Walls.


Resumen de Spring 3.0
En primer lugar, dividiremos los capítulos vistos en el libro:
  1. Antecedentes - EJB vs Spring, características, módulos, tipos de contextos, ciclo de vida de un bean y configurar Spring con XML o con anotaciones.
  2. Conexión de un bean - <bean>, ámbitos del bean, <property>, <null/>, SpEL.
  3. Minimizar la configuración del XML
  4. AOP - consejo, pto de cruce, pto de corte y aspecto. Declaración (xml o anotaciones).
  5. ORM - DAO, excepciones, plantillas, origen de datos, clases de apoyo a DAO, integración ORM (xml o anotaciones).
  6. Gestión de transacciones - transactionManager, tipos, declaración (xml o anotaciones).
  7. MVC - Configuración, controladores, ViewResolver, Pantalla inico, formularios,  validación y tratamiento de archivos.
  8. Spring Web Flow - Configuración, componentes (estados, transiciones y datos), declaración de variables, ámbitos y seguridad en Web Flows.
  9. Spring Security - configuración de filtros, interceptar solicitudes, autenticación, protección de métodos.
  10. Servicios remotos - SOAP y JAX-WS.
  11. REST
  12. Complementos extra - externalizar la configuración, conexión de objetos, envío de mails y tareas en segundo plano.

Contenido de Spring 3.0
1. ANTECEDENTES
Antecedentes      Java Beans (POJO) -> EJB -> Spring
EJB -> Muy laborioso ya que introducía métodos del ciclo de vida
Características Spring 3:
 - Desarrollo ligero (POJO)
 - Acoplamiento débil (DI)
 - Programación declarativa (AOP)
 - Reducción de código (Plantillas)


Módulos Spring 3:
 - DI -> otorga a un objeto sus dependencias para que no las obtenga por sí solo.
 - AOP -> atajar problemas transversales.
 - Plantillas -> reducir código (ej. JDBCTemplate)
 - Contenedores de Beans -> donde residen los objetos de la aplicación y se administra su ciclo de vida (desde new hasta finalize).


Tipos de contenedores:
 - BeanFactory -> fábricas de beans. Básicos. DI.
 - ApplicationContext -> contextos de aplicación (BeanFactory + Servicios).


Tipos de contexto de aplicación:
 - ClassPathXmlApplicationContext -> xml en el classpath.
 - FileSystemXmlApplicationContext -> xml en el filesystem.
 - XmlWebApplicationContext -> xml en aplicación web.


Para cargar el contexto haríamos,
ApplicationContext ctx = new FileSystemXmlApplicationContext("c:/foo.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext("foo.xml");
Para recuperar un bean del contenedor, ejecutaríamos su método getBean().


Ciclo de vida de un bean:
1) Instanciar un bean.
2) Inyecta valores en sus propiedades.
3) Si el bean implementa BeanNameAware, se proporciona el ID del bean al método setBeanName().
4) Si el bean implementa BeanFactoryAware, se ejecuta el método setBeanFactory proporcionando el mismo la fábrica de beans.
5)  Si el bean implementa ApplicationContextAware, se ejecutará el método setApplicationContext() proporcionando una referencia del contexto.
6) Si el bean implementa BeanPostProcessor, se ejecuta el método postProcessBeforeInitialization().
7) Si el bean implementa InitializingBean, se ejecuta el método afterPropertiesSet(). Si el bean se ha declarado con un init-method, entonces se ejecuta el método de inicialización especificado.
8) Si el bean implementa BeanPostProcessor, se ejecuta el método postProcessAfterInitialization().
9) El bean está listo para la aplicación y permanecerá en el contexto hasta que se elimine.
10) Si algún bean implementa la interfaz DisposableBean, Spring ejecutará sus métodos destroy(). Si el bean se ha declarado con algún método destroy-method, se ejecutará el método especificado.

Framework
Está formado por 20 jars y tiene 6 módulos:
- Acceso a datos e integración (JDBC, ORM, Tx, OXM, JMS).
- Web y acceso remoto (WEB, PORTLET, SERVLET, STRUTS).
- AOP (ASPECTOS).
- Instrumentación.
- Core (BEANS, NUCLEO, CONTEXTO, TEXTO, SOPORTE CONTEXTO).
- Pruebas.

Configuración
Dos formas: por XML o por Anotaciones.

Tags de XML
<bean> -> declaración de beans y su conexión.
<aop> -> aspectos.
<context> -> incluir elementos para configurar el contexto de la aplicación.
<jee> -> integración con las APIs de J2EE (JNDI y EJB).
<jms> -> declarar POJOS basados en mensajes.
<lang> -> declarar beans implementados por Groovy, JRuby o BeanShell.
<mvc> -> activa caracterísiticas MVC de Spring (controladores orientados a anotación, controladores de vista, interceptores).
<oxm> -> configuración de ubicaciones de objetos con XML de Spring.
<tx> -> transacciones.
<util> -> elementos de utilidad.




2. CONEXIÓN DE BEANS
  DECLARACIÓN DE BEANS
<bean id="duke" class="com.project.domain.Duke" />
Elementos         id -> nombre de referencia en el contenedor de Spring
                        class -> clase

En código Java sería,
new com.project.domain.Duke() -> constructor predeterminado
Cargando el contexto sería,
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/project/xml/duke.xml");
Performer performer = (Performer) ctx.getBean("duke");
Si queremos cargar otro constructor con valores,
<bean id="duke" class="com.project.domain.Duke"  constructor-arg value="15" />
Si queremos cargar otro constructor con referencias,
<bean id="duke" class="com.project.domain.Duke" constructor-arg ref="instrument" />
Para crear el bean mediante métodos de fábrica, es decir, para clases singleton sin constructor público
<bean id="duke" class="com.project.domain.Duke"  factory-method="getInstance" />
donde getInstance() es un método estático para crear una instancia de la clase.

Ámbitos
- prototype -> se crean varias instancias.
- request -> una instacia por solicitud HTTP (MVC).
- session -> una instancia por sesión HTTP (MVC).
- global-session -> una instancia por sesión HTTP global (Portlet).
<bean id="duke" class="com.project.domain.Duke"  scope="singleton" />
Por defecto, todos los beans de Spring son singleton,es decir, sólo se crea una instancia para toda la aplicación (por contenedor de Spring).

Para modificar los métodos de inicialización y eliminación del bean,
<bean id="duke" class="com.project.domain.Duke"  init-method="turnOnLights" destroy-method="turnOffLights" />
Son los métodos que se van a ejecutar en el bean justo después de la instanciación y el que se ejecuta justo antes de que se elimine del contenedor.
Para usarlo de modo predeterminado, se puede incluir default-init-method y default-destroy-method para que siempre use los mismos métodos.


INYECCIÓN DE PROPIEDADES
Para valores sencillos,
<bean id="duke" class="com.project.domain.Duke" >
<property name="song" value="Jingle Bells" />
</bean>
Indica que se ejecute el método setSong() para inyectar la propiedad. Da igual el tipo de dato ya que Spring los transforma al tipo de dato que esté en el bean.

Para referencias,
<bean id="duke" class="com.project.domain.Duke">
<property name="instrument" value="saxophone"/>
</bean>
Para beans internos,
<bean id="duke" class="com.project.domain.Duke">
<property name="instrument" >
<bean class="com.project.domain.Saxophone" />
</property>
</bean>
* Beans internos son aquellos que se definen en el ámbito de otro bean.


NOTA: Se puede cambiar la tag <property> por el namespace p.

Para inyectar colecciones tenemos:
- <list> -> lista de valores permitiendo duplicados
- <set> -> conjunto de valores sin duplicados
- <map> -> colección de pares (clave / valor) de cualquier tipo
- <props> -> colección de pares (clave / valor) de tipo String

Ej. <list> o <set>
<bean id="duke" class="com.project.domain.Duke">
<property name="instruments" >
<list>
<ref bean="guitar" /> * También se puede utlizar <value>, <bean> o <null/>
<ref bean="cymbal" />
<ref bean="harmonica" />
</list>
</property>
</bean>
Ej.
<map>
<bean id="duke" class="com.project.domain.Duke">
<property name="instruments" >
<map>
<entry key="guitar" value="uno" /> * También se puede utlizar <key>, <key-ref>, <value> ó <value-ref>
<entry key="cymbal" value="uno" />
<value-ref>
<entry key="harmonica" value="cuatro" />
</map>
</property>
</bean>
Ej.
<props>
<bean id="duke" class="com.project.domain.Duke">
<property name="instruments" >
<props>
<prop key="guitar">strum strum</prop>
<prop key="cymbal">crash crash</prop>
</props>
</property>
</bean>
Para inyectar un null en una propiedad,
<property name="instrument"><null/></property>
CONEXIÓN CON EXPRESIONES (SpEL #{})
Son expresiones que se evalúan en tiempo de ejecución.
Funciones:
- Hacer referencia a beans por su ID.
- Invocar métodos y acceder a propiedades.
- Operaciones lógicas, relacionales y matemáticas.
- Coincidencia de expresiones regulares.
- Manipulación de colecciones.

Para valores literales,
<property name="field" value="#{9}" />(valor entero)
<property name="field" value="#{9.1}" />(valor decimal)
<property name="field" value="#{'nombre'}" /> (valor String)
<property name="field" value="#{false}" /> (valor boolean)
  
Para referencias, propiedades y métodos,
<property name="field" value="#{duke}" />
<property name="field" value="#{duke.song}" />
<property name="field" value="#{duke.getSelected()}" />
* Con descriptores de acceso para validar null
<property name="field" value="#{duke.getSelected()?.toUpperCase()}" />
Para tipos,
<property name="field" value="#{T(java.lang.Math).PI}" />
Para colecciones,
<property name="field" value="#{collection[2]}" />

Operaciones:
- Artiméticas (+,-,*,/,%,^)
- Relaciones (<,>==,<=,>=,lt,gt,eq,le,ge)
- Lógicas (and,or,not)
- Condicionales (?: ternario) (?:elvis)
- Expresiones regulares (matches)

3. MINIMIZAR LA CONFIGURACIÓN DEL XML
  CONEXIÓN AUTOMÁTICA DE PROPIEDADES
¿Cómo reducir XML? Conexión automática y detección automática.
Cuatro tipos para poder hacer la conexión automática:
- byName -> intenta coincidir todas las propiedades del bean conectado automáticamente con aquellos que tengan el mismo nombre o ID.
- byType -> intenta hacer coincidir todas las propiedades cuyos tipos puedan asignarse a sus propiedades.
- constructor -> intenta hacer coincidir un constructor del bean con aquellos beans que tengan constructores con argumentos del mismo tipo.
- autodetect -> utiliza primero el "constructor" y si no funciona "byType".

CONEXIÓN MEDIANTE ANOTACIONES 
Añadir <context : annotation-config /> en el XML para activarlo.
Se puede conectar propiedades, métodos y constructores.
Anotaciones:
- @Autowired (Spring)
- @Inject (JSR-330)
- @Resource (JSR-250)

@Autowired
Funciones:
- Para inyectar una propiedad en su método establecedor (set).
- En métodos no establecedores.
- En constructores.
- En una propiedad directamente aunque sea private.

Problemas:
- Puede no haber un bean que se conecte a la propiedad o parámetro @Autowired
- Si no hay bean o hay varios beans que puedan conectarse de forma automática.

Soluciones:
- Conexión automática opcional.
- Calificar dependencias ambiguas.
- Crear calificadores personalizados.

* Si @Autowired no se puede conectar a ningún bean con la propiedad anotada, se producirá un NoSuchBeanDefinitionException.

1ª Solución - Conexión automática opcional
@Autowired (required = false)
private Instrument instrument;
La propiedad es opcional y puede aceptar un null.
Si se hace con constructores, sólo uno debe tener required = true y todos los demás a false.

2ª Solución - Calificar dependencias ambiguas
Cuando hay dos o más beans que se puedan conectar a una propiedad o parámetro donde se producirá un NoSuchBeanDefinitionException
@Autowired
@Qualifier("guitar") (->id del bean)
private Instrument instrument;
3ª Solución - Crear anotaciones personalizadas
Declarar:
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface StringedInstrument { ... }
Uso:
@StringedInstrument
public class Guitar implements Instrument { ... }

@Inject
Es igual que el @Autowired de Spring. Se puede anotar propiedades, métodos y constructores. No tiene required. Si no se cumple, se generará el error.
También tiene una solución para las definiciones de bean ambiguas (como el @Qualifier de @Autowired), y es el @Named.
@Inject
@Named("guitar") (->id del bean)
private Instrument instrument;
También se pueden crear anotaciones personalizadas con el @Qualifier de JSR-330.

@Value
Uso de expresiones con inyección de anotaciones.
Le permite conectar valores primitivos como int, boolean y String.
Podrá utilizarla en una propiedad, método o parámetro de método.
@Value("Eruption")
private String song;
Aunque es mucho más útil con expresiones SpEL.
@Value("#{systemProperties.myFavouriteSong}")
private String song;
DETECTAR BEAN DE FORMA AUTOMÁTICA
<context : component-scan> detecta los beans de forma automática y los declara. ej.
<context : component-scan base-package="com.spring.idol" />
Buscará un paquete de clases con las siguientes anotaciones:
- @Component -> componente Spring
- @Controller -> controlador MVC Spring
- @Repository -> repositorio de datos
- @Service -> servicio
- Anotación personalizada con @Component
@Component / @Component("eddie") (->id del bean)
public class Guitar implements Instrument {
public void play() { ... }
}
Tiene varias opciones de filtrado añadiendo filtros de inclusión o exclusión.
<context : component-scan base-package="com.spring.idol" >
<context : include-filter type="assignable" expression="com.spring.idol.Instrument" />
</context : component-scan>
Tipos de filtrado:
- annotation -> busca clases con una determinada anotación
- assignable -> busca clases que puedan asignarse al tipo
- aspectj -> busca clases con una determinada anotación AspectJ
- custom -> para un determinado TypeFilter
- regex -> para un nombre de clase predeterminado
* Para excluir <context : exclude-filter >

USO DE LA CONFIGURACIÓN BASADO EN JAVA
Activarla en el XML con <context : component-scan base-package="com.spring.idol" />
Busca clases que estén anotadas con  @Configuration en un determinado paquete.
@Configuration
public class SptingIdolConfig { ... }
Para declarar un bean sencillo,
@Bean
public Performer duke() {
return new Juggler();
}
La ventaja que tiene es que como es código Java, se comprueba en tiempo de compilación. 
 
4. AOP
TERMINOLOGÍA
AOP se utiliza para separar las preocupaciones transversales de la lógica de negocio. Las preocupaciones tranversales son funciones que abarcan varios puntos dentro de una aplicación.
AOP ayuda a desacoplar las preocupaciones transversales de los objetos que los afectan.
AOP se utilizará para transacciones, seguridad y cacheado.

Consejo -> propósito o funcionalidad de un aspecto (el qué y el cuándo)
Tipos de consejo:
- Antes de la ejecución
- Después de la ejecución
- Después de la devolución (el método se ejecuta correctamente)
- Después de producir un error (el método se ejecuta incorrectamente)
- Alrededor del método (encapsula el método antes y después)

Punto de cruce -> dónde se va a aplicar el consejo. Puede ser unmétodo, error o campo.
Punto de corte -> reduce no tener que ddar consejo a todos los puntos de cruce.
Aspecto -> define el consejo y los puntos de corte (qué, dónde y cuándo).
Instrucciones -> permite añadir nuevos métodos y atributos a las clases existentes sin modificarlas.
Entrelazado -> proceso de aplicar aspectos a un objeto de destino para crear un nuevo objeto proxy.

Tres lugares:
- Tiempo de compilación
- Tiempo de carga de clases
- Tiempo de ejecución

Marcos de trabajo:
- AspectJ
- JBOSS AOP
- Spring AOP

Variantes de Spring AOP:
- AOP basado en proxy de Spring básico
- Aspectos basados en anotaciones AspectJ
- Aspectos POJO puros
- Aspectos AspectJ inyectados

Funcionamiento:
- Los consejos de Spring se escriben en clases Java.
- Los puntos de corte se definen en los XML de configuración de Spring.
- Spring "aconseja" los objetos en tiempo de ejecución. Los aspectos se entrelazan con los beans empaquetándolos en una clases proxy.
- El proxy lleva a cabo toda la lógica de aspectos, entre el momento en el que el proxy intercepta la ejecución del método y el momento en el que se invoca el método del bean de destino.
- No se crean los objetos proxy hasta que se necesitan.
- Spring sólo admite puntos de cruce de método. AspectJ y JBOSS AOP admiten también de constructor y de campo.

FUNCIONAMIENTO
Designadores de AspectJ que usa Spring:
- args(), @args(), execution, this(), target(), @target(), within(), @within(), @annotation
* Si usas otro que no sean estos de arriba, dará IllegalArgumentException.
execution -> el íunico que realiza coincidencias.
el resto -> se utilizan para delimitar su alcance.

ej. execution(* com.spring.idol.Instrument.play(. .))
Explicación: * - puede devolver cualquier tipo
                   . . - acepta cualquier tipo de argumento
ej. execution(* com.spring.idol.Instrument.play(. .) && within(com.spring.idol.*) and bean(eddie)
Explicación: * - puede devolver cualquier tipo
                   . . - acepta cualquier tipo de argumento
                   && - and
                   within - cuando el método se ejecuta dentro de cualquier clase del paquete
                   eddie - id del bean
<aop:config>
<aop:aspect ref="audience" >
<aop:before pointcut="execution(* com.spring.Performer.perform(. .))" method="takeSeats" />
<aop:before pointcut="execution(* com.spring.Performer.perform(. .))" method="demand" />
</aop:aspect>
</aop:config>
* Aspecto aplicado al bean Audience con dos tipos de consejos que se ejecutan antes del método. Como el punto de cruce es igual para los dos aspectos, se podría escribir así,
<aop:config>
<aop:aspect ref="audience" >
<aop:pointcut id="performance" expression="execution(* com.spring.Performer.perform(. .))" >
<aop:before pointcut-ref="performance" method="takeSeats" />
<aop:before pointcut-ref="performance" method="demand" />
</aop:pointcut>
</aop:aspect>
</aop:config>
Declaración entorno al consejo
Se da en circunstancias donde quieres guardar un valor antes y después de la ejecución del método para compararlo.
public void watchPerformance(ProceedingJoinPoint joinpoint){
try{
long start = System.currentTimeMilis();
joinpoint.proceed();
long end = System.currentTimeMilis();
}catch(){ ... }
}
Si tuviera argumentos sería,
<aop:config>
<aop:aspect ref="audience" >
<aop:pointcut id="performance2" expression="execution(* com.spring.Performer.perform(String)) and args(thoughts)" >
<aop:before pointcut-ref="performance2" method="applaud" arg-names="thoughts"/>
</aop:pointcut>
</aop:aspect>
</aop:config>
Nuevas funcionalidades con Aspectos
Si utilizamos un concepto de AOP llamado introducción, los aspectos pueden añadir nuevos métodos a los beans de Spring ya que los aspectos son sólo proxies que implementan la misma interfaz que los beans que contienen. El proxy intercepta las ejecuciones y los delega a un objeto diferente que implementa el nuevo método.
<aop:config>
<aop:aspect>
<aop:declare-parents types-matching="com.spring.Performer" implement-interface="com.spring.Contestant" default-impl="com.spring.GraciousContestant" />
</aop:aspect>
</aop:config>
* Aquí se describe que todos los beans cuyo tipo coincida con la interfaz Performer, debería contar con Contestant como elementos principales, siendo GraciousContestant su implementación. También se podría sustituir default-impl por delegate-ref con el ID de un bean.

ANOTACIÓN DE ASPECTOS
@Aspect
public class Audience {
@Pointcut("execution(* com.spring.Performer.perform(. .))")
public void performance(){ ... }
@Before("performance()")
public void takeSeats(){ ... }
@AfterReturning("performance()")
public void applaud(){ ... }
@Around("performance()")
public void watchPerformance() { ... }
}
* En el XML se deberá meter <bean id="audience" class="com.spring.Audience" />
                                              <aop:aspectj-autoproxy /> 

Si trabajamos con argumentos,
@Aspect
public class Magician implements MindReader{
private String thoughts;
@Pointcut("execution(* com.spring.Thinker.think(String)) and args(thoughts)")
public void thinking(String thoughts){ ... }
@Before("thinking(thoughts)")
public void intercept(String thoughts){ ... }
}
Para trabajar con introducciones,
@Aspect
public class ContestantIntroducer { @DeclaredParents(value="com.spring.Performer",defaultImpl="GraiousContestant..class")
public static Contestant contestant;
}
* Aquí también habrá que introducir el bean en el contexto y la tag <aop:aspectj-autoproxy />
5. ORM
ACCESO A DATOS DE SPRING
Podemos utilizar JDBC, Hibernate, JPA, etc.
DAO ->objeto de acceso a datos. Sirve para leer y escribir datos en la base de datos.
             Servicio -> Interfaz DAO -> Impl. DAO
Poner el DAO con una interfaz tiene dos ventajas:
- Probar objetos de servicio fácilmentepor no estar acoplados a una implementación.
- Toda la persistencia se aisla con el DAO. Si se cambiara a otra tecnología de persistencia, el cambio sería mínimo.

Excepciones -> la más conocida es SQLException de JDBC. No nos da apenas información.
                        JDBC                               SPRING
             BatchUpdateException      CannotAdquiredockException 
                DataTruncation               CannotSerializeTransactionException
                SQLException                CleanupFailureDataAccessException
                  SQLWarning                 ConcurrencyFailureException  
                                                       DataAccessException
                                                    DataAccessResourceFailureException
                                                    DataIntegrityViolationException  ...

La excepción DataAccessException se encuentra en la raiz. Es una excepción no comprobada, no tiene que capturar todas las excepciones de acceso a datos.
Spring sabe que muchas excepciones no pueden solucionarse en el "catch", de ahí que se decante por excepciones no comprobadas.
Para sacar partido a las excepciones de Spring debe utilizar las plantillas de acceso a datos.

Plantillas
Acceso a datos:
- Plantillas -> gestionan la parte fija. (Prepara recursos, inicia transacción, ejecuta / revierte transacción, cierra los recursos y gestiona errores).
- Retrollamadas -> gestiona la parte variable. (Ejecuta la transacción y devuelve los datos).
Sólo nos preocuparíamos de las retrollamadas (parte variable).
Tipos de plantillas:
- JDBCTemplate -> jdbc.core.JdbcTemplate
- HibernateTemplate -> orm.hibernate.HibernateTemplate (Hibernate < 3.0)
                                -> orm.hibernate3.HibernateTemplate (Hibernate >= 3.0) 
- JPATemplate -> orm.jpa.JpaTemplate
- iBATIS -> orm.ibatis.SqlMapClientTemplate
 Pasos:
- Configurar la plantilla como un bean en el contexto.
- Conectarla con su DAO (clases de apoyo DAO).

Clases de apoyo DAO -> son las clases que proporcionan un cómodo acceso a la clase plantilla a la que apoyan. Al crear su implementación DAO, se configura la clase de apoyo DAO como una subclase y ejecutar así el método de recuperación de la plantilla directamente.
Ejemplo para JDBC (subclase -> JdbcDaoSupport, método -> getJdbcTemplate y getConnection)
Tipos:
- JDBC -> jdbc.core.support.JdbcDaoSupport
- Hibernate -> orm.hibernate.support.HibernateDaoSupport (Hibernate < 3.0)
                       orm.hibernate3.support.HibernateDaoSupport (Hibernate >= 3.0)
- JPA -> orm.jpa.support.JpaDaoSupport
- iBATIS -> orm.ibatis.support.SqlMapClientDaoSupport

CONFIGURAR UN ORIGEN DE DATOS
Se deberá configurar un bean con el origen de datos.
Tipos:
- Definidos por un controlador JDBC.
- Buscados por JNDI.
- Los que agrupan conexiones.

JNDI -> La ventaja es que se pueden configurar de una manera externa a la aplicación. Permite solicitar un origen de datos cuando esté lista para acceder a la base de datos. Spring permite configurar un bean de referencia a un origen de datos con JNDI y conectarlo con las clases que necesite.
<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/ApplicationDS" (->nombre del recurso JNDI)
resource-ref="true" />(->a true sólo si se está ejecutando en un servidor de aplicaciones en Java jndi-name="java:compt/env/")
AGRUPADO -> Es la segunda mejor opción. Spring nos proporcionan un origen de datos de este tipo (DBCP). El más sencillo es el BasicDataSource.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource>" >
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost/splitter" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="initialSize" value="5" />
<property name="maxSize" value="10" />
</bean>
Otras propiedades: maxIdle, maxOpenPreparedStatements, maxWait, minEvictableIdleTimeMilis, minIdle, poolPreparedStatements.

CONTROLADOR JDBC ->Es el más sencillo. Se puede hacer por 2 clases diferentes:
- DriveManagerDataSource -> devuelve una conexión nueva.
- SingleConnectionDataSource -> devuelve la misma conexión.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriveManagerDataSource" >
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost/splitter" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
Desventajas:
- DriveManagerDataSource -> puede permitir varios subprocesos pero con un alto coste de rendimiento al crear una nueva conexión cada vez.
- SingleConnectionDataSource -> sólo tiene una conexión a base de datos. No trabaja bien en aplicaciones con varios procesos. 

USO DE JDBC CON SPRING
Se utlizarán plantillas para liberar código que trata de administrar recursos y excepciones.
Tres clases de plantillas:
- JdbcTemplate -> la más sencilla. Acceso a base de datos por JDBC y consultas de parámetros indexados sencillos.
- NamedParametersJdbcTemplate -> las consultas son cuando los valores están vinculados a parámetros con nombre en SQL.
- SimpleJdbcTemplate -> a utilizar con Java 1.5

Primero crearemos un bean de tipo SingleJdbcTemplate conectado a nuestro dataSource
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
Luego crearíamos nuestro DAO,
public class JdbcSpitterDAO implements SpitterDAO {
private SimpleJdbcTemplate jdbcTemplate;
public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
}
Conectamos la propiedad jdbcTemplate con JdbcSpitterDAO a través de su interfaz,
<bean id="spitterDAO" class="com...." >
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
Ejemplo de método para insetar en base de datos (teniendo en cuenta el orden de parámetros)
public void addSpitter(Spitter spitter){
jdbcTemplate.update(SQL_INSERT_SPITTER,
spitter.getUsername(),spitter.getPassword(),spitter.getEmail());
spitter.setId(queryForIdentity());
}
private static final String SQL_INSERT_SPITTER = "insert into spitter(username, password, email) values(: username, : password, : email)"; 
*Queda transparente para nosotros obtener la conexión, crear instrucción y ejecutar el SQL. También el tema de las excepciones.
 Ejemplo de método getSpitterById() -> Sería igual que el anterior sólo que en vez de queryForIdentity() sería queryForObject con 3 parametros:
- Un String con la sentencia.
- ParameterizedRowMapper: extrae ResultSet y crear el objeto
- Lista de argumentos
Ejemplo MEJORADO para insertar en base de datos (sin tener en cuenta el orden de los parámetros)
public void addSpitter(Spitter spitter){
Map<String,Object> params = new HashMap<String,Object>;
params.put("username", spitter.getUsername());
params.put("password", spitter.getPassword());
params.put("email", spitter.getEmail());
jdbcTemplate.update(SQL_INSERT_SPITTER, params);
spitter.setId(queryForIdentity());
}
CLASES DE APOYO DAO PARA JDBC
Se creará una clase de apoyo genérica (JdbcDaoSupport) de la que heredarán todas las clases DAO de la aplicación.
Tres clases de apoyo: JdbcDaoSupport, SimpleJdcbDaoSupport, NamedParametersJdbcDaoSupport.
public exampleDaoJdbc extends SimpleJdbcDaoSupport implements exampleDaoJdbcImpl { ... }
Luego configuraríamos el bean en el contexto,
<bean id="spitterDAO" class="com..." >
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
* Opción mejorada
<bean id="spitterDAO" class="com..." >
<property name="dataSource" ref="dataSource" />
</bean>
INTEGRACIÓN CON HIBERNATE
Características más sofisticadas:
- Carga diferida -> no cargar relaciones de objetos en memoria.
- Carga activa -> cargar relaciones de objetos en memoria.
- Secuenciación -> modificaciones y borrados en cascada.
Spring es compatible con Hibernate, iBatis, JPA. JDO, etc.
Spring ofrece:
- Compatibilidad integrada para las transacciones.
- Gestión de excepciones.
- Clases de plantillas.
- Clases de apoyo DAO.
- Gestión de recursos.

Dos modos de hacerlo:
- XML -> LocalSessionFactoryBean
- Anotaciones -> AnnotationSessionFactoryBean

Configuración para el XML
- dataSource
- mappingResources (xml de Hibernate) 
- hibernateProperties (configuración)
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="mappingResources" >
<list>
<value>Spitter.hbm.xml</value>
</list>
</property>
<property name="mappingResources" >
<props>
<prop key="dialect">org.hibernate.dialect.HSQLDialect</prop>
</props>
</property>
</bean>
Configuración con anotaciones
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com..." /> (->ruta de paquetes a escanear @Entity)
<property name="hibernateProperties" >
<props>
<prop key="dialect">org.hibernate.dialect.HSQLDialect</prop>
</props>
</property>
</bean>
* También se puede sustituir packagesToScan por annotatedClasses para poner una lista de clases, cuando son pocas.

DAO -> garantizar una sessión por transacción. Se crea el DAO sin código Spring ya que Hibernate gestiona esto por sí sólo.
@Repository
public class HibernateSpitterDAO implements SpitterDAO {
private SessionFactory sessionFactory;
@Autowired
public HibernateSpitterDAO (SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
private Session currentSession(){
return sessionFactory.setCurrentSession();
}
public void addSpitter(Spitter spitter){
currentSession().save(spitter);
}
public Spitter getSpitterById(long id){
return (Spitter) currentSession().get(Spitter.class,id);
}
public void saveSpitter(Spitter spitter){
currentSession().update(spitter);
}
}
* NOTA: @Autowired -> Spring inyecta automáticamente una SessionFactory
               método currentSession() -> obtiene la sesión de la transacción actual
              @Repository -> Analiza <context:component-scan /> para saber qué clases del paquete tiene anotaciones.       
                                    -> Comprueba la gestión de excepciones no comprobadas de Spring. Se debe añadir <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" > 

6. GESTIÓN DE LAS TRANSACCIONES
FUNCIONAMIENTO
Las transacciones son ACID:
- Atómicas -> formadas por una o varias actividades.
- Coherentes -> después de la transacción, la aplicación queda coherente.
- Independientes -> deben permitir a varios usuarios trabajar con los mismo datos.
- Duraderas -> los resultados son permanentes.

GESTOR DE TRANSACCIONES
Gestores:
- Hibernate 3 -> orm.hibernate3.HibernateTransactionManager
- JDBC o iBATIS -> jdbc.datasource.DataSourceTransactionManager
- JPA -> orm.jpa.JpaTransactionManager
Se declara como un bean en el contexto.
JDBC
<bean id="transactionManager" class="org.springframework.jdbc.dataSource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource" />
</bean>
HIBERNATE
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory" />
</bean>
* HibernateTransactionManager delega el control a un objeto org.hibernate.Transaction que recupera la sesión de Hibernate. Cuando la transacción se completa con éxito, HibernateTransactionManager ejecuta el método commit() del objeto Transaction, y si falla, ejecuta el rollback().

PROGRAMAR TRANSACCIONES
Tipos de transacciones:
- Declarativas
- Programáticas (más control)

Ejemplo de declarativa
public void saveSpitter(Spitter spitter){
spitterDao.saveSpitter(spitter);
}
Ejemplo de programática
public void saveSpitter(Spitter spitter){
txTemplate.execute(new TransactionCallback<Void>(){
public void doInTransaction(TransactionStatus txStatus){
try{
spitterDao.saveSpitter(spitter);
}catch(RuntimeException e){
txStatus.setRollbackOnly();
throw e;
}
return null;
}
});
}
* TransactionTemplate debe inyectarse como un bean en el contexto.
<bean id="spitterService" class="...SpitterServiceImpl" >
<property name="transactionTemplate" >
<bean class="org.springframework.transaction.support.TransactionTemplate" >
<property name="transactionManager" ref="transactionManager" />
</bean>
</property>
</bean>
DECLARAR TRANSACCIONES
Las transacciones declarativas se definen mediante atributos de transacción. Son 5 parámetros los que definen su política interna: propagación, aislamiento, sólo lectura, tiempo de espera, normas de reversión.

Propagación -> define los límites de la transacción respecto al cliente y el método que se está ejecutando.
7 tipos de comportamiento:
- PROPAGATION_MANDATORY -> el método se ejecuta dentro de la Tx. Si no hay ninguna en proceso, Excepción.
- PROPAGATION_NESTED -> el método se ejecuta dentro de una Tx anidada.
- PROPAGATION_NEVER -> el método no se ejecuta dentro de de un contexto de Tx.
- PROPAGATION_NOT_SUPPORTED -> el método no se ejecuta dentro de una Tx.
- PROPAGATION_REQUIRED -> el método debe ejecutarse dentro de una Tx. Si no hay ninguna en curso, se ejecutarán dentro, sino, se creará una nueva.

Aislamiento -> varias Tx se ejcutan a la vez con unos mismos datos. Esto puede dar problemas: lectura de datos sucios, lectura no repetible, lectura fantasma,...
Niveles:
- ISOLATION_DEFAULT -> predeterminado.
- ISOLATION_READ_UNCOMITTED -> permite leer cambios que no se han aplicado (puede dar lectura de datos sucios, no repetible y fantasma). LA + EFICIENTE
- ISOLATION_READ_COMMITED - > permite leer cambios que se han aplicado (puede dar lectura no repetible y fantasma).
- ISOLATION_REPETEABLE_READ -> varias lecturas al mismo tiempo (puede darse la lectura fantasma).
- ISOLATION_SERIALIZABLE -> nivel de aislamiento ACID (lento). LA - EFICIENTE
* No todos los niveles de aislamiento son compatibles con los orígenes de datos:
 · Sólo lectura: transacciones sólo lectura.
 · Tiempo de espera: para ponerle a la Tx un tiempo máximo.
 · Normas de reversión: definir qué excepciones causan reversión y cuáles no.

XML
<tx:advice id="txAdvice" >
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" >
<tx:method name="*" propagation="SUPPORTS" read-only="true" >
</tx:attributes>
</tx:advice>
Atributos: 
- isolation
- propagation
- read-only
-normas de reversión: rollback-for, no-rollback-for, timeout. 
* Necesitará tener definido el transactionManager y un asesor AOP.
<aop:config>
<aop:advisor pointcut="execution(* * ...SpitterService.*(. .))" advice-ref="txAdvice" />
</aop:config>
ANOTACIONES
Definir <tx:annotation-driven transaction-manager="txManager" /> en el contexto para que busque en todos los beans anotaciones del tipo @Transactional, tanto a nivel de clase como de método.
@Transactional(propagation=Propagation.SUPPORTS, read-only=true)
public class SpitterServiceImpl implements SpitterService {
@Transactional(propagation=Propagation.REQUIRED, read-only=false)
public void addSpitter(Spitter spitter){ ... }
}
7. MVC
INTRODUCCIÓN
Pasos de una petición:
- La solicitud lleva la información y llega al DispatcherServlet (único servlet controlador de Spring).
- El DispatcherServlet envía la solicitud a un controlador de Spring que procesará la solicitud.
- El asignador del gestor prestará atención a la URL que lleva la solicitud y decidirá a qué controlador se dirige.
- El controlador delega la lógica de negocio a uno o más servicios.
- A menudo, la lógica que lleva el controlador devuelve parte de información al usuario (modelo).
- Devuelve la solicitud, modelo y nombre de la vista al DispatcherServlet.
- El DispatcherServlet resuelve la vista a mostrar a través del nombre de la vista lógica en su ViewResolver.

Configuración
Hay que insertar el DispatcherServlet en nuestra aplicación en nuestro archivo web.xml
<servlet>
<servlet-name>spitter</servlet-name>
<servlet-class>org.springframework.Web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Cuando se carga el servlet, se carga el contexto de Spring desde un xml cuyo nombre se basa en él. En este caso, intentará cargar el fichero spitter-servlet.xml del WEB-INF. Luego indicaremos qué tipo de URL van a ser gestionadas por el servlet. ej. *.htm, /*, /app
Estas posibilidades traen demasiados problemas. Lo mejor es ésta,
<servlet-mapping>
<servlet-name>spitter</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Esto gestionará todas las solicitudes incluyendo las de contenido estático.
Spring te ayuda con este tipo de solicitudes. Sólo tienes que añadir,
<mvc : resources mapping="/resources/**" location="/resouces/" /> en el spitter-servlet.xml
* Sólo se podrá utilizar a partir de la versión Spring 3.04

CREAR UN CONTROLADOR BÁSICO
Spring dispone de varias implementaciones de asignación de gestores para que el servlet decida a qué controlador ir.
Gestores:
- BeanNameUrlHandlerMapping -> asigna controladores a URL en función de los nombres de bean de los controladores.
- ControllerBeanNameHandlerMapping -> los nombres de bean no tienen que seguir las convenciones de las URL (similar al anterior).
- ContollerClassNameHandlerMapping -> asigna controladores a URL utilizando los nombres de la clase de los controles como base para sus URL.
- DefaultAnnotationHandlerMapping -> asigna una solicitud a un controlador y métodos de controlador anotados con @RequestMapping.
- SimpleUrlHandlerMapping -> asigna controladores a URL utilizando una colección de propiedades definidas en el contexto.
* Sólo habrá que declararlo como un bean en el contexto. Si no está declarado, utilizará por defecto el primero BeanNameUrl y DefaultAnnotation.
Aquí sólo usaremos la de anotaciones, para ello habrá que añadir una línea al spitter-servlet.xml para activar las anotaciones <mvc : annotation-driver />

ej. Controlador para página de inicio
@Controller
public class HomeController {
private SpitterService spitterService;
@Inject
public HomeController (SpitterService spitterService){
this.spitterService = spitterService;
}
@RequestMapping({"/","/home"})
public String showHomePage(Map<String, Object> model){
model.put("spittles", spitterService.getRecentSpittles(25));
return "home";
}
}
* @Controller (->indica que es controlador de Spring. Es una especialización de @Component en donde añadoremos <context:component-scan /> para detectar anotaciones)
   @Inject (->inyecta automáticamente el servicio cuando se instancie el controlador)    
   @RequestMapping (->registra el método como gestor de solicitudes de / ó /home)
    return "home" (->devuelve un String con el nombre lógico de la vista. Con esto, el DispatcherServlet la resuelve mediante el ViewResolver)

Resolución de Vistas (ViewResolver)
Nombre lógico vista -> nombre de vista
Por lo general son JSP, pero podría ser Velocity o FreeMarker.
org.springframework.Web.servlet.View
Varias implementaciones:
- BeanNameViewResolver -> busca una implementación de View que esté como un <bean> y cuyo ID sea el mismo que el del nombre de la vista lógica.
- ContentNegociationgViewResolver -> delega en uno o más solucionadores de vista. Se basa en el tipo de contenido solicitado.
- FreeMarkerViewResolver -> FreeMarker
- InternalResourceViewResolver -> busca una plantilla de vista almacenada en un WAR.
- JasperReportsViewResolver -> busca una plantilla de vista almacenada como un archivo Jasper.
- ResourceBundleViewResolver -> busca implementaciones View para un archivo de propiedades.
- TilesViewResolver -> Tiles
- UrlBasedViewResolver -> clase básica de algunos solucionadores de vista.
- VelocityLayoutViewResolver -> Velocity
- VelocityViewResolver -> Velocity
- XmlViewResolver -> busca una implementación de View en un <bean> que se declara en un xml /WEB-INF/view.xml
- XsltViewResolver -> resuelve una vista basada en XSLT.
 ej. InternalResouceViewResolver (/WEB-INF/views/home.jsp)
<bean class="org.springframework.Webservlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=". jsp" />
</bean>
Internamente el solucionador proporciona esa ruta a un objeto View que envía la solicitud a la JSP.
Agrupar el contexto
Varios XML de configuración:
- XML de capa de servicio
- XML de capa de persistencia
- XML de origen de datos
- spitter-servlet.xml
Aquí es donde entra el ContextLoaderListener, que es como un agente de escucha del servlet que carga configuraciones adicionales para el contexto de Spring. Añadir en el web.xml,
<listener>
<listener-class>org.springframework.Web.context.ContextLoaderListener</listener-loader>
</listener>
También deberemos cargar qué archivos de configuración de Spring debe meter. Si no se define ninguno, buscará por defecto /WEB-INF/applicationContext.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spitter-security.xml
classpath: service-context.xml
classpath: persistence.context.xml
</param-value>
</context-params>>
GESTIÓN DEL CONTROLADOR DE ENTRADA
Controlador "SpitterController" que muestra una lista de spittles para un spitter dado.
http://localhost:8080/spitter/spitters/spittles?spitter=habuma
@Controller
@RequestMapping("/spitter")
public class SpitterController {
private final SpitterService spitterService;
@Inject
public SpitterController(SpitterService spitterService){
this.spitterService = spitterService;
}
@RequestMapping(value="/spittles", method=GET)
public String listSpittlesForSpitter(@RequestParam("spitter") String username, Model model){
Spitter spitter = spitterService.getSpitter(username);
model.addAttribute(spitter);
model.addAttribute(spitterService.getSpittlesForSpitter(username));
return "/spittles/list";
}
}
* @RequestParam("spitter") se debe proporcionar el parámetro de la consulta "spitter" en la solicitud.
Hemos cambiado el 2º parámetro del método Map<String,String> por Model que en realidad es un Map pero con cómodos métodos para rellenar (addAttribute = put).

PROCESADO DE FORMULARIOS
Dos pasos:
- Mostrar el fomulario
- Procesar su envío

Mostrar el formulario
Crear el siguiente método en el Controller
@RequestMapping(method=RequestMethod.GET, params="new")
public String createSpitterProfile(Model model){
model.addAttribute(new Spitter());
return "spitters/edit";
}
* Tipo de URL que va a gestionar http://localhost:8080/spitter/spitters?new

Procesar su envío
Crear el siguiente método en el Controller
@RequestMapping(method=RequestMethod.GET)
public String addSpitterFromForm(@Valid Spitter spitter, BindingResult bindingResult){
if(bindingResult.hasErrors())
{ 
return "spitters/edit"; }
spitterService.saveSpitter(spitter);
return "redirect : /spitters/" + spitter.getUsername(); 
(->redirección con valores de ruta)
}
* Valid -> validación antes del procesado

Solicitudes con valores de ruta (/spitters/{username})
La respuesta a esta redirección es otro método gestor.
@RequestMapping(value="/{username}", method=RequestMethod.GET)
public String showSpitterProfile(@PathVariable String username, Model model){
model.addAttribute(spitterService.getSpitter(username));
return "spitters/view";
}
Los dos elementos nuevos trabajan de forma conjunta para permitir que el método gestione solicitudes cuyas URL incluyan parámetros insertados en sus rutas.

Validación (@Valid)
Se utiliza para validar el objeto Spitter. Si hay algún error, se transmite por el método a través del objeto BindingResult que tiene un método hasErrors() que devuelve true si tiene errores. Para mostrar lo errores de validación, el objeto BindingResult tiene un método getFieldError().
ej.
@Size(min=3, max=20, message="...")
Pattern(regexp="^[a-zA..]"), message="...")
private String username;
GESTIÓN DE LA CARGA DE ARCHIVOS
Tres pasos:
- Añadir un campo al formulario.
- Modificar el método add para recibir el fichero.
- Configurar el solucionador de archivos multiparte en Spring.
Añadir campo -> modificar la etiqueta <form> y añadirle enctype="multipart/form-data"
Modificar método
@RequestMapping(method=RequestMethod.POST)
public String addSpitterFromForm(@Valid Spitter spitter, BindingResult bindingResult, @RequestParam(value="image", required=false) MultipartFile image){
try{
if(!image.isEmpty()){
validateImage(image);
saveImage(spitter.getId()+".jpg", image);
}
}catch(ImageUploadException e){
bindingResult.reject(e.getMessage());
return "spitters/edit";
}
}
Guardar la imagen en un sistema de archivos
private void saveImage(String filename, MultipartFile image) throw ImageUploadException{
try{
File file = new File(WebRootPath+"/resource/"+filename);
FileUtils.writeByteArrayToFile(file, image.getBytes());
}catch(IOException e){
throw new ImageUploadException("...", e);
}
}
Configurar el solucionador de archivos
El DispatcherServlet por sí solo no puede. Hay que añadir un <bean> que implemente la interfaz MultipartResolver,
<bean id="multipartResolver" class="org.springframework.Web.multipart.commons.CommonsMultipartResolver" p:maxUploadSize="500000" />
8. SPRING WEB FLOW
9. SPRING SECURITY
10. SERVICIOS REMOTOS
11. REST
12. EXTRA
EXTERNALIZAR LA CONFIGURACIÓN
La configuración del origen de datos no debe estar en el xml de Spring, debería estar en otro lado (.properties).
Existen dos formas de hacerlo:
- Configuradores de marcadores de posición de propiedades
- Anuladores de propiedades

Marcadores de posición de propiedades
<context:property-placeholder location="classpath://db.properties" />
El db.properties contendría todos los valores del DriveManagerDataSource
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://localhost/spitter/spitterjdbc.username=admin
jdbc.password=admin
Sustituimos el bean dataSource por los valores del properties,
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"
p:username="${jdbc.username}" p:password="${jdbc.password}" />
También se puede usar anotaciones,    
@Value("${jdbc.url}")
private String databaseUrl;
Posibles errores:
- No se cargue el .properties por tener una ruta erronea.
- No exista una variable en el properties.
Posible solución,
<context:property-placeholder location="file://etc/myconfig.properties"
ignore-resource-not-found="true"
(->ignora las excepciones de .properties no encontrado)
ignore-unresolvable="true"
(->ignora las excepciones de variable no encontrada)
properties-ref="defaultConfiguration" /> 
(->bean a cargar con la configuración predeterminada)
Aquí se crearía un bean java.util.Properties que será,
<util:properties id="defaultConfiguration" >
<prop key="jdbc.url">...</prop>
<prop key="jdbc.driverClassName">...</prop>
<prop key="jdbc.username">...</prop>
<prop key="jdbc.password">...</prop>
</util:properties>
También se pueden elegir las propiedades del sistema añadiendo al <context:property-placeholder> la línea system.properties-mode.
Tres valores posibles:
- OVERRIDE -> primero las propiedades del sistema y sino, el archivo de propiedades.
- FALLBACK -> primero archivo de propiedades y sino, las propiedades del sistema.
- NEVER -> nunca las propiedades del sistema.

Anulación de propiedades
<context:property-override location="classpath://db.properties" />
Entonces el archivo db.properties tendría que ser dataSource.username=admin
Si no existe el properties, se cargará el bean de dataSource del contexto. Si existe el archivo, las cogerá de ahí. También puede usarse los mismos atributos que <context:property-placeholder>. Podemos darle seguridad a este archivo properties con Jasypt (cifrado en Java), añadiendo un bean en el contexto.
<bean class="org.jasypt.spring.properties.EncryptablePropertyPlaceHolder(ó Override)Configurer" p:location="file://etc/db.properties" >
<constructor-arg ref="StringEncrypter" />
</bean>
<bean id="StringEncrypter" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig" p:algoritm="PBEWithMD5AndDES" p:passwordEnvName="DB_ENCRYPTION_PWD" />
(variable de entorno)
CONEXIÓN DE OBJETOS
Lo que se va a permitir hacer es conectar un objeto gestionado por JNDI en las propiedades de otros beans de Spring como si el objeto JNDI fuera un bean del contexto.
  1.- Inyección del objeto
<jee:jndi-lookup> facilita el trabajo de conectar un objeto JNDI con Spring.
<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true" />
Lo conectamos a la sessionFactory de Hibernate
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
... 
</bean>
  2.- Cacheado de objetos JNDI
Es una buena técnica aunque impide su reimplementación en caliente de los objetos JNDI, es decir, tendría que reiniciarse para recuperar el nuevo objeto.
<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" 
resource-ref="true" cache="false"
proxy-interface="javax.sql.DataSource" /> (->tipo esperado para objeto JNDI)
Esto se da en situaciones donde el objeto JNDI va a cambiar mucho.
  3.- Carga diferida de objetos JNDI
En situaciones donde queremos que el objeto se cargue en el momento que digamos,
<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true" 
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />
  4.- Objetos de retroceso
Cuando se busca un objeto JNDI y no se encuentra, se añade una línea a,
<jee:jndi-lookup ...
... default-ref="devDataSource" /> (->bean por defecto que define el origen de datos)(->bean con lazy-init="true")
  5.- Conectar EJB a Spring
<jee:jndi-lookup> puede recuperar facilmente un bean se sesión de EJB3.
Para EJB2 lo podemos hacer con :
- <jee:local-slsb> -> accede al bean de sesión sin estados locales.
- <jee:remote-slsb> -> accede al bean de sesión sin estados remotos.
<jee:remote-slsb id="myEJB" jndi-name="my.ejb" business-interface="com.habuma.ejb.MyEJB" />
* my.ejb - nombre JNDI para buscar la interfaz de inicio de EJB
* com.habuma.ejb.MyEJB - interfaz de negocio que EJB va a implementar
<jee:local-slsb id="myEJB" jndi-name="my.ejb" business-interface="com.habuma.ejb.MyEJB" />
Para EJB3 también se puede utilizar. Para EJB2 ejecutarán el método create() por usted. Para EJB3 hará que el objeto esté disponible en el contexto de Spring.

ENVÍO DE MAILS
Spring cuenta con una API de abstracción de correo electrónico. Cuenta con una interfaz llamada MailSender qu eimplementa JavaMailSenderImpl. Configuramos el bean en el contexto,
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" p:host="${mailserver.host}" />
Si mi servidor no escucha en el puerto 25,
...p:port="${mailserver.port}" />
Si requiere autenticación,
...p:username="${mailserver.username}" p:password="${mailserver.password}" />
Si vamos a utilizar una sesión de correo JNDI,
<jee:jndi-lookup id="multiSession" jndi-name="mail/Session" resource-ref="true" />
y luego lo conectamos al bean mailSender,
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" p:session-ref="mailSession" />
Sólo nos quedaría conectar el remitente del correo con un bean de servicio,
@Autowired
JavaMailSender mailSender;
y crear el cuerpo del mensaje,
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("...");
message.setTo("...");
message.setSubject("...");
message.setText("...");
mailSender.send(message);
* Para añadir adjuntos, no nos sirve la clase SimpleMailMessage, debemos usar MimeMessage,
MimeMessage message = mailSender.createMimeMessage();
Aunque esta clase es muy compleja de tratar, Spring cuenta con MimeMessageHelper que es mejor,
MimeMessageHelper helper = new MimeMessageHelper(message, true); //multipart a true
helper.setFrom("...");
helper.setTo("...");
helper.setSubject("...");
helper.setText("...");
FileSystemResource couponImage = new FileSystemResource("/collateral/coupon.png");
helper.addAttachment("Coupon.png", couponImage);
mailSender.send(message);
Si quieres puedes enviar el cuerpo del mensaje enriquecido con HTML,
helper.setText("<html>...</html>", true); //código HTML a true
Se pueden crear plantillas HTML para cuerpos de mensajes con Velocity.

TAREAS EN SEGUNDO PLANO
Dos tipos:
- Tareas programadas -> funcionalidades que se ejecutan cada cierto tiempo.
- Métodos asíncronos -> se ejcutan y se devuelven de inmmediato.
<task:annotation-driven> para identificar las anotaciones @Scheduled y @Async en los beans.
Tarea programada (@Scheduled)
@Scheduled(fixedRate=86400000) //milisegundos
public void archiveOldSpitters(){ ... }
Opciones:
- fixedRate -> entre cada iteración.
- fixedDelay -> entre cada ejecución.
- cron -> expresión Cron. ej. @Scheduled(cron="0 0 0 1 12 2 1999") (->sec min hour day month dayWeek year)
En las expresiones Cron se puede poner un valor específico, un rango (9-12), una lista (9,11,13) o un comodín (*).
Método asíncrono (@Async)
Esto sirve para cuando un método saveSpitter() va a tardar mucho, lo mejor es ponerlo como método asíncrono y mostrarle una vista nueva mientras se ejcuta el método en segundo plano.
@Async
public void addSpitter(Spitter spitter){ ... }
Cuando se ejecuta el método, el control vuelve de inmediato al ejecutor, mientras que el método se va a estar ejecutando en segundo plano. Si el método asíncrono tuviera que devolver allgo al ejecutor, Spring cuenta con una implementación de java.util.concurrent.Future llamado AsyncResult
@Async
public Future<Long> performSomeReallyHairyMath(long imput){
...
return new AsynResult<Long>(result);
}
Una vez que el resultado esté listo, el ejecutor puede recuperarlo ejecutando el método get() sobre el objeto Future. Hasta entonces, el ejecutor puede ir comprobando el objeto con los métodos isDone() o isCancelled().

6 comentarios: