Category : General

Verificación Visual en Formularios, CAPTCHA

Seguramente sabes que significa Captcha . Bueno yo tampoco sabía, según Wikipedia es el acrónimo de Completely Automated Public Turing test to tell Computers and Humans Apart ó Prueba de Turing pública y automática para diferenciar máquinas y humanos.

En algunas ocasiones te habrás topado con algún formulario donde aparece una imagen extraña donde debes teclear un código que en teoría solo un humano puede reconocer. De esta forma se evita que robots entren y agreguen publicidad indeseada de forma automática en comentarios de blogs o en algunos foros.


Haremos un ejemplo sencillo para mostrar esta funcionalidad, desde luego Struts2 no tiene un método directo para hacerlo y de hecho la solución que damos puede ser usada sin ningún framework, pero aun asi veremos como se configura el Action para recibir la respuesta del usuario.

Para este ejemplo debes descargarte la libreria SimpleCaptcha-1.1.1.jar y agregarla junto con las demas librerias de tu proyecto. La puedes encontrar y descargar aqui:

Este proyecto creado por James Childers es sencillo y fácil de utilizar, permite crear la imagen con el código de verificación utilizando un servlet que debe darse de alta en el archivo web.xml de nuestro proyecto.

Te muestro el archivo a continuación.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<servlet>
<servlet-name>SimpleCaptcha</servlet-name>
<servlet-class>nl.captcha.servlet.SimpleCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimpleCaptcha</servlet-name>
<url-pattern>/simpleImg.jpg</url-pattern>
</servlet-mapping>

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

Agregamos el Action en struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name="struts.enable.DynamicMethodInvocation" value="false" />
   <constant name="struts.devMode" value="false" />

<package name=»default» namespace=»/» extends=»struts-default»>
<action name=»Inicio»>
<result>/index.jsp</result>
</action>
<action name=»Validar» class=»ejemplos.struts2.actions.AccionValidarCodigo»>
<result name=»input»>/index.jsp</result>
<result name=»error»>/index.jsp</result>
<result>/validacionExitosa.jsp</result>
</action>
</package>
</struts>

Puedes ver que solo agregamos un servlet, sin embargo, la librería SimpleCapcha tiene algunas opciones mas para soportar tamaños especificos de imagenes y juegos de caracteres.

Aqui te muestro la clase Action que usaremos: AccionValidarCodigo.

package ejemplos.struts2.actions;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import nl.captcha.Captcha;

public class AccionValidarCodigo extends ActionSupport {
@Override
public String execute() throws Exception {
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
HttpSession session = request.getSession();
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
request.setCharacterEncoding(«UTF-8»);
String answer = request.getParameter(«answer»);
if (captcha.isCorrect(answer)) {
return SUCCESS;
} else {
addActionError(«Código inválido, trate nuevamente.»);
return ERROR;
}
}
}

Como puedes ver, el servlet que dimos de alta guarda en la sesión la variable que será cotejada con el dato de entrada del formulario.
Puedes ver que es muy sencilla, lo importante que debes notar es que el servlet de SimpleCaptcha es la que se encarga de generar la imagen con el código de verificación, siempre y cuando la llames igual que como la definiste en el archivo web.xml, es

Usaremos dos JSPs parar este ejemplo, el que se encarga de mostrar el sencillo formulario y el que muestra el mensaje de validación exitosa.

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
       <title>Validacion Capcha</title>
       <style>
           .errorMessage {
               color: red;
               font-size: 0.8em;
           }
           .label {
               color:#000000;
           }
       </style>
   </head>
   <body>
       <table>
           <tr>
               <td>
                   <h1>Validacion Capcha</h1>
                   <s:form action="Validar" namespace="/" method="POST">
                       <s:actionerror />
                       <img src="simpleImg.jpg" border="0">
                       <s:textfield label="Code" name="answer" size="20" maxlength="10"/>
                       <s:submit value="Verify" align="center" />
                   </s:form>
               </td>
           </tr>
       </table>
   </body>
</html>

El jsp con el mensaje de éxito. validacionExitosa.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
<head>
<title>Validacion Capcha</title>
</head>
<body>
<table><tr><td><h1>Validación exitosa</h1></td></tr></table>
</body>
</html>

Al ejecutar el ejemplo, la pantalla del navegador lucirá asi:


Si se ingresa el código correcto el Framework nos redirige a la página de éxito.


En caso de error vuelver a aparecer el formulario.


Bueno espero que sea de interés este post, dejen sus comentarios.

Espero poner pronto el código. Hasta el próximo post.


Carga de archivo, Interceptor FileUpload con Struts2

En este ejemplo veremos nuevamente el uso interceptores, como ya hemos mencionado en otros post, Struts2 posee una amplia gama de funciones que permiten hacer mas ágil el desarrollo y que están puestas a disposición de los desarrolladores a través de los interceptores que vienen por default.

En esta ocasión veremos un interceptor que nos permite realizar una de las funciones con la que comúnmente nos topamos en el desarrollo de aplicaciones empresariales, se trata de la carga de archivos.

El interceptor FileUpload está dado de alta en la pila de interceptores del paquete default que maneja Struts2.

org.apache.struts2.interceptor.FileUploadInterceptor

Si ya tenemos configurado nuestro proyecto solo es necesario agregar estas librerías:

  • commons-fileupload-1.2.1.jar
  • commons-io-1.3.2.jar

Si no recuerdas que otras librerías son requeridas o como configurar tu proyecto para usar Struts2 puedes regresar al primer ejemplo que vimos en este mismo blog sobre como hacerlo:

Lo primero que haremos es crear un formulario de carga de archivos, el código lo muestro a continuación:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Carga de archivos con interceptores</title>
</head>
<body>
<h1>Carga de archivos con interceptores</h1>
<s:form action="CargaArchivo" method="post" enctype="multipart/form-data">
<s:file name="archivo" label="Carga Archivo"/>
<s:submit value="Subir" align="center"/>
</s:form>
</body>
</html>

Despues creamos la clase AccionCargaArchivo que se encargará de recibir y manejar el contenido del archivo.

package ejemplos.struts2.accion;
import com.opensymphony.xwork2.ActionSupport;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class AccionCargaArchivo extends ActionSupport {
private File archivo;
private String archivoContentType;
private String archivoFileName;
private String datos = "";

public String execute() {
try{
BufferedReader entrada = new BufferedReader( new FileReader( archivo ) );
if ( archivoContentType.equals("text/plain")){
String aux;
while((aux = entrada.readLine()) != null){
datos += aux + "n";
}
}
}catch(Exception e){
e.printStackTrace();
}
return SUCCESS;
}

public File getArchivo() {
return archivo;
}

public void setArchivo(File archivo) {
this.archivo = archivo;
}

public String getArchivoContentType() {
return archivoContentType;
}

public void setArchivoContentType(String archivoContentType) {
this.archivoContentType = archivoContentType;
}

public String getArchivoFileName() {
return archivoFileName;
}

public void setArchivoFileName(String archivoFileName) {
this.archivoFileName = archivoFileName;
}

public String getDatos() {
return datos;
}

public void setDatos(String datos) {
this.datos = datos;
}
}

Del la clase Action anterior observa cuidadosamente las siguientes variables:

  • File nombreDeArchivo;
  • String nombreDeArchivoContentType;
  • String nombreDeArchivoFileName;

Como puedes ver la variable de tipo File tiene un nombre arbitrario, sin embargo las otras dos deben cumplir con un formato establecido para que el interceptor pueda encontrarlas y establecer los datos correspondientes al tipo de contenido y al nombre del archivo.

  • archivo – Es el nombre del archivo.
  • archivoContentType – Contiene el tipo de contenido del archivo.
  • archivoFileName – Contiene el nombre del archivo tal como fue almacenado en el servidor.

Esto es todo lo que debe hacerse para que el Framework a través del inteceptor tome el archivo y lo relacione con las variables que declaramos en el Action.

También haremos la jsp de respuesta, que solo mostrará algunos datos del archivo que se esta subiendo al servidor.

El código es el siguiente:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>El archivo fu&eacute; recibido con exito!</h1>
El tipo del contenido es : <s:property value="archivoContentType"/><br>
Nombre del archivo es : <s:property value="archivoFileName"/><br>
Nombre del archivo temporal : <s:property value="archivo.name"/><br>
Contenido del archivo :<br>
<s:textarea name="dat" value="%{datos}" cols="50" />
</body>
</html>

y por último haremos cambios necesarios en el archivo de configuración de Struts2 para hacer referencia a las clases y jsps que acabamos de crear.

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<package name="default" namespace="/" extends="struts-default">
<action name="FormularioCargaArchivo" >
<result>/formularioDeCargaDeArchivo.jsp</result>
</action>
<action name="CargaArchivo" class="ejemplos.struts2.accion.AccionCargaArchivo">
<result>/archivoCargado.jsp</result>
<result name="input">/formularioDeCargaDeArchivo.jsp</result>
</action>
</package>
</struts>

El código fuente de todos los archivos aqui:

Si corres el ejemplo y mandas llamar al formulario de carga de archivo debe aparecerte algo como lo siguiente:

formularioDeCargaDeArchivo.jsp

Como puedes ver nos aparece el campo para especificar el archivo que queremos subir.

Para este ejemplo solo cargaremos archivos de texto plano y visualizaremos el contenido.


Damos click en el boton de Subir y tendremos una respuesta como esta:


En esta jsp mostramos el tipo de datos del archivo, el nombre del archivo y el nombre que tendrá temporalmente en el servidor mientras es procesado durante el tiempo que se ejecute nuestra acción.

Despues mostramos simplemente el contenido. Listo ya tenemos el ejemplo.

Es importante que sepas que el archivo temporal se removera del servidor una vez que el ciclo de llamada a la acción termine.


Espero que te sirva este ejemplo, si tienes alguna duda o comentario hazmelo saber. Hasta el proximo post.


Struts1 vs Struts2

La siguiente es una comparación tomada y traducida de la página de Rose India, un pequeño articulo que anima a los desarrolladores de Struts1 a comenzar a usar Struts2
Les pongo la liga de la página.





También puedes encontrar muchos otros ejemplos de programación en Java.

Struts1 vs Struts2

Clases Action

Struts1
Se Requiere extender de la una clase Action abstracta. El problema común en Struts1 es que se programan clases abstractas en lugar de interfaces.
Struts2
Un Action puede implementar una interfaz Action, además de otras interfaces que le permitan integrar mas servicios. Struts2 provee de una clase base ActionSupport que implementa las interfaces comúnmente usadas. Además esta interfaz no es requerida. Cualquier POJO con un método de ejecución puede ser usado como Action en Struts2

Modelo de hilos

Struts1
Las Actions implementan el patrón singleton y deben ser thread-safe por lo que puede haber solo una instancia de una clase para manejar todas las peticiones para ese Action. La estrategia singleton pone restricciones sobre lo que podemos hacer con los Actions de Struts1 y se requiere un cuidado extra para desarrollar. Los recursos usados para los Actions deben ser thread-safe o sincronized.
Struts2
Los objetos Action son instanciados por cada petición, por lo que no hay problemas de tipo con la seguridad de hilos. En la práctica, los contenedores de servlets generan muchas instancias, así que un objeto mas no representa problemas de rendimiento y de impacto en el garbage collection

Dependencia de los Servlets

Struts1
Las Actions tiene dependencias de la API de Servlets dado que HttpServletRequest y HttpServletResponse son pasados al método excecute cuando la Action es invocada.
Struts2
Las Actions no están acopladas al contenedor. A menudo el contexto de los servlets esta representado por simples Maps, permitiendo a las Actions ser probadas de forma aislada. Las Actions de Struts2 puede mantener el uso del request y el response si se requiere. De cualquier forma, otros elementos de la arquitectura reducen o eliminan la necesidad de acceder a HttpServetRequest o a HttpServletResponse directamente.

Manejo de pruebas

Struts1
El principal obstáculo para las Actions de Struts1 es que la ejecución de métodos requiere de la API de Servlets. Una extensión de terceras partes, como Struts TestCase, que ofrece un conjunto de simuladores para objetos de Struts1.
Struts2
Las Actions pueden ser probadas instanciado la Action, estableciendo propiedades e invocando métodos. El soporte a la Inyección de Dependecias permite hacer las pruebas de forma simple.

Recolección de datos de entrada

Struts1
Es necesario el uso de un objeto ActionForm para capturar las entradas. Como las Actions, todos los ActionForm deben extender de una clase. Como algunos JavaBeans no implementan de ActionForm los desarrolladores a menudo crean clases redundantes para capturar a las entradas. Los DynaBeans pueden ser usados de forma alternativa para crear clases ActionForm convencionales, pero, los desarrolladores deben JavaBeans existentes.
Struts2
Usa las propiedades de las Actions para manejar las entradas, elimina la necesidad de un segundo objeto de entrada. las propiedades de entrada pueden ser objetos de una amplia variedad que incluso pueden tener sus propias variables. Las propiedades de las Action pueden usadas por la pagina Web por medio de los TagLibs. Struts2 soporta incluso el patrón de ActionForm, asi como objetos y acciones POJO. Tipos de objetos, incluyendo negocios o objetos de dominio, pueden ser usados como objetos en entrada y salida. La característica ModelDriven simplifica las referencias por taglib a objetos POJO.

Lenguaje de Expresiones

Struts1
Esta integrado con JSTL, así que usa el JSTL EL. El EL tiene una traza grafica de objetos básica y una relativamente pobre colección e indexación de soporte a propiedades.
Struts2
Puede usarse JSTL, pero el marco de trabajo soporta ademas un lenguaje de expresiones mas poderoso y flexible llamado «Object Graph Notation Language» (OGNL)

Vinculación de objetos de la vista

Struts1
Usa el mecanismo estándar de JSPS para el vincular objetos en el contexto de las páginas.
Struts2
Usa una tecnología llamada «ValueStack» donde los taglibs pueden acceder a valores sin estar acoplados a la vista donde el tipo de objeto se renderea. La estrategia del «ValueStack» permite reutilizar vistas gracias al rango de variables que pueden tener el mismo nombre pero tipo diferente tipos de propiedades.

Conversion de tipo

Struts1
Las propiedades de los ActionForm son usualmente Strings. Struts1 usa comúnmente Commons-Beanutils para la conversión de tipos. Las conversiones son configurables por clase y no por instancia.
Struts2
Usa OGNL para la conversión de tipos. El marco de trabajo incluye convertidores para objetos básicos y tipos primitivos.

Validación

Struts1
Soporta validación manual por medio de métodos en el ActionForm, o a través de una extensión de los Commons Validator. Las clases pueden tener diferentes contextos de validación para la misma clase, pero no pueden encadenar validaciones en sub objetos.
Struts2
Soporta validación manual por medio de métodos y por el marco de trabajo XWork Validation. El XWork soporta encadenamiento de validaciones en las subpropiedades usando las validaciones definidas para las propiedades de la clase y el contexto de validación.

Control de la ejecución del Action

Struts1
Soporta Request Porcessors (Ciclos de vida) separados por cada módulo, pero todas las Actions en el módulo deben compartir el mismo ciclo de vida.
Struts2
Soporta ciclos de vida diferentes, uno por Action por medio de la pila de interceptores. Pilas configurables pueden ser creadas y usadas con diferentes Actions si es necesario.

Esta es una tabla excelente para observar solo algunas de las mejoras en Struts2, sin embargo yo pondría especial énfasis en las ventajas que ofrecen los interceptores en Struts2, ya que permiten aislar gran parte de operaciones de control que son comunes en todas las aplicaciones Web, entre ellas una muy importante, el manejo de la sesión y la restricción de acceso a usuarios con permisos. Aislando estas operaciones es mas fácil reutilizar el código en otras aplicaciones.
Además los interceptores que vienen por default en el marco de trabajo resuelven y aislan una gran cantidad trabajo, como carga de archivos, validaciones, intenacionalizacion y mas. Solo tendremos que usar lo que los desarrolladores de Struts2 ponen a nuestra disposición.

Espero que este post les sea de utilidad, no olviden dejar sus comentarios si tienen alguna duda sobre los ejemplos o si tienen alguna sugerencia para el blog.

Hasta el próximo post.


2.1 – Manejo de Sesión en Struts2

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión

En este ejemplo, el segundo de Struts2, veremos como restringir el acceso a páginas privadas mediante el uso de la sesión y de los interceptores, también mostraremos como desplegar una lista de resultados utilizando las etiquetas de Struts2.

Antes de comenzar es necesario tener a la mano el código del ejemplo anterior pues lo usaremos como base, puedes verlo dando click acá:




El Primer Ejemplo

Haremos algunos cambios en el código, pero es necesario que notes algunas cosas que el primer ejemplo adelantaba sobre el manejo de la sesión.

Como podrás ver la clase AccionEntrar.java esta extendiendo de ActionSupport y también se implementan los métodos de la interfaz SessionAware, esta última es la que nos permitirá hacer uso de la sesión dentro del marco de trabajo.

public class AccionEntrar extends ActionSupport implements SessionAware{
  private Map session;
  private String mensajeError;
  private String usr;
  private String pas;
…

Al implementar SessionAware se definen los métodos:

        public Map getSession() {
          return session;
      }

public void setSession(Map session) {
this.session = session;
}

y desde luego declaramos la variable session, que es de la clase Map.

En nuestra clase AccionEntrar verificamos los datos del usuario. De ser válidos daremos acceso a la página de bienvenida, si son incorrectos redirigimos a la página de entrada nuevamente. Todo este flujo también esta definido en nuestro archivo de configuración struts.xml.

Pero que pasa si ahora queremos que en nuestra aplicación se despliegue una lista de datos privados que solo pueda verse después de una autenticación válida, mostraremos como hacer eso. Comencemos por agregar una liga para desplegar una lista de usuarios en nuestra página de bienvenida.

Después de la etiqueta de bienvenida agrega esta línea:

<s:a href="DesplegarLista.action">Desplegar lista de productos</s:a>

El código de tu jsp deberá quedar así:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Pagina de Bienvenida</title>
  </head>
  <body>
      <h1>Bienvenido, has entrado al sistema!</h1>
      <s:a href="DesplegarLista.action">Desplegar lista de usuarios</s:a>
  </body>
</html>

para descargar paginaBienvenida.jsp

No olvides poner la declaración de etiquetas de Struts2 cuando sea necesario.

 

<%@ taglib prefix="s" uri="/struts-tags" %>

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión


2.2 – Manejo de Sesión en Struts2

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión

La configuración de struts.xml

También debemos modificar el archivo de configuración struts.xml. Debes agregar la siguiente linea:

<include file="sistema.xml"/>

Tu archivo debe quedar asi al final:

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
  <constant name="struts.enable.DynamicMethodInvocation" value="false" />
  <constant name="struts.devMode" value="false" />

  <package name="default" namespace="/" extends="struts-default">
      <action name="FormularioEntrada">
          <result>/formularioEntrada.jsp</result>
      </action>
      <action name="Entrar" class="ejemplos.struts2.action.AccionEntrar">
          <result name="input">/formularioEntrada.jsp</result>
          <result name="error">/formularioEntrada.jsp</result>
          <result>/paginaBienvenida.jsp</result>
      </action>
  </package>
  <include file="sistema.xml"/>
</struts>

Como podrás ver ahora hacemos referencia a otro archivo de configuración de Struts2 en donde están las peticiones que se hacen solo por usuarios que están identificados por nuestra aplicación como válidos. El archivo sistema.xml deberá ser algo como esto:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
  <package name="sistema" namespace="/" extends="struts-default">
      <interceptors>
          <interceptor name="iterceptorAtuenticacion" class="ejemplos.struts2.inter.InterAutenticacion" />
          <interceptor-stack name="secureStack">
              <interceptor-ref name="iterceptorAtuenticacion" />
              <interceptor-ref name="defaultStack" />
          </interceptor-stack>
      </interceptors>
      <default-interceptor-ref name="secureStack" />

      <global-results>
          <result name="login" type="redirect">/FormularioEntrada.action</result>
      </global-results>

      <action name="DesplegarLista" class="ejemplos.struts2.action.AccionDesplegarLista">
          <result name="error">/formularioEntrada.jsp</result>
          <result>/desplegarLista.jsp</result>
      </action>
  </package>
</struts>

Hay algunas cosas nuevas en este archivo de configuración. Ahora estamos creando un “paquete” de declaración para nuestros Actions.

    <package name="sistema" namespace="/" extends="struts-default">

También estamos haciendo la declaración de nuestro interceptor InterAutenticacion, el cual aún no hemos creado.

        <interceptors>
          <interceptor name="iterceptorAtuenticacion" class="ejemplos.struts2.inter.InterAutenticacion" />
          <interceptor-stack name="secureStack">
              <interceptor-ref name="iterceptorAtuenticacion" />
              <interceptor-ref name="defaultStack" />
          </interceptor-stack>
      </interceptors>

Otra cosa importante que hacemos es declarar una pila de interceptores nueva, que agrega nuestro nuevo interceptor a la lista de interceptores que existen por default en el marco de trabajo. Este paso es importante.

    <default-interceptor-ref name="secureStack" />

También hemos agregado un redireccionamiento global para los casos en que no axista una sesión válida y que devuelve al usuario al formulario de entrada:

        <global-results>
          <result name="login" type="redirect">/FormularioEntrada.action</result>
      </global-results>

Y por último, la declaración de nuestra acción DesplegarLista

        <action name="DesplegarLista" class="ejemplos.struts2.action.AccionDesplegarLista">
          <result name="error">/formularioEntrada.jsp</result>
          <result>/desplegarLista.jsp</result>
      </action>

Bien, hemos terminado con la configuración del archivo nuevo sistema.xml. Pero ahora debemos crear la clase que se encargará de desplegar la lista y del interceptor que nos permitirá discriminar las peticiones válidas de las que no lo son.

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión


2.3 – Manejo de Sesión en Struts2

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión

La clase Action que desplegará la lista

Nuestra clase Action será algo como esto:

package ejemplos.struts2.action;
import ejemplos.struts2.beans.Usuario;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.SessionAware;
import ejemplos.struts2.utilidades.UsuarioHabilitado;

public class AccionDesplegarLista extends ActionSupport implements SessionAware,UsuarioHabilitado{
  private Map session;
  private Usuario usuario;
  private String mensajeError;
  private List miLista;

  public String execute() throws Exception {
      llenarArreglo();
      return SUCCESS;
  }

  public void llenarArreglo(){
      miLista = new ArrayList();
      Usuario usuario1 = new Usuario();
      Usuario usuario2 = new Usuario();
      Usuario usuario3 = new Usuario();
      Usuario usuario4 = new Usuario();
      usuario1.setNombre("Fulano de tal 1");
      usuario2.setNombre("Fulano de tal 2");
      usuario3.setNombre("Fulano de tal 3");
      usuario4.setNombre("Fulano de tal 4");
      miLista.add(usuario1);
      miLista.add(usuario2);
      miLista.add(usuario3);
      miLista.add(usuario4);
  }

  public List getMiLista(){
      return miLista;
  }

  public Map getSession() {
      return session;
  }

  public void setSession(Map session) {
      this.session = session;
  }

  public void setUsuario(Usuario usuario){
      this.usuario = usuario;
  }

  public Usuario getUsuario(){
      return usuario;
  }

  public void setMensajeError(String mensajeError) {
      this.mensajeError = mensajeError;
  }
}

Para descargar AccionDesplegarLista.java

Hay varias cosas que se deben notar en esta clase, la primera de ellas es que aunque tenemos declarada una variable de sesión, no verificamos si es nula o no, simplemente la usamos, mas adelante veremos porque.

    usuario = (Usuario)session.get("usuario");

No hacemos ninguna validación sobre si existe o no sesión y por lo tanto, tampoco verificamos si hay una instancia de “usuario” referenciada en la sesion. Será el interceptor el que se encargue de hacer la validación. En esta clase simplemente llenamos un arreglo con los datos de nuestra lista.

    public String execute() throws Exception {
      usuario = (Usuario)session.get("usuario");
      llenarArreglo();
      return SUCCESS;
  }

  public void llenarArreglo(){
      miLista = new ArrayList();
      Usuario usuario1 = new Usuario();
      Usuario usuario2 = new Usuario();
      Usuario usuario3 = new Usuario();
      Usuario usuario4 = new Usuario();
      usuario1.setNombre("Fulano de tal 1");
      usuario2.setNombre("Fulano de tal 2");
      usuario3.setNombre("Fulano de tal 3");
      usuario4.setNombre("Fulano de tal 4");
      miLista.add(usuario1);
      miLista.add(usuario2);
      miLista.add(usuario3);
      miLista.add(usuario4);
  }

Antes de ver como es el interceptor, mostraremos como debe quedar el jsp que se encarga de desplegar los datos.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">

<html>
  <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Ejemplos con Struts 2</title>
  </head>
  <body>
      <h1>Lista de usuarios del sistema</h1>
      Usuario:<s:property value="usuario.nombre" /><br>
      <s:iterator value="miLista">
          <s:property value="nombre" /><br>
      </s:iterator>
  </body>
</html>

Para descargar desplegarLista.jsp

El jsp es muy sencillo, pero debes notar que estamos haciendo uso de dos de las instancias a las que hacemos referencia o creamos en nuestra clase AccionDesplegarLista, y son:

usuario.nombre

miLista

Te preguntarás como llegarán hasta ahí esos datos cuando se despliegue el jsp, no te preocupes el framework se encargará de “llenar” tu jsp con los valores correctos siempre y cuando estén declarados con el mismo nombre en la clase AccionDesplegarLista.

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión


2.4 – Manejo de Sesión en Struts2

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión

El Interceptor y la sesión

Ahora veremos como debe ser el interceptor. El código se muestra a continuación:

package ejemplos.struts2.inter;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import java.util.Map;
import ejemplos.struts2.beans.Usuario;
import ejemplos.struts2.utilidades.UsuarioHabilitado;

public class InterAutenticacion implements Interceptor {

  public void destroy() { }
  public void init() { }
  public String intercept(ActionInvocation actionInvocation) throws Exception {
      Map session = actionInvocation.getInvocationContext().getSession();
      Usuario usuario = (Usuario) session.get("usuario");
      if (usuario == null) {
          return Action.LOGIN;
      } else {
          Action action = (Action) actionInvocation.getAction();
          if (action instanceof UsuarioHabilitado) {
              ((UsuarioHabilitado) action).setUsuario(usuario);
          }
          return actionInvocation.invoke();
      }
  }
}

Se hacen algunas cosas interesantes, la primera de ellas es que se toma la sesión y se verifica si ya existe una instancia de la clase Usuario, buscando al objeto referenciado por la cadena «usuario».

        Map session = actionInvocation.getInvocationContext().getSession();
      Usuario usuario = (Usuario) session.get("usuario");
      if (usuario == null) {

Si todo está bien y se hace una petición a una acción a la que el usuario tiene permiso, entonces pasamos la referencia del objeto usuario a la acción para que la pueda usar. Para eso tenemos que hacer que nuestras acciones implementen de UsuarioHabilitado.

            Action action = (Action) actionInvocation.getAction();
          if (action instanceof UsuarioHabilitado) {
              ((UsuarioHabilitado) action).setUsuario(usuario);
          }

Implementar de esta interfaz podría permitirnos hacer una validación adicional, para aseguramos que solo cuando nuestras clases implementen a UsuarioHabilitado podran ser llamadas, de lo contrario se cambia el flujo al formulario de entrada. En nuestro ejemplo solo sirve para pasar los datos del usuario a la acción.

La interfaz se muestra a continuación:

package ejemplos.struts2.utilidades;
import ejemplos.struts2.beans.Usuario;

public interface UsuarioHabilitado {
  public void setUsuario(Usuario usuario);
}

Para descargar UsuarioHabilitado.java

En donde se declara un solo método setUsuario y servirá para pasar la referencia del objeto usuario que le corresponda al usuario que esta haciendo la petición de datos.

Y eso es todo. Ya podemos echar a andar nuestro ejemplo, no olvides como siempre, verificar que las clases que hemos creado estén en los paquetes correctos y si vas a crear tus propias clases sin copiar el código, no olvides ser cuidadoso con los nombres de tus clases al crear los archivos de configuración de Struts2, ya que es muy común equivocarse con las mayusculas y las cosas tardan en funcionar.

Al correr el ejemplo y después de pasar por el formulario de username y password deberá aparecer lo siguiente


Despues das click en desplegar lista


¡Aparace la lista de usuarios!

Pero si intentas llamar a DesplegarLista desde el navegador sin haber pasado por el formulario de entrada de forma directa…

http://localhost:8080/Struts2Ejemplo2/DesplegarLista.action

Podras ver como el marco de trabajo te envía nuevamente al formulario de entrada

(Quiza deberás reiniciar el servidor web para observar esto)

Es el interceptor el que se encargará de redirigir al usuario al formulario de entrada.

Este es un ejemplo bastante simple como podras ver, los flujos de redirección de páginas dependerán mucho de como diseñes tu aplicación. Espero que este ejemplo te sirva para darte una idea de como hacerlo.

Todo el código lo podras descargar de aqui.

(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = «//connect.facebook.net/en_US/all.js#xfbml=1»;
fjs.parentNode.insertBefore(js, fjs);
}(document, ‘script’, ‘facebook-jssdk’));

 

¡Listo! Eso es todo por el momento, espero que el ejemplo sea de utilidad. Hasta el próximo post.

2.1.- Primeros Pasos
2.2.- La configuración de struts.xml
2.3.- La clase Action que desplegará la lista
2.4.- El Interceptor y la sesión


1.1 – Ejemplo de Struts2, el hola mundo

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto

Struts 2 es un marco de trabajo (o framework en ingles) que ofrece muchas ventajas para desarrollar aplicaciones Web con Java y cuenta con nuevas características que facilitan el desarrollo aún mas que en la versión de Struts anterior. Haremos un ejemplo sencillo paso a paso de tal forma que puedas comenzar a trabajar con el marco de trabajo sin demasiada teoria.

 

Puedes seguir los pasos de este ejemplo divido en cinco post o también puedes ver el video para darte una mejor idea de como está organizado el proyecto.

Nuestro ejemplo de Struts2 será algo asi como el Hola Mundo, aunque no tan básico y lo haremos siguiendo estos pasos:

Requisitos

Utilizaremos la IDE de Sun Microsystems NetBeans 6.5.1 para hacer el ejemplo, si no lo tienes puedes descargar la última versión en el siguiente link: http://www.netbeans.org/downloads/index.html. Para evitarte problemas, baja la version completa, asi te aseguras que tiene lo necesario para crear tu proyecto Web. Cuando instales NetBeans, asegurate tambien de incluir Tomcat 6.x en la lista de servidores que puede manejar, ya que es con ese servidor web con el que haremos nuestro ejemplo

Deberás descargar de la pagina de Struts 2 las siguientes librerias

  • commons-fileupload-1.2.2.jar
  • commons-io-2.0.1.jar
  • commons-lang-2.5.jar
  • commons-logging-1.1.1.jar
  • freemarker-2.3.16.jar
  • javassist-3.11.0.GA.jar
  • ognl-3.0.1.jar
  • struts2-core-2.2.3.1.jar
  • xwork-core-2.2.3.1.jar

Las puedes obtener aqui: http://apache.mirrors.tds.net/struts/library/, toma en cuenta que estas librerias van actualizandose con el tiempo y las últiias versiones de estos archivos pueden cambiar, te recomiendo que bajes solo las Essential Dependencies que es un archivo comprimido que contienen solo las librerias de Struts2 necesarias. Es importante que bajes las versiones que vienen en estos paquetes, de lo contrario prodrias tener problemas de compatibilidad entre los mismos, este es un problema común al usar las librerias de Apache.

Essential Dependencies http://apache.webxcreen.org/struts/library/struts-2.2.3.1-lib.zip
Comencemos con nuestro Hola Mundo de Struts2, espero que les sea de utilidad.

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto


1.2 – Ejemplo de Struts2, el hola mundo

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto

Crear el proyecto en NetBeans

Una vez instalado NetBeans, crea un nuevo proyecto Web con el nombre EjemploStruts2.

File>New Project>Java Web>Web Application


Cuando estes creando el proyecto usa un folder dedicado para almacenar tus librerias, habilita el checbox Use Dedicated Folder for Storing Libraries para almacenar mas tarde las librerias de Struts 2.


Selecciona Apache Tomcat 6.0.18 o la versión que esté disponible superior a la 6.


Esa es toda la configuración que necesitaremos, asi que puedes dar click al boton de finish al asistente de NetBeans.

Una vez hecho esto hay que crear la carpeta en la que alojaremos las librerias de Struts 2, te sugiero que lo llames Struts2. Aunque puedes mandar llamar las librerias desde donde quieras a veces es mejor poner todo lo necesario en la misma carpeta que tu proyecto y dejar que NetBeans las ponga en el lugar correcto.


Despues de creado el proyecto, importa las librerias dandole click derecho a la carpeta de proyecto, despues en propiedades, librerias y por último selecciona los archivos de Struts donde las hayas despositado y agregalos.

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto


1.3 – Ejemplo de Struts2, el hola mundo

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto

Configurar el proyecto para usar Struts 2

Al crear tu proyecto en NetBeans, se creará por default un archivo web.xml que tendremos que modificar para agregar el filtro mediante el cual se gestionarán las peticiones a Struts 2. Estas son las lineas que te permitirán hacer dar de alta el filtro:

<filter>
   <filter-name>struts2</filter-name>
   <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
   <filter-name>struts2</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Puedes descargar el archivo web.xml, pero trata de modifcarlo directamente en tu proyecto.

Otro archivo que será necesario crear es struts.xml, este archivo es uno de los mas importantes para el marco de trabajo de Struts 2. Lo debes crear en el paquete default del proyecto.

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name="struts.enable.DynamicMethodInvocation" value="false" />
   <constant name="struts.devMode" value="false" />

   <package name="default" namespace="/" extends="struts-default">

   //Declaracion de Acciones

   </package>
</struts>

Como podras ver le aún le faltan algunas cosas al archivo, pero lo completaremos a continuación.

1.1.- Requisitos
1.2.- Crear el proyecto en NetBeans
1.3.- Configurar el proyecto para usar Struts 2
1.4.- La vista de nuestro proyecto
1.5.- La capa de negocios
1.6.- Ejecutar el proyecto