Integración de Spring con el envío de emails: técnicas avanzadas (II)

0
15572

Integración de Spring con el envío de emails: técnicas avanzadas (II).

0. Índice de contenidos.

1. Introducción

Este tutorial es el tercero de una serie que analiza el soporte que proporciona Spring para el envío de correo electrónico:

Velocity es un motor de plantillas basado en Java. Con Velocity se pueden crear páginas web, SQL, clases java y cualquier otro tipo de salida de plantillas.
Se puede utilizar como una aplicación independiente para generar código fuente e informes, o como un componente integrado en otros sistemas.

Spring nos proporciona un motor de Velocity para generar, de forma dinámica, el cuerpo de nuestros mensajes de correo electrónico.

En este tutorial, basándonos en la arquitectura definida en el tutorial anterior:

  • un servicio de envío de correo electrónico, y
  • una familia de proveedores de mensajes,

vamos a extender la funcionalidad de nuestra aplicación para incluir un nuevo proveedor de mensajes, basado en el motor de Velocity.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Asus G1 (Core 2 Duo a 2.1 GHz, 2048 MB RAM, 120 GB HD).
  • Sistema operativo: Windows Vista Ultimate.
  • JDK 1.5.0_15
  • Eclipse 3.4, con q4e.

3. Maven: el pom.xml.

Añadimos al pom.xml las siguientes dependencias:


...
		
			velocity
			velocity
			1.5
		 
		
		    org.apache.velocity.tools
		    velocity-tools
		    2.0-alpha1
		 
...


La librería velocity es estrictamente necesaria y la librería velocity-tools la incluimos porque vamos a hacer uso de
una clase de utilidades que contiene para el formateo de fechas dentro de la plantilla.

4. Creación de un nuevo proveedor de mensajes.

Vamos a crear un nuevo proveedor de mensajes basado en el motor de Velocity que proporciona Spring:

package com.autentia.training.spring.mail;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.DateTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.ui.velocity.VelocityEngineUtils;

import com.autentia.training.spring.model.User;

public class VelocityEmailMessageProviderImpl implements EmailMessageProvider {

	private Map inlineFiles;
	
	private String subject;
	
	private String body;
	
	private String template;
	
	@Autowired
	private VelocityEngine velocityEngine;
	
	public String getSubject(){
		return subject;
	}
	
	public void setSubject(String subject){
		this.subject = subject;
	}
	
	public String getBody() {
		return body;
	}
	
	public Map getInlineFiles() {
		return inlineFiles;
	}
	
	public void setInlineFiles(Map inlineFiles) {
		this.inlineFiles = inlineFiles;
	}

	public void setTemplate(String template){
		this.template = template;
	}
	
	public void fillblanks(String courseName, Date date, User user) throws IOException {
		Map model = new HashMap();
		model.put("date", new DateTool());
		model.put("user", user);
		model.put("courseDate", date);
		model.put("courseName", courseName);
		
		
		this.body = VelocityEngineUtils.mergeTemplateIntoString(
				velocityEngine, template, model);
		
	}
}

La clase cumple la intefaz definida para los proveedores mensajes de correo electrónico.

En la línea 27 solicitamos al contexto de Spring el motor de Velocity para llevar a cabo la generación en base a la plantilla.

El método setTemplate(), que queda fuera de la interfaz, recibe un String con el path de la plantilla de Velocity.

Mediante el método fillBlanks, damos contenido al modelo que tendremos disponible en la plantilla de Velocity, de este modo tendremos accesibles las siguientes variables:

  • user: con la instancia de un objeto de tipo User, que tiene las propiedades básicas de un usuario destinatario de un correo electrónico,
  • courseDate: con una fecha que mostraremos en el cuerpo del correo,
  • date: es una instancia de la clase de utilidades DateTool de Velocity que nos permitirá formatear la fecha,
  • courseName: con un cadena (el nombre del curso) que también mostraremos en el cuerpo del correo.

El objeto de tipo User no es más que un POJO, que podría ser una entidad dentro de una capa de persistencia:

package com.autentia.training.spring.model;

public class User {
	
	private String name;
	
	private String email;

