Tip Struts 2 #05: mensajes


VERSIONES

  1. 05/09/2013 (Primera publicación)
  2. 16/11/2013:
    • Añadida sección «Acciones de ámbito sesión»

05/09/2013
struts2 tip

En Struts 2 contamos con un sistema muy sencillo de utilizar para enviar mensajes al usuario desde un Action a una JSP. Este «servicio» de mensajería en realidad forma parte del sistema de validación de Struts 2 y es accesible por las clases que implementen la interfaz ValidationAware como ActionSupport

Estos mensajes consisten en simples cadenas clasificables en dos grupos: ActionMessage para mostrar información genérica y ActionError para mostrar mensajes de error. Estos mensajes se establecerán en nuestro action mediante los métodos addActionMessage y addActionError respectivamente. Iremos añadiendo los mensajes en el orden en que queremos que sean mostrados y siempre que sea posible debemos procurar que estos mensajes estén internacionalizados por lo que podemos obtenerlos de los .properties de internacionalización gracias a las distintas versiones del método getText (ver tip 11).

Nota: existe un tercer mecanismo (FieldError) específico para la validación de campos de formularios tratado en el tip 16.

A continuación se muestra el único action del proyecto de ejemplo.

package com.danielme.tips.struts2.actions;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 
 * @author danielme.com
 *
 */
public class MensajeriaAction extends ActionSupport 
{	
	
	/**
	 * Identificador para serialización
	 */
	private static final long serialVersionUID = 1L;

	
	public String execute() 
	{		
		addActionError(getText("error1"));
		addActionError(getText("error2"));
		
		//mensaje con parámetro, fecha y hora localizada según los properties i18n
		SimpleDateFormat sdf = new SimpleDateFormat(getText("pattern"), ActionContext.getContext().getLocale());
		String msg1 = String.format(getText("msg1"), sdf.format(new Date()));
		addActionMessage(msg1);
		addActionMessage(getText("msg2"));

		return SUCCESS;
    }	
	
}

El fichero /src/main/resources/global_es.properties (recordad que los ficheros de i18n se definen en el struts.xml)

title=tip 5 - Mensajes
error1 = Error número uno 
error2 = Error número dos
msg1 = Mensaje 1 %s
msg2 = Mensaje 2
pattern = EEEE dd.MM.yyyy HH:mm:ss

Para mostrar los mensajes en una JSP usaremos las etiquetas s:actionError y s:actionMessage. Los mensajes se imprimirán como una lista no ordenada en el orden en que fueron insertados.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
	<%@include file="/jsp/head.jsp"%>		
	</head>
	
	<body>
		</br>
	
		<s:actionmessage />
		</br>
		<s:actionerror />	
		
	
		<%@include file="/jsp/footer.jsp"%>
		
	</body>
</html>

mensajes sin estilos

En una aplicación real deberemos aplicar estilos a los mensajes según su tipo tal y como. Para aplicar estos estilos a los mensajes, podemos usar los atributos cssClass o cssStyle, otra altenativa es «envolver» los mensajes en un div. Struts 2, a través de OGNL, nos permite saber si hay mensajes para mostrar mediante la invocación de los métodos hasActionErrors y hasActionMessages. Esto nos permite generar dinámicamente código en la JSP si hay mensajes que mostrar y, por ejemplo, lanzar una modal con jQuery UI para mostrar los mensajes o realizar acciones similares. El snippet para hacer esto es el siguiente:

<!--"Envolvemos" los mensajes en un div para darle estilo. También podríamos
		ejecutar algún javascript para mostrar el mensaje en una ventana modal o realizar
		acciones similares -->
		<s:if test="hasActionMessages()">
			<div class="div-message">
				<s:actionmessage />
			</div>
		</s:if>
	
		<s:if test="hasActionErrors()">
			<div class="div-error">
				<s:actionerror />
			</div>
		</s:if>

La JSP final del proyecto con estilos y una simple animación con JQuery es la siguiente:

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
	
	<%@include file="/jsp/head.jsp"%>
	
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
	
		<STYLE type="text/css">
		
			.div-error 
			{
				background-color: #ea9184;
				border: 2px solid #ea523b;
				font-weight: bold;
				padding: 6px 6px 6px 6px;
				text-align: left;
				font-size: 1em;
				width: 99%;	
				margin-top: 10px;		
				display:none;
			}
			
			.div-error li 
			{
				list-style-type: none;
			}
			
			.div-message 
			{
				background-color: #aae28b;
				border: 2px solid #6db943;
				font-weight: bold;
				padding: 6px 6px 6px 6px;
				text-align: left;
				width: 99%;
				font-size: 1em;
				margin-top: 10px;
				display:none;
			}
			
			.div-message li 
			{
				list-style-type: none;
			}
			
		</STYLE>
		
		<script type="text/javascript">
			<s:if test="hasActionMessages()">
				$(document).ready(function() {
							$(".div-message").slideDown(500);
						});			
			</s:if>		
			<s:if test="hasActionErrors()">
				$(document).ready(function() {
							$(".div-error").slideDown(500);
						});
			</s:if>
		</script>
	
	</head>
	
	<body>
		</br>
	
		<s:actionmessage cssClass="div-message"/>
		<s:actionerror cssClass="div-error"/>
	
	
		<!--"Envolvemos" los mensajes en un div para darle estilo. También podríamos
		ejecutar algún javascript para mostrar el mensaje en una ventana modal o realizar
		acciones similares -->
		<s:if test="hasActionMessages()">
			<div class="div-message">
				<s:actionmessage />
			</div>
		</s:if>
	
		<s:if test="hasActionErrors()">
			<div class="div-error">
				<s:actionerror />
			</div>
		</s:if>
	
		<%@include file="/jsp/footer.jsp"%>
		
	</body>
</html>

El resultado final del proyecto de ejemplo:
mensajes2

Conservar los mensajes a través de los redirectAction

En el tip anterior vimos cómo navegar entre actions y que al hacerse un redirectAction se generaba una nueva petición dentro del servidor con su propio request. En ese caso, los mensajes se pierden con la redirección por lo que si queremos conservarlos no nos quedará más remedio que guardarlos y eliminarnos de la sesión, o bien «arrastrarlos» a través de la url (opción que quedaría horrible). Afortunadamente, y por tratarse de un problema habitual que tarde o temprano todos nos encontramos con Struts 2, existe un interceptor proporcionado por el propio framework que permite conservar mensajes entre redirecciones, guárdandolos en la sesión al salir de un Action y recuperándolos al ejecutarse el siguiente. Este inteceptor se llama Message Store y por defecto está deshabilitado (simplemente no hace nada). No voy a entrar en detalles sobre su uso, pero lo más simple es establecerlo en modo «automático» dentro de nuestra pila de interceptores por defecto.

           <interceptors>	
			<interceptor-stack name="tipStack">
				<interceptor-ref name="defaultStack" />

				<interceptor-ref name="store">
					<param name="operationMode">AUTOMATIC</param>
				</interceptor-ref>
			</interceptor-stack>
					
		</interceptors>
		
		<default-interceptor-ref name="tipStack" />

Nota: Este interceptor sólo funciona si en el momento de su ejecución existe una sesión abierta para el navegador del usuario, en caso contrario no hará nada y mostrará un error en el log en el nivel debug. Es un caso muy raro, pero si no os funciona el interceptor revisad el log porque puede ser este el problema.

Acciones de ámbito sesión

En Struts 2 no podemos definir el ámbito (scope) de los action como en Struts, pero tenemos esta posibilidad si definimos los Action como bean de Spring (u otras opciones similares como Guice) tal y como vimos en este artículo. En este caso, si nuestro action es de sesión los mensajes permanecerán en el mismo y podremos tener problemas de datos «fantasma». Si este es el caso, habrá que «limpiar» los mensajes después de renderizarlos en pantalla cuando ya no los necesitemos invocando el método clearErrorsAndMessages. Desde una JSP se puede hacer así:

<s:property value="clearErrorsAndMessages()"/> 

El proyecto completo para Maven se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.

<< TIPS STRUTS 2

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.