domingo, 27 de diciembre de 2009

La importancia de ActionSupport en Java con Struts 2

Hasta ahora siempre he utilizado una clase que heredaba de ActionSupport para tratar la action que lanzabamos desde la JSP - mas que nada porque así me habían enseñado en las clases prácticas - pero ha sido hoy cuando he entendido el verdadero significado de hacer esto, y sobretodo, lo importante que resulta.

Tenemos una pagina index.jsp con dos formularios de Struts 2 para recoger el login y el password del usuario.
Cuando hacemos click sobre el boton Acceder, se lanza la action correspondiente, es decir, aquella que le indiquemos a traves del TAG de Struts ACTION:

<html>

<body>

<h3>Acceso al perfil de jugador</h3>

<p>Introduzca su usuario y contraseña:</p>

<s:form action="Login">

<s:textfield key="login" label="Login de jugador: " />

<s:password key="password" label="Contraseña: " />

<s:submit value="Acceder"/>

</s:form>

</body>

</html>

en este caso, la ACTION se llama LOGIN.

En nuestra aplicación deberemos tener un fichero struts.xml en nuestra carpeta de codigo fuente que contendra un mapeo de las acciones. Esto quiere decir que cuando el ACTION del codigo de la JSP sea LOGIN, se ha de proceder de la manera X.

En el ejemplo que seguimos, en nuestro struts.xml deberiamos tener:

<action name="Login" class="com.dasdi.presentation.login.LoginAction">

<result name="success" >/panelControl.jsp</result>

</action>

que traducido así de forma mas "llana" viene a ser que cuando el action sea LOGIN ejecutes el codigo de la clase LOGINACTION. Si el resultado del método execute es SUCCESS, muestra la página panelControl.jsp.

¿Y qué hace la clase LoginAction?, ¿Y cual es el metodo execute? ¿Y si no devuelve SUCCESS que hara?

Pues bien, toda navegacion de una pagina a otra en nuestra aplicacion debera tener asociado una clase java que se ejecute con los action; salvo aquellos casos básicos, por ejemplo cuando damos de alta un usuario, solo necesitamos que se muestre un formulario, por lo que no hara falta una clase action relacionada con el proceso.
Pero en el ejemplo que estamos tratando, el loguearse obliga a ejecutar un codigo, es decir, buscar en la base de datos el nombre de usuario y contraseña introducidos y ver que coinciden. Estas comprobaciones se hacen a traves de las capas de negocio y persistencia, con sus respectivos facades, por lo tanto deberemos relacionar nuestras JSP con las diferentes capas de la aplicacion.

LoginAction recogera de los campos de la JSP el login y la contraseña y se los pasara a la capa de negocio a traves de su facade. Esta fachada debera devolver una confirmacion de que el logueo es correcto o no.
En codigo seria:

public class LoginAction extends ActionSupport implements SessionAware{



private String login;

private String password;

private Jugador perfil;

private Map<String, Object> session;



public String execute() throws Exception {

JugadoresService service;

try {

service = Factories.services.createJugadoresService();

this.perfil = service.verifyLogin(login, password);

this.session.put("perfil", perfil);

return SUCCESS;



} catch( Exception e ) {

e.printStackTrace();



return LOGIN;

}

/*añadir metodos get y set para cada atributo*/

}

  1. El service sera una referencia a la fachada de la capa de negocio.
  2. A traves de esta referencia pediremos la confirmacion de un logueo correcto.
  3. Si no es correcto recibira una excepcion, por lo que se devolvera ERROR
  4. Si todo fue bien, colocamos el nuevo usuario (o jugador, o perfil) en la sesion de la aplicacion.

¿Por qué todo esto es importante?

Pues bien, si intentaramos volver atras desde cualquier pagina JSP de nuestra aplicación a otra JSP sin lanzar la ejecución de un clase ACTION, no habría forma de relacionarse con el resto de capas, y por lo tanto con los datos, tanto de la sesion como de la persistencia (base de datos).

Un ejemplo es el panel de control.

Esto es lo que muestra panelControl.jsp, donde se indica el nombre del usuario de la sesion, en este caso ADMINISTRADOR.

¿Cómo se obtuvo este dato? - Pues utilizando PanelControlAction, el cual recoge de la sesión el Jugador, llamandolo "perfil" y lo asigna como uno de sus atributos. De esta forma, cuando panelControl.jsp devuelve el código HTML, la etiqueta de "Perfil:" mostrara el nombre del jugador que inicio la sesión.

Esto en código sería:

  • panelControl.jsp

<h3>Perfil: <s:label value="%{perfil.nombre}"/></h3>


  • PanelControlAction.java

public class PanelControlAction extends ActionSupport implements SessionAware{



private Map<String, Object> session;

private Jugador perfil;



public String execute()throws Exception{

try{

this.perfil = (Jugador)session.get("perfil");



return SUCCESS;

}

catch(Exception e){

e.printStackTrace();

return ERROR;

}

}

/*mas get y set de los atributos*/

}


  • struts.xml

<action name="Login" class="com.dasdi.presentation.login.LoginAction">

<result name="success" type="chain">PanelControl</result>

</action>



<action name="PanelControl" class="com.dasdi.presentation.PanelControlAction">

<result name="success">/panelControl.jsp</result>

</action>



Sin utilizar el PanelControlAction.java, es decir, redirigiendo directamente a panelControl.jsp, no podríamos mostrar siempre el nombre del perfil, ya que nunca se obtendría de la sesion.

He aquí la importancia de añadir estos detalles.

1 comentario:

  1. Hola goladed te hago una pregunta, de que libreria sale @Actions({
    @Action(
    value="/jsonsample",
    results={
    @Result(name="success",type="json")
    })
    })
    estoy haciendo un ejemplo de combos anidados, y no encuento la solucion para eso. espero me pudas dar una ayuda gracias.

    ResponderEliminar