	public User(String name, String email){
		this.name = name;
		this.email = email;
	}
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
	
	public void setEmail(String email) {
		this.email = email;
	}

	public String getEmail() {
		return email;
	}	
}

5. Configuración del applicationContext.xml.

Añadimos la definición de nuestro proveedor de mensajes dentro del applicationContext.xml (cuidado con tener dos beans con el mismo id!!!):


...
	
	  
	  
	   
		
			
				
					id001
				
				classpath:generic.css
			
			
				
					id002
				
				classpath:autentia.gif
			
		
	  
	
	
	
		
			
				resource.loader=class
				class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
				dateToolAttribute=org.apache.velocity.tools.generic.DateTool
			
		
	
...	


Dos beans:

  • el proveedor de mensajes: la definición es similar a la ya planteada solo que, en este caso, recibe la ruta a la plantilla de Velocity,
  • VelocityEngineFactoryBean: que nos va a permitir acceder a motor de plantillas de Velocity que provee Spring.

Podemos modificar el valor de la propiedad del fichero de propiedades app.properties para que tenga un mensaje más genérico:

email.subject.trainingConfirmation=Confirmación de celebración de charla

6. La plantilla de Velocity.

La carpeta de recursos de nuestro proyecto tendrá la siguiente estructura de directorios, ahora con la plantilla de Velocity en el mismo directorio que tenemos la de HTML estático:

La plantilla trainingConfirmation.vm, puede tener un contenido parecido al que sigue:





Confirmación de la celebración de la charla sobre "${courseName}"


	
	

Hola ${user.name},

Te confirmamos la celebración de la charla sobre "${courseName}" del $date.format("dd/MM/yyyy", $courseDate).

Un saludo.

El equipo de Autentia.

Destacamos:

  • línea 14: ahora el saludo está personalizado hacía el usuario que recibe el correo, con ${user.name} se imprime el user.getName(),
  • línea 15: imprimimos el nombre del curso y formateamos la fecha del mismo.

Básicamente, imprimimos el contenido asignado al modelo, si bien el lenguaje VTL de Velocity permite hacer uso de estructuras de control más complejas.

7. Creación de un nuevo testCase.

Vamos a probar su funcionamiento añadiendo al test un nuevo método que realice la invocación:

...
	/**
	 * Probamos el envío en base a una plantilla de Velocity.
	 * 
	 * @throws MessagingException
	 */
	@Test
	public void testVelocityTemplateResources() throws MessagingException {
		Calendar calendar = Calendar.getInstance(Locale.getDefault());
		calendar.set(Calendar.DAY_OF_MONTH, 22);
		calendar.set(Calendar.MONTH, 0);
		calendar.set(Calendar.YEAR, 2009);
		try {
			User user = new User("Jose Manuel Sánchez", "jmsanchez@autentia.com");
			((VelocityEmailMessageProviderImpl) emailMessageProvider)
					.fillblanks("Spring Framework", calendar.getTime(), user);
			mailService.send(user.getEmail(), emailMessageProvider);
		} catch (Exception e) {
			final String msg = "Excepción en el envío de emails con recursos incrustados.";
			log.warn(msg, e);
			Assert.fail(msg);
		}
	}
...

El método fillBlanks recibe:

  • el nombre del curso,
  • la fecha del mismo,
  • una instancia del objeto usuario, a quien va dirigido el correo.


8. El resultado.

Tras la ejecución del test deberíamos tener en la bandeja de entrada de nuestro cliente de correo un mensaje como el que sigue:


9. Conclusiones.

Ahora podemos generar el contenido de nuestros correos electrónicos, de forma dinámica, basándonos en plantillas de Velocity.

Parece que nuestro código está lo suficientemente modularizado y desacoplado, puesto que hemos modificado el objeto de nuestros correos,
extendiendo su funcionalidad, sin modificar la implementación existente:

  • solo hemos incluido una nueva clase, el nuevo proveedor de mensajes, y
  • modificado la configuración del contenedor de Spring, para que ahora se haga uso del mismo.

Podeis descargaros el proyecto configurado para Maven con el código de los tres tutoriales.

Un saludo.

Jose

mailto:jmsanchez@autentia.com

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad