El API Struts

Este cap�tulo se enfoca en la tarea de construir los componentes de la Vista de una aplicaci�n, que principalmente est� creada usando tecnolog�a JavaServer Pages (JSP). En particular Struts proporciona soporte para construir aplicaciones internacionalizadas, as� como para interact�ar con formularios de entrada.

.�Mensajes Internacionalizados

Hace unos pocos a�os, los desarrolladores de aplicaciones pod�an tener que contar s�lo con los residentes de su pa�s, que normalmente s�lo usaban un idioma (a veces dos), y una forma de representar cantidades num�ricas, como fechas, n�meros y valores monetarios. Sin embargo, la explosi�n del desarrollo de aplicaciones basadas en tecnolog�as Web, as� como el despliegue de dichas aplicaciones sobre Internet y otras redes accesibles, han hecho que los l�mites nacionales sean invisibles en muchos casos. Esto se ha traducido en la necesidad de que las aplicaciones soporten la internacionalizaci�n (frecuentemente llamada "i18n" porque 18 es el n�mero de letras entre la "i" y la "n") y localization.

Struts se construye sobre la plataforma Java proporcionada para construir aplicaciones internacionalizadas y localizadas. Los conceptos clava para familiarizarnos con ellos son:

  • Locale - La clase fundamental Java que soporta internacionalizaci�n es java.util.Locale. Toda Locale representa una elecci�n particular de pa�s e idioma (adem�s de variantes opcionales del idioma), y tambi�n un conjunto de asumpciones de formateo para cosas como los n�meros y las fechas.
  • ResourceBundle - La clase java.util.ResourceBundle proporciona la herramienta fundamental para el soporte de mensajes en varios idiomas.
  • PropertyResourceBundle - Una de las implementaciones est�ndard de ResourceBundle que nos permite definir recursos usando la misma sintaxis "nombe=valor" usada para inicializar ficheros de propiedades. Esto es muy conveniente para preparar paquetes de recursos con mensajes que son usados en una aplicaci�n Web, porque estos mensajes normalmente est�n orientados a texto.
  • MessageFormat - La clase java.text.MessageFormat nos permite reemplazar porciones de un string de un mensaje (en este cado, recuperado de un paquete de recursos) con argumentos especificados en tiempo de ejecuci�n. Esto es �til en casos donde est�mos creando una sentencia, pero las palabras podr�an aparecer en diferente orden en diferentes idiomas. El string contenedor {0} del mensaje es reemplazado por el primer argumento, {1} es reemplazado por el segundo argumento, etc.
  • MessageResources - La clase Struts org.apache.struts.util.MessageResources nos permite tratar un conjunto de paquetes de recursos como una base de datos, y nos permite solicitar un string de mensajes particular para una Localidad particular (normalmente asociado con el usuario actual) en lugar de la localidad por defecto en la que el propio servidor se est� ejecutando.

Por favor, observa que el soporte de i18n en un marco de trabajo como Struts est� limitado a la presentaci�n de texto e im�genes internacionalizadas al usuario.. El soporte para localidades espec�ficas m�todos de entrada (usado con idiomas como el Japon�s, el Chino y el Koreano) se deja al dispositivo del cliente, que normalmente es un navegador Web.

Para una aplicaci�n internacionalizada, seguimos los pasos descritos en el documento Internationalization del paquete de documentaci�n del JDK de nuestra plataforma para crear un fichero de propiedades que contenga los mensajes para cada idioma. M�s adelante, un ejemplo ilustrar� esto.

Asumimos que nuestro c�digo fuente se ha creado en el paquete com.mycompany.mypackage, por eso est� almacenado en un directorio (relativo a nuestro directorio fuente) llamado com/mycompany/mypackage. Para crear un paquete de recursos llamado com.mycompany.mypackage.MyResources, creariamos los siguientes ficheros en el directorio com/mycompany/mypackage:

  • MyResources.properties - Contiene los mensajes del idioma por defecto de nuestro servidor. Si el idioma por defecto es Ingl�s, podr�amos tener una entrada como esta:prompt.hello=Hello
  • MyResources_xx.properties - Contiene los mismos mensajes en el idioma cuyo c�digo de idioma ISO es "xx". Para una versi�n Espa�ola del mensaje mostrado arriba, tendr�amos esta entrada: prompt.hello=Hola. Podemos tener ficheros de recursos para tantos idiomas como necesitemos.

Cuando configuramos el servlet controlador en el descriptor de despliegue de la aplicaci�n Web, una de las cosas que necesitamos definir en un par�metro de inicializaci�n es el nombre base del paquete de recursos para la aplicaci�n. En el caso descrito arriba, ser�a com.mycompany.mypackage.MyResources.

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
    <param-name>application</param-name>
    <param-value>com.mycompany.mypackage.MyResources</param-value>
  </init-param>
  <.../>
</servlet>

Los importante para este paquete de recursos es encontrarse en el classpath de nuestra aplicaci�n. Otra aproximaci�n es almacenar el fichero MyResources.properties en la carpeta classes de nuestra aplicaci�n. Entonces podremos especificar simplemente "myResources" como el valor de la aplicaci�n. Debemos tener cuidado de no borrarlo si construimos scripts de borrado de clases como parte de una fuente de "limpieza".

Si lo hace, hay una tarea de Ant a ejecutar cuando compilemos nuestra aplicaci�n que copia los contenidos de un directorio src/conf al directorio classes:

        
<!-- Copy any configuration files -->
        <copy todir="classes">
            <fileset dir="src/conf"/>
        </copy>

.�Interacciones de Forms y FormBean

Una vez u otra, la mayor�a de los desarrolladores web han construido formularios usando las capacidades est�ndard del HTML, como la etiqueta <input>. Los usuarios esperan que las aplicaciones interactivas tengan ciertos comportamientos, y uno de estos est� relacionado con el manejo de errores -- si el usuario comete un error, la aplicaci�n deber�a permitirle corregir s�lo lo que necesita ser modificado -- sin tener que re-introducir cualquier parte del resto de la informaci�n de la p�gina o formulario actual.

Conseguir esto es tedioso y aburrido cuando codificamos usando HTML y p�ginas JSP. Por ejemplo, un elemento de entrada para un campo username podr�a parecerse a esto (en JSP):

<input type="text" name="username"
      value="<%= loginBean.getUsername() %>"/>

lo que es dificil de teclear correctamente, confunde a los desarrolladores HTML que no tienen conocimientos sobre conceptos de programaci�n, y puede causar problemas con editores HTML. En su lugar Struts proporciona una facilidad comprensiva para construir formularios, basada en la facilidad de las Librer�as de Etiquetas Personalizadas de JSP 1.1. El caso de arriba ser�a renderizado de esta forma usando Struts:

<html:text property="username"/>

sin la necesidad de refirnos explicitamente al formulario JavaBean del que se recupera el valor inicial. Esto lo maneja autom�ticamente el marco de trabajo.

Algunas veces los formularios HTML se usan para cargar otros ficheros. La mayor�a de los navegadores soportan esto a trav�s de un elemento <input type="file">, que genera un bot�n navegador de ficheros, pero es cosa del desarrollador manejar los ficheros entrantes. Struts maneja estos formularios "multipart" de la misma forma que los formularios normales. En la siguiente secci�n, usaremos Struts para crear un simple formulario de login, y tambi�n un simple formulario multiparte.

.�Construir Formularios con Struts

Un ejemplo completo de un formulario de login ilustrara c�mo Struts trata con los formularios de una forma menos dolorosa que usar s�lo las facilidades HTML y JSP estandards. Consideremos la siguiente p�gina (basada en la aplicaci�n de ejemplo incluida con Struts) llamada logon.jsp:

<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld"
        prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"
        prefix="bean" %>
<html:html>
<head>
<title>
  <bean:message key="logon.title"/>
</title>
<body bgcolor="white">
<html:errors/>
<html:form action="/logon" focus="username">
<table border="0" width="100%">
  <tr>
    <th align="right">
      <html:message key="prompt.username"/>
    </th>
    <td align="left">
      <html:text property="username"
       size="16"/>
    </td>
  </tr>
  <tr>
    <th align="right">
      <html:message key="prompt.password"/>
    </th>
    <td align="left">
      <html:password property="password"
           size="16"/>
    </td>
  </tr>
  <tr>
    <td align="right">
      <html:submit>
        <bean:message key="button.submit"/>
      </html:submit>
    </td>
    <td align="right">
      <html:reset>
        <bean:message key="button.reset"/>
      </html:reset>
    </td>
  </tr>
</table>
</html:form>
</body>
</html:html>

Los siguientes �tems ilustran las caracter�sticas clave del manejo de formularios en Struts, basadas en este ejemplo:

  • La directiva taglib le dice al compilador de la p�gina JSP donde encontrar el tag library descriptor para la librer�a de etiquetas Struts. En este caso, estamos usando bean como el prefijo que identifica las etiquetas de la librer�a struts-bean, y "html" como el prefijo que identifica las etiquetas de la librer�a struts-html. Se puede usar cualquier prefijo que deseemos.
  • Esta p�gina usa varias ocurrencias de la librer�a de mensajes para buscar los strings de mensajes internacionalizados desde un objeto MessageResources que contiene todos los recursos de esta aplicaci�n. Para que esta p�gina funcione, se deben definir las siguientes claves de mensajes en estos recursos:
    • logon.title - T�tulo de la p�gina de login.
    • prompt.username - Un string para pedir el "Username:"
    • prompt.password - Un string para pedir la "Password:"
    • button.submit - Etiqueta para el bot�n "Submit"
    • button.reset - Etiqueta para el bot�n "Reset"

    Cuando el usuario entra, la aplicaci�n puede almacenar un objeto Locale en la sesi�n de este usuario. Este Locale se usar� para seleccionar mensajes en el idioma apropiado. Esto se hace sencillo de implementar dando al usario una opci�n para elegir el idioma -- simplemente cambiamos el objeto Locale almacenado, y todos los mensajes se modificaran autom�ticamente.

  • Las banderas de error muestran cualquier mensaje de error que haya sido almacenado por un componente de l�gica de negocio, o ninguna si no se ha almacenado ning�n error. Esta etiqueta se describir� m�s adelante.
  • La etiqueta form renderiza un elemento <form> HTML, bas�ndose en los atributos especificados. Tambi�n asocia todos los campos que hay dentro del formulario con un FormBean con �mbito de sesi�n que se almacena bajo la clave logonForm. El desarrollador de Struts proporciona la implementaci�n Java para este bean de formulario, extendiendo la clase ActionForm de Struts. Este bean se usa para proporcionar valores iniciales para todos los campos de entrada que tienen nombres que corresponden con nombres de propiedades del bean. Si no se encuentra un bean apropiado, se crear� uno nuevo autom�ticamente, usando el nombre de la clase Java especificado.
  • El bean formulario tambi�n se puede especifiar en el fichero de configuraci�n de Struts, en cuyo caso se pueden omitir el Nombre y el Tipo. (Puedes ver m�s detalles en Fichero de Configuraci�n para Action Mappings).
  • La etiqueta text se renderiza como un elemento <input> de HTML del tipo "text". En este caso tambi�n se han especificado el n�mero de caracteres y la posici�n a ocupar en la ventana del navegador. Cuando se ejecuta esta p�gina, el valor actual de la propiedad username del bean correspondiente (es decir, el valor devuelto por getUsername()).
  • La etiqueta password se usa de forma similar. La diferencia est� en que el navegador mostrar� asteriscos, en lugar del valor de entrada, mientras el usuario teclea su password...
  • Las etiquetas submit y reset generan los botones correspondientes en la parte inferior del formulario. Las etiquetas de texto para cada bot�n se crean usando la librer�a de mensajes, como las peticiones, para que estos valores sean internacionalizados.

Manejar formularios multiparte tambi�n es sencillo. Obviamente cuando creamos un formulario multiparte est�mos creando un formulario que al menos tiene un entrada del tipo "file". El primer paso para crear el formulario multiparte es utlizar la librer�a de etiquetas struts-html para crear la p�gina de presentaci�n:

<%@page language="java">
<%@taglib uri="/WEB-INF/struts-html.tld"
       prefix="html">
<html:form action="uploadAction.do">
  Please Input Text:
  <html:text property="myText"><br/>
  Please Input The File You Wish to Upload:<br/>
  <html:file property="myFile"><br />
  <html:submit />
</html:form>

El siguiente paso es crear nuestro bean ActionForm :

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
public class UploadForm extends ActionForm {
  protected String myText;
  protected FormFile myFile;
  public void setMyText(String text) {
    myText = text;
  }
  public String getMyText() {
    return myText;
  }
  public void setMyFile(FormFile file) {
    myFile = file;
  }
  public FormFile getMyFile() {
    return myFile;
  }
}

Podemos ver los Javadocs del FormFile para ver los m�todos que expone para manipular y subir ficheros. Tambi�n podemos ver los Javadocs para ActionServlet y ActionMapping para ver los distintos par�metros que podemos especificar para cambiar la forma en que se (suben) cargan los ficheros. B�sicamente en nuestro m�todo peform() de nuestra clase action deber�amos llamar a ((UploadForm) form).getMyFile() para recuperar el FormFile y hacer lo que queramos con �l.

.�Tipos de Campos de Entrada Soportados

Struts define etiquetas HTML para todos estos tipos de campos de entrada:

En cada caso, una etiqueta de campo debe est�r anidada dentro de una etiqueta form, por eso los campos saben qu� bean utilizar para inicializar los valores mostrados.

.�Otras �tiles Etiquetas de Presentaci�n

Hay varias etiquetas �tiles para crear presentaciones, consulta la documentaci�n de cada librer�a de etiquetas especifica, junto con la Gu�a de Desarrolladores de Etiquetas, para m�s informaci�n:

  • [logic] iterate repite su cuerpo de etiqueta una vez por cada elemento de una colecci�n especificada (que puede ser una Enumeration, un Hashtable, un Vector, o un array de objetos).
  • [logic] present dependiendo del atributo que se especifique, esta etiqueta chequea la solicitud actual, y evalua el contenido de los campos anidados de esta etiqueta s�lo si hay un valor presente. S�lo se puede usar uno de los atributos en una ocurrencia de esta etiqueta, a menos que utilicemos el atributo property, en cuyo caso tambi�n es necesario el nombre del atributo. Los atributos incluyen cookie, header, name, parameter, property, role, scope, y user.
  • [logic] notPresent el contrario de la etiqueta present, notPresent proporciona la misma funcionalidad pero cuando el atributo especificado no est� presente.
  • [html] link genera un elemento <a> HTML como una definici�n de un enlace o un hiperenlace a la URL especificada, y autom�ticamente aplica codificaci�n URL para mantener el estado de la sesi�n en la ausencia del soporte de cookies.
  • [html] img genera un elemento <img> HTML con la habilidad de modificar din�micamente las URLs especificadas por los atributos "src" y "lowsrc" de la misma forma en que se puede hacer con <html:link>.
  • [bean] parameter recupera el valor del par�metro solicitado, y define el resultado como un atributo de �mbito de p�gina del tipo String o String[].

.�Validaci�n Autom�tica de Formularios

Adem�s de las interacciones entre el formulario y el bean descrita arriba, Struts ofrece una facilidad adicional para validar los campos de entrada que ha recibido. Para utilizar esta caracter�stica, sobreesribimos el siguiente m�todo en nuestra clase ActionForm:

public ActionErrors
  validate(ActionMapping mapping,
    HttpServletRequest request);

El m�todo validate() es llamado por el servlet controlador despu�s de que se hayan rellando las propiedades del bean, pero antes de se llame al m�todo perform() correspondiente de la clase action. El m�todo validate() tiene las siguientes opciones:

  • Realiza las validaciones apropiadas y no encuentra problemas -- Devuelve null o ejemplares de ActionErrors de longitud cero, y el servlet controlador proceder� a llamar al m�todo perform() de la clase Action apropiada.
  • Realiza las validaciones apropiadas y encuentra problemas -- Devuelve un ejemplar de ActionErrors conteniendo ActionError's, que son clases que contienen las claves del mensaje de error (dentro del paquete MessageResources de la aplicaci�n) que se deber�an mostrar. El servlet controlador almacena este array como un atributo de la solicitud disponible para usarse por la etiqueta <html:errors>, y devolver� el control al formulario de entrada (identificado por la propiedad input de este ActionMapping).

Como se mencion� anteriormente, esta caracter�stica es totalmente opcional. La implementaci�n por defecto de validate() devuelve null, y el servlet controlador asumir� que no se requiere que se haga ninguna validaci�n por parte de la clase Action.

Una aproximaci�n com�n es realizar validaciones iniciales usando el m�todo validate(), y luego manejar la validaci�n de la "l�gica de negocio" desde el objeto Action.

Un paquete opcional para realizar validaciones ActionForm est� disponible en la web site de David Winterfeldt's.

.�Otras T�cnicas de Presentaci�n

Aunque el aspecto y el comportamietno de nuestra aplicaci�n puede construirse completamente bas�ndonos en las capacidades est�ndards de JSP y la librer�a de etiquetas de Struts, deber�amos considerar emplear otras t�cnicas que mejoren la reutilizaci�n de componentes, reduzca los esfuerzos de mantenimiento, y/o reduzca los errores. En las siguientes secciones se explican varias opciones.

.�Etiquetas Personalizadas Espec�ficas de la Aplicaci�n

M�s all� del uso de las etiquetas personalizadas proporcioandas por la librer�a de Struts, es f�cil crear etiquetas que sean espec�ficas de la aplicaci�n que estamos construyendo, para asistirnos en la creaci�n del interface de usuario. La aplicaci�n de ejemplo incluida con Struts ilustra este principio creando las siguientes etiquetas �nicamente para la implementaci�n de esta aplicaci�n:

  • checkLogon - Chequea la existencia de un objeto session particular, y reenv�a el control a la p�gina de logon si no esite. Esto se usa para capturar casos donde un usuario ha colocado un p�gina del medio de la aplicaci�n en su bookmark e intenta saltarse el login. o si ha expirado la sesi�n de un usuario.
  • linkSubscription - Genera un hiperenlace a una p�gina de detalles para una Subscription, que pasa los valores de la clave primaria requerida como atributos de la solicitud. Esto se usa cuando se listan las subcripciones asociadas con un usuario, y proporciona enlaces para editarlas o borrarlas.
  • linkUser - Genera un hiperenalce a una p�gina de detalles de usuario, que pasa los valores de la clave primaria requerida como un atributo de la solicitud.

El c�digo fuente de estas etiquetas est� en el directorio, src/example, en el paquete org.apache.struts.example, junto con otras clases Java que son usadas por esta aplicaci�n.

.�Composici�n de P�ginas con Includes

Crear la presentaci�n completa de una p�gina en un fichero JSP (con etiquetas personalizadas y beans para acceder a los datos din�micos requeridos) es un aproximaci�n de dise�o muy com�n, y fue empleada en el ejemplo incluido con Struts. Sin embargo, muchas aplicaciones requieren mostrar varias porciones de distinciones l�gicas de nuestra aplicaci�n en una s�la p�gina

Por ejemplo, una aplicaci�n portal, podr�a tener alguna o todas estas capacidades funcionales disponibles en la p�gina "home" del portal:

  • Acceso a un motor de b�squeda para este portal.
  • Uno o m�s displays "alimentadores de noticias" con los t�picos de inter�s personalizados desde el perfil de registro del usuario.
  • Acceso a t�picos de discusi�n relacionados con este portal.
  • Un indicador de "mail esperando" si nuestro portal proporciona cuentas gratuitas de correo.

El desarroolo de los distintos segmentos de esta site es sencillo si podemos dividir el trabajo y asignar los distintos segmentos a diferentes desarrolladores. Luego, podemos usar la capacidad include de las p�ginas JSP para combinar los resultados en una s�la p�gina, o usar la etiqueta include proporcionada por Struts. Hay disponibles tres tipos de include, dependiendo de cuando queremos que ocurra la combinaci�n de la salida:

  • Una directiva <%@ include file="xxxxx" %> puede incluir un fichero que contiene c�digo Java o etiquetas JSP. El c�digo incluido en el fichero puede incluso referenciar variables declaradas antes en la p�gina JSP exterior. El c�digo se pone en l�nea dentro de la otra p�gina JSP antes de que sea compilada y por eso puede contener definitivamente m�s que s�lo c�digo HTML.
  • El include de action (<jsp:include page="xxxxx" flush="true" />) se procesa en el momento de la solicitud, y es manejado de forma transparente por el servidor. Junto con otras cosas, esto significa que podemos realizar el include condicionalmente anidandolo dentro de una etiqueta como equals usando sus atributos de par�metros
  • La etiqueta bean:include toma un argumento "forward" que representa un nombre l�gico mapeado al JSP a incluir, o el argumento "id", que representa la variable string del contexto de la pagina a imprimir en la p�gina JSP.

Otra aproximaci�n a esto ser�a el uso de la librer�a de plantillas de etiquetas de Struts. Puedes ver m�s detalles en la Guia del Desarrollador.

Tiles es una alternativa a la Librer�a de Plantilla de Etiquetas, ofreciendo varias mejoras y nuevas capacidades. Tiles est� disponible en el la web site de Cedric Dumoulin.

.�Componentes de Renderizado de Im�genes

Algunas aplicaciones requieren generar im�genes din�micamente, como cartas de precios sobre una site de informe de stocks. Normalmente se utilizan dos diferentes aproximaciones para obtener estos requerimientos:

  • Renderizar un hiperenlace con una URL que ejecuta una solicitud Servlet. El servlet usa una librer�a gr�fica para renderizar la imagen, selecciona el tipo de contenido apropiadamente (como a image/gif), y envia de vuelta al navegador los bytes de la imagen, que los mostrar� como si hubiera recibido un fichero est�tico.
  • Renderizar el c�digo HTML necesario para descargar un Applet Java que cree el gr�fico necesario. Podemos configurar el gr�fico selecionando los par�metros de inicializaci�n del applet en el c�digo de renderizado, o podemos tener que hacer que el applet haga su propia conexi�n al servidor para recibir estos par�metros.

.�Dibujo de Texto

Algunas aplicaciones requieren que se genere texto o marcas, como XML, din�micamente. Si est� siendo renderizada una p�gina completa, y puede sacarse usando un PrintWriter, es muy f�cil hacerlo desde un Action:

           response.setContentType("text/plain"); // or text/xml
           PrintWriter writer = response.getWriter();
           // use writer to render text
           return(null);

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP