Está en la página 1de 29

STRUTS:Implementacin del patrn MVC en aplicaciones Web

STRUTS Implementacin del patrn MVC en aplicaciones Web


(Actualizaciones y ejemplos en http://ciberia.ya.com/pxai/ma.html)

http://www.javahispano.com

INDICE
1. INTRODUCCIN..................................................................................................... 3 2. MVC: Model View Controller................................................................................... 4 3. STRUTS..................................................................................................................... 7
ESTUCTURA .......................................................................................................................... 8 UN EJEMPLO SENCILLO DE STRUTS .......................................................................... 12 UN EJEMPLO DE STRUTS MS COMPLEJO............................................................... 15 Errores comunes con Struts.................................................................................................. 29

STRUTS:Implementacin del patrn MVC en aplicaciones Web

1.

INTRODUCCIN

Este documento describe el patrn de diseo MVC (Model View Controller). Como ejemplo de implementacin se utiliza el framework Struts, que facilita el desarrollo de aplicaciones web en Java basadas en MVC. En al mbito del desarrollo web se siguen unas pautas que tratan ms o menos de conseguir un desarrollo estructurado de las aplicaciones, donde la verificacin de sesin se centraliza y cada caso de uso se distingue claramente. Utilizando Struts ese ms o menos se convierte en una arquitectura completamente estructurada que divide perfectamente lgica de negocio (Model), presentacin (View) y control de flujo de aplicaciones(Controller). En muchos desarrollos web se disea consciente o inconscientemente siguiendo este patrn, por tanto la adopcin del modelo Struts no debiera suponer un quebradero de cabeza. Adems hay que tener en cuenta que Struts nos da parte del trabajo hecho, funciona correctamente, y nos da ciertos extras. Teniendo en cuenta adems las aportaciones de grupos de desarrollo (taglibs nuevos, etc..), la adopcin de esta plataforma puede resultar muy interesante.

http://www.javahispano.com

2.

MVC: MODEL VIEW CONTROLLER

MVC o Model view Controller es un patrn de diseo aportado originariamente por el lenguaje SmallTalk a la Ingeniera del Software. El paradigma MVC consiste en dividir las aplicaciones en tres partes: Controlador Modelo Vistas.

El controlador es el encargado de redirigir o asignar una aplicacin (un modelo) a cada peticin; el controlador debe poseer de algn modo, un "mapa" de correspondencias entre peticiones y respuestas (aplicaciones o modelo) que se les asignan. El modelo seria la aplicacin que responde a una peticin, es la lgica de negocio a fin de cuentas. Una vez realizadas las operaciones necesarias el flujo vuelve al controlador y este devuelve los resultados a una vista asignada. Vemos las diferencias que supone el modelo con los modelos convencionales.

Yndonos al esquema ms bsico de programa, tenemos una entrada o parmetros que llegan(INPUT), se procesan y se muestra el resultado (OUTPUT).

STRUTS:Implementacin del patrn MVC en aplicaciones Web

En el caso del patrn MVC el procesamiento se lleva a cabo entre sus tres componentes. El controller recibe una orden y decide quien la lleva a cabo en el modelo. Una vez que el modelo (la lgica de negocio) termina sus operaciones devuelve el flujo vuelve al controller y este enva el resultado a la capa de presentacin.

http://www.javahispano.com

El Controller en cierta forma debe tener un registro de la relacin entre ordenes que le pueden llegar y la lgica de negocio que le corresponde (Es como una operadora de telfono que recibe una peticin y une dos lineas). En el siguiente grfico se representa ese funcionamiento:

Que ventajas obtenemos de este modelo? Obviamente una separacin total entre lgica de negocio y presentacin. A esto se le pueden aplicar opciones como el multilenguaje, distintos diseos de presentacin,.. etc sin alterar la lgica de negocio. La separacin de capas como presentacin, lgica de negocio, acceso a datos es fundamental para el desarrollo de arquitecturas consistentes, reutilizables y ms facilmente mantenibles, lo que al final resulta en un ahorro de tiempo en desarrollo en posteriores proyectos. En el lenguaje Java disponemos de una clases muy sencillas para implantar el modelo MVC: la clase Observer, Observable del paquete util. Aunque esa implementacin del MVC con esas clases se podra hacer a un nivel muy simple de interaccin entre unas pocas clases. En este caso, mediante Struts se aplica el MVC en toda una aplicacin Web convencional.

STRUTS:Implementacin del patrn MVC en aplicaciones Web

3.

STRUTS

Struts Framework (http://jakarta.apache.org/struts) Struts es un framework para aplicaciones web java que implementa el modelo MVC. Realmente lo que provee es un conjunto de clases y TAG-LIBS que conforman el Controlador, la integracin con el Modelo (o lgica de negocio) y facilitan la construccin de vistas. Naturalmente, el Modelo o lgica de negocio es la parte que nos corresponde desarrollar. Por eso Struts es una plataforma sobre la que montamos la lgica de negocio, y esta plataforma nos permite dividir la lgica de la presentacin entre otras cosas.

http://www.javahispano.com

ESTUCTURA Supongamos que tenemos una aplicacin Web que consiste en un formulario que recoge datos y los manda al servidor para su proceso. Este ejemplo tan simple necesitara implementar unos 6 ficheros (2 de ellos jsps). Suena mal eh? Es el precio que hay que pagar por una aplicacin bien estructurada. Utilizando Struts nunca se llega a una pagina de la capa de presentacin directamente. Esto es, en la url nunca se llega a una pagina jsp o html a traves de su nombre. De eso se trata el MVC, la presentacin esta separada en otra capa. En este entorno, se debe invocar una accin o aplicacin que debe estar mapeada en Struts: una accin se corresponder con una clase Java (heredera de la clase Action de Struts). El mapeo de acciones y clases se especifica en un fichero de importancia vital: strutsconfig.xml. Ah se especifican todas las relaciones entre acciones y clases, formularios y clases, acciones y jsps de presentacin, que globalmente conforman el mapa de la aplicacin. Si quisieramos crear la aplicacin Struts ms simple posible, por ejemplo una pgina con un saludo, debiramos hacer lo siguiente: 1. -Una pgina JSP (la presentacin) 2. -Una clase Action (componente del controlador) 3. -La clase Action debe definirse en el struts-config.xml correctamente Veamos los diagramas correspondientes a ese caso: Diagrama de clases En el caso ms simple este sera el conjunto de clases utilizadas y sus relaciones.

Como se puede ver, no tendramos ms que dos ficheros, una clase que hereda de struts.Action y una JSP con la presentacin. La clase Action se configura en el strtus-config.xml y se convierte en parte del controlador. Cuando la aplicacin recibe una peticin, Struts decidir que debe cargar esa clase y travs de ella cargar la JSP. As se puede ver en el siguente diagrama:

Diagrama de colaboracin Esta sera la manera de interactuar entre la clases y Struts

STRUTS:Implementacin del patrn MVC en aplicaciones Web

Una peticin llega a struts (una URL); este mira en su mapa (el fichero struts-config.xml), y deduce que tiene que cargar la ClaseAction. Esta clase esta configurada para que cargue una pagina JSP. Como se puede observar,no se carga la JSP directamente, hay que pasar por el controlado Diagrama de secuencia. Estos seran los pasos seguidos por la aplicacin en el plano temporal. Obviamente, este no es el ejemplo ms clsico de una accin de Struts. Por lo general, en cualquier aplicacin web siempre se sigue un mismo esquema: 1. se muestra un formulario 2. se rellena 3. se validase 4. se manda a una pgina que realiza la lgica de negocio 5. se muestra el resultado. Todo esto se podra hacer con dos JSPs o dos ASPs, o dos CFM, o dos PHP o con un CGI, etc En Struts necesitaramos lo siguiente: 1. -Una clase Action (su nombre podra empezar por Edit) encargada de cargar el formulario. 2. -Un Bean tipo Form cuyos campos u atributos de instancia coinciden con los campos del formulario. (al ser tipo JavaBean tendr los correspondientes mtodos set y get para los atributos) . Este form y sus atributos son un requisito imprescindible. 3. -Una JSP que contiene el formulario citado. Los campos deben coincidir con los definidos en el Bean de formulario 4. -Una clase Action (su nombre podra empezar por Save) encargada de pasar la instancia del formulario al Bean de Logica de Negocio, esperar su resultado y redirigir el flujo a una JSP de error o de xito. 5. -Un Bean de lgica de negocio (El que hace algo con los datos del formulario) 6. -Una JSP para mostrar un mensaje en caso de xito (o puede ser la misma del principio) 7. -Una JSP para mostrar los errores en caso de error (o puede usarse una genrica). Struts permite cierta flexibilidad en cuanto a nombres, pero conviene especificar cual es Action, cual es Form, cual es Bean de negocio, etc.. as como meterlos en subpaquetes con ese nombre. Veamos como quedan esos siete elementos en diagramas

http://www.javahispano.com

Diagrama de clases Este sera el conjunto de clases utilizadas y sus relaciones.

La clase edit tambin podra usar el formulario, pero en principio no tiene porqu. Sera interesante ver como interactan las clases entre ellas, y eso se ve en el siguiente grfico. Diagrama de colaboracin Esta sera la manera de interactuar entre las clases y Struts

10

STRUTS:Implementacin del patrn MVC en aplicaciones Web

Diagrama de secuencia. Estos seran los pasos seguidos por la aplicacin en el plano temporal.

11

http://www.javahispano.com

UN EJEMPLO SENCILLO DE STRUTS Bien, veamos ahora el ejemplo mtico de HelloWorld por el que se suele empezar cuando no se tiene ni idea de algo. Vamos a crear una aplicacin que muestra una pgina con el saludo Kaixo! que significa hola en euskera. Es fcil de narices. Entrada de aplicacin: ninguna Salida: Una pgina que muestra el texto Kaixo! Diagrama de clases

/** * EditKaixoAction.java * Pello Xabier Altadill Izura */ package pxai.struts.kaixo.action; import import import import import import import import import import import import import import import import import import import java.io.IOException; java.lang.reflect.InvocationTargetException; java.util.Locale; java.util.Vector; javax.servlet.RequestDispatcher; javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpSession; javax.servlet.http.HttpServletResponse; org.apache.struts.action.Action; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionError; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping; org.apache.struts.action.ActionServlet; org.apache.struts.util.MessageResources; org.apache.struts.util.PropertyUtils; com.jazztel.numeracionip.comun.Log;

Clase EditKaixoAction

/** * EditKaixoAction.java * Maneja las peticiones enviadas por el browser * en el url se pondra: /kaixo.do y struts cargara esta clase * que redirigira el flujo a una jsp: Kaixo.jsp * * @author Pello Xabier Altadill Izura * @version 1.0 ,date 13/2/02 */ public final class EditKaixoAction extends Action {

/** * Procesa la peticion HTTP (request) especificada y genera su correspondiente

12

STRUTS:Implementacin del patrn MVC en aplicaciones Web


* respuesta HTTP (response) (o lo redirige a otro componente web que podria * Devuelve una instancia code>ActionForward</code> que describe a DONDE y COMO * se redirige el control, o sino, si la respuesta se ha completado se devolveria * <code>null</code> * * @param mapping El mapeo utilizado para seleccionar esta instancia * @param request El request que estamos procesando * @param actionForm La instancia ActionForm que estamos utilizando (si la hay) * @param response La respuesta HTTP que creamos. * * @exception IOException en caso de error de entrada/salida (i/o) * @exception ServletException en caso de error de servlet */ public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Extrae los atributos que se necesitan Locale locale = getLocale(request); MessageResources messages = getResources(); HttpSession session = request.getSession(); String action = request.getParameter("action"); ActionErrors errors = null; try { if (action == null) action = "Create"; if (servlet.getDebug() >= 1) servlet.log("EditKaixoAction: Procesando action " + action); /***** Logica segun el parametro action (no imprescindible)**************/ /************************************ fin de logica *********************/ // Redirige el control en caso de exito a la pagina espcificada en struts-config.xml if (servlet.getDebug() >= 1) servlet.log(" Redirigiendo a pagina 'success'"); return (mapping.findForward("success")); } catch (Exception e) { e.printStackTrace(System.out);//Escribe en el fichero de log del servidor de aplicaciones errors = new ActionErrors(); errors.add("action",new ActionError("action.perform.carga.error"));//Se incluye un mensaje de error que se encuentra en el fichero especificado especificado en las propiedades de Struts saveErrors(request,errors); return (mapping.findForward("failure")); } } }

crear).

El fichero JSP Kaixo.jsp


<%@ <%@ <%@ <%@ <%@

page language="java" %> taglib uri="/WEB-INF/app.tld" prefix="app" %> taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html:html> <head> <title>STRUTS :: ejemplo</title> </head> <body> <H1> <% out.println("Kaixo!!"); %> </H1>

13

http://www.javahispano.com

</body> </html:html>

Configuracion del fichero struts-config.xml para este sencillo caso. Se debiera aadir, dentro de action mappings:

<action-mappings> <!-- Edit Kaixo--> <!-- path: el nombre que debe especificarse en la url para acceder --> <!-- type: la clase asociada a la accion, con la ruta del paquete si la tuviere --> <!-- name: nombre del formulario asociado con esta accion Normalmente No requerido para una carga de pagina o accion Edit--> <!-- scope: ambito de validez de ese formulario (request o peticion): puede ser session--> <!-- validate: si se va a validar el formulario o no.--> <action path="/kaixo" type="pxai.struts.kaixo.action.EditKaixoAction" name="" scope="request" validate="false"> <forward name="success" path="/Kaixo.jsp"/> </action>

(Nota: debe reiniciarse el servidor de aplicaciones si se cambia este fichero) El resultado:

14

STRUTS:Implementacin del patrn MVC en aplicaciones Web UN EJEMPLO DE STRUTS MS COMPLEJO En fin, el ejemplo anterior era el tpico toy-code que nicamente es valido como iniciacin al Struts. Ahora veremos un ejemplo ms acorde con la funcionalidad esperada de una aplicacin web cualquiera. Se trata de una aplicacin de alta de usuario, un tipo de aplicacin muy comn y que presente en muchos sistemas. Veremos como implementar esto con struts. En cualquier otro entorno bastara con crear un formulario y una pgina que realiza el alta y da el mensaje correspondiente; pero aqu no ser tan simple. Entrada de aplicacin: Un formulario de datos: username, password,edad,fechanacimiento y profesion Salida: Una pgina que muestra si se ha dado de alta correctamente Diagrama de clases Aqu se puede contemplar las clases que sern necesarias para este ejemplo

15

http://www.javahispano.com Diagrama de colaboracin Esta sera la manera de interactuar entre las clases action, form, bean, jsp y Struts .

Diagrama de secuencia Aqu podemos ver como interactan las clases en el tiempo.

16

STRUTS:Implementacin del patrn MVC en aplicaciones Web

El cdigo
EditAltaAction
/** * EditAltaAction.java * Pello Xabier Altadill Izura */ package pxai.struts.alta.action; import import import import import import import import import import import import import import import import import import import import java.io.IOException; java.lang.reflect.InvocationTargetException; java.util.Locale; java.util.Vector; javax.servlet.RequestDispatcher; javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpSession; javax.servlet.http.HttpServletResponse; org.apache.struts.action.Action; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionError; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping; org.apache.struts.action.ActionServlet; org.apache.struts.util.MessageResources; org.apache.struts.util.PropertyUtils; com.jazztel.numeracionip.comun.Log; com.jazztel.numeracionip.bean.MigracionNumeracionBean;

/** * EditAltaAction.java * Maneja las peticiones enviadas por el browser * @author Pello Xabier Altadill Izura * @version 1.0 ,date 13/2/02 */ public final class EditAltaAction extends Action {

crear).

/** * Procesa la peticion HTTP (request) especificada y genera su correspondiente * respuesta HTTP (response) (o lo redirige a otro componente web que podria * Devuelve una instancia code>ActionForward</code> que describe a DONDE y COMO * se redirige el control, o sino, si la respuesta se ha completado se devolveria * <code>null</code> * * @param mapping El mapeo utilizado para seleccionar esta instancia * @param request El request que estamos procesando * @param actionForm La instancia ActionForm que estamos utilizando (si la hay) * @param response La respuesta HTTP que creamos. * * @exception IOException en caso de error de entrada/salida (i/o) * @exception ServletException en caso de error de servlet */ public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Extrae los atributos que se necesitan Locale locale = getLocale(request); MessageResources messages = getResources(); HttpSession session = request.getSession(); String action = request.getParameter("action"); ActionErrors errors = null; try { if (action == null) action = "Create"; if (servlet.getDebug() >= 1) servlet.log("EditAltaAction: Procesando action " + action);

17

http://www.javahispano.com
/************************************ *******************************************/ // En este caso unicamente cargamos la JSP /************************************ *******************************************/ // Redirige el control en caso de exito a la pagina espcificada en struts-config.xml if (servlet.getDebug() >= 1) servlet.log(" Redirigiendo a pagina 'success'"); return (mapping.findForward("success")); } catch (Exception e) { e.printStackTrace(System.out);//Escribe en el fichero de log del servidor de aplicaciones // Creamos un error y lo salvamos para mostrarlo por pantalla errors = new ActionErrors(); errors.add("alta",new ActionError("alta.edit.error")); saveErrors(request,errors); return (mapping.findForward("failure")); } } }

alta.jsp
<%@ <%@ <%@ <%@ <%@

page language="java" %> taglib uri="/WEB-INF/app.tld" prefix="app" %> taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html:html> <head> <title>STRUTS :: ejemplo de ALTA</title> </head> <body> <html:form action="/saveAlta.do" > <b>ALTA de USUARIO</b><hr> Usuario:<html:text property="username" size="8" maxlength="8" /><br> Password:<html:text property="password" size="8" maxlength="8" /><br> Edad:<html:text property="edad" size="3" maxlength="3"/><br> Fecha Nacimiento(dd/mm/aaaa):<html:text property="fechanacimiento" size="10" maxlength="10"/><br> Profesion:<html:select property="profesion"> <html:option value="-1">Selecciona ...</html:option> <html:option value="Parado">Parado</html:option> <html:option value="Estudiante">Estudiante</html:option> <html:option value="Profesional liberal">Profesional liberal</html:option> <html:option value="Empresario">Empresario</html:option> <html:option value="Currela">Currela</html:option> </html:select><br> <html:submit property="alta"/> </html:form> </body> </html:html>

AltaForm

/** * AltaForm.java * Pello Xabier Altadill Izura */ package pxai.struts.alta.form; import import import import import javax.servlet.http.HttpServletRequest; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionMapping;

18

STRUTS:Implementacin del patrn MVC en aplicaciones Web


import com.jazztel.numeracionip.comun.IP; import com.jazztel.numeracionip.comun.Log; import java.sql.Date; /** * AltaForm * * Implementa el formulario de ALTA que se muestra en html * @author Pello Xabier Altadill Izura * @version 1.0 * date 13/2/02 */ public final class AltaForm extends ActionForm { /** * @field Mantenimiento de la accion que estamos procesando (Create or Edit). * atributo IMPRESCINDIBLE para STRUS */ private String action = "Create"; private private private private private String username = null; String password = null; Integer edad = null; String fechanacimiento = null; String profesion = null;

/** * Devuelve la accion. * * @return String la accion */ public String getAction() { } return (this.action);

/** * Establece la accion * * @param action La nueva accion */ public void setAction(String action) { } this.action = action;

/** * getUsername * Devuelve nombre de usuario * @return String */ public String getUsername() { return (this.username); } /** * setUsername * Establece el nombre de usuario * @param String */ public void setUsername(String username) { this.username = username; } /** * getPassword * Devuelve el password * @return String */ public String getPassword() { return (this.password); } /** * setPassword * Establece el password

19

http://www.javahispano.com
* @param String */ public void setPassword(String password) { System.out.println("Aqui estamos: " +password); this.password = password; }

/** * getEdad * Devuelve edad * @return Integer */ public Integer getEdad() { return (this.edad); } /** * setEdad * Establece la edad * @param Integer */ public void setEdad(Integer edad) { this.edad = edad; } /** * getFechanacimiento * Devuelve la fecha de nacimiento dd/mm/aaaa * @return String */ public String getFechanacimiento() { return (this.fechanacimiento); } /** * setFechanacimiento * Establece la fechanacimiento * @param String */ public void setFechanacimiento(String fechanacimiento) { this.fechanacimiento = fechanacimiento; }

/** * getProfesion * Devuelve la profesion * @return String */ public String getProfesion() { return (this.profesion); } /** * setProfesion * Establece la profesion * @param String */ public void setProfesion(String profesion) { this.profesion = profesion; }

/** * Resetea todas las propiedades a sus valores por defecto. * * @param mapping El mapping utilizado por la instancia. * @param request El servlet request que estamos procesando. */ public void reset(ActionMapping mapping, HttpServletRequest request) { this.action = "Create";

20

STRUTS:Implementacin del patrn MVC en aplicaciones Web


} /** * Valida las propiedades asignadas desde el HTTP request * y devuelve un objeto <code>ActionErrors</code> que encapsula cualquier * validacin de error que haya sido encontrada. Si no se han encontrado errores * , devuelve <code>null</code> o un objeto <code>ActionErrors</code> sin mensajes * de error grabados. * * @param mapping El mapping utilizado por la instancia. * @param request El servlet request que estamos procesando. */ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (getUsername().trim().compareTo("") == 0 || getUsername() == null) { // El nombre de usuario es nulo, se devuelve mensaje de error errors.add("alta",new ActionError("alta.username.nulo")); } if (getPassword().trim().compareTo("") == 0 || getPassword() == null) { // El password es nulo, se devuelve mensaje de error errors.add("alta",new ActionError("alta.password.nulo")); } return errors; } }//class

SaveAltaAction

/** * SaveAltaAction.java * Pello Xabier Altadill Izura */ package pxai.struts.alta.action; import import import import import import import import import import import import import import import import import java.io.IOException; java.util.Locale; javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpSession; javax.servlet.http.HttpServletResponse; org.apache.struts.action.Action; org.apache.struts.action.ActionError; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping; org.apache.struts.action.ActionServlet; org.apache.struts.util.MessageResources; pxai.struts.alta.bean.AltaBean; com.jazztel.numeracionip.comun.Log; com.jazztel.numeracionip.comun.Data;

/** * Invoca al bean de lgica de negocio para procesar la migracion * en caso de encontrar datos validos devuelve un objeto data en * la sesin. * @author Pello Xabier Altadill Izura * @version 1.0 , date 13/2/02 */ public final class SaveAltaAction extends Action { /** * Procesa la peticion HTTP (request) especificada y genera su correspondiente * respuesta HTTP (response) (o lo redirige a otro componente web que podria * * * * * * Devuelve una instancia code>ActionForward</code> que describe a DONDE y COMO se redirige el control, o sino, si la respuesta se ha completado se devolveria <code>null</code> @param mapping El mapeo utilizado para seleccionar esta instancia @param request El request que estamos procesando

crear).

21

http://www.javahispano.com
* @param actionForm La instancia ActionForm que estamos utilizando (si la hay) * @param response La respuesta HTTP que creamos. * * @exception IOException en caso de error de entrada/salida (i/o) * @exception ServletException en caso de error de servlet */ public ActionForward perform(ActionMapping mapping, ActionForm theForm, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Extract attributes and parameters we will need Locale locale = getLocale(request); MessageResources messages = getResources(); HttpSession session = request.getSession(); String action = request.getParameter("action"); if (action == null) action = "Create"; ActionErrors errors = null; { /********************** LOGICA DE NEGOCIO *****************************/ //Instancia el bean de lgica de negocio AltaBean theAltaBean = new AltaBean(); //Invoca al proceso de carga y recoge el valor de vuelta errors = theAltaBean.alta(theForm); /********************** FIN de LOGICA DE NEGOCIO **********************/ if (errors==null ) //Se ejecut correctamente return (mapping.findForward("success")); else { //Hubo errores saveErrors(request,errors); return (mapping.findForward("failure")); } }catch (Exception e) { e.printStackTrace(System.out);//Escribe en el fichero de log del servidor de aplicaciones errors = new ActionErrors(); errors.add("action",new ActionError("alta.save.error")); saveErrors(request,errors); return (mapping.findForward("failure")); } } } try

AltaBean

/** * AltaBean.java * Pello Xabier Altadill Izura */ package pxai.struts.alta.bean; import import import import import import import import import import import import import javax.servlet.http.HttpServletRequest; javax.servlet.ServletException; com.jazztel.numeracionip.comun.Log; com.jazztel.numeracionip.comun.Propiedades; com.jazztel.numeracionip.comun.DataService; com.jazztel.numeracionip.comun.Data; org.apache.struts.action.ActionForm; org.apache.struts.action.ActionErrors; org.apache.struts.action.ActionError; java.sql.Connection; java.sql.DriverManager; java.sql.SQLException; java.sql.Statement;

22

STRUTS:Implementacin del patrn MVC en aplicaciones Web


import pxai.struts.alta.form.AltaForm;

/** * Implementa la lgica de negocio para el proceso Alta * @author Pello Xabier Altadill Izura, AXPE * @version 1.0 * date 23/1/02 */ public class AltaBean { /** * @field Constante que identifica el estado libre en la tabla de estados */ private static final Integer _ESTADO = new Integer(1);

/** * alta * * Da el alta de un usuario * @param formulario con los datos a guardar * * @return null si no hay errores o ActionErrors con los * errores capturados en caso de error. */ public synchronized ActionErrors alta (ActionForm theActionForm) { //Instancia un objrcto ActionErrors para recoger los errores ActionErrors theActionErrors = null; Connection conn = null; Statement stmn = null; try { // Casting de ActionForm a nuestro FORM concreto AltaForm form = (AltaForm)theActionForm; // AQUI SER REALIZA UNA CONEXION A UNA ORIGEN DE DATOS ODBC, // PARA INSERTAR EL NUEVO USUARIO. NO RESULTA UNA FORMA MUY // DE HACERLO, MENOS AUN EN SERVIDORES DE APLICACIONES Y EN // BIEN ESTRUCTURADAS, PERO PARA SIMPLIFICAR EL EJEMPLO SE HA =

CORRECTA APLICACIONES HECHO ASI.

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conn DriverManager.getConnection("jdbc:odbc:usuarios","db_user","db_password");

// CREAMOS la SENTENCIA stmn = conn.createStatement(); // Siii, ya se que es una forma poco elegante de alterar // la BBDD, pero se trata de simplificar el ejemplo. stmn.executeUpdate("INSERT INTO USUARIOS VALUES ('"+form.getUsername()+"','"+form.getPassword()+"',"+form.getEdad()+",'"+form.getFechana cimiento()+"','"+form.getProfesion()+"')"); // Cerramos sentencia y conexion stmn.close(); conn.close(); error) // Si llegamos aqui: Devolvemos objeto ActionErrors (nulo == sin return theActionErrors;

} catch(Exception e){ e.printStackTrace(System.out);//Escribe en el fichero de log del servidor de aplicaciones theActionErrors = new ActionErrors(); theActionErrors.add("alta",new ActionError("alta.bean.error")); return theActionErrors; } } //Logica de Negocio

// Fin class

23

http://www.javahispano.com

confirmacionalta.jsp
<%@ <%@ <%@ <%@ <%@

page language="java" %> taglib uri="/WEB-INF/app.tld" prefix="app" %> taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html:html> <head> <title>STRUTS :: ejemplo de ALTA :: Confirmacion ALTA</title> </head> <body> <!-- mensaje de confirmacin recuperando el nombre de usuario --> <h3>Alta de usuario <bean:write name="altaForm" property="username"/> correcta</h3> </body> </html:html>

errorAlta.jsp

<%@ page language="java" %> <%@ taglib uri="/WEB-INF/app.tld" prefix="app" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <html:html> <head> <title>Error en el proceso de alta de usuario</title> </head> <body> <table cellspacing="8" cellpadding="8" border="0" align="center"> <tr> <td colspan ="3"> <H3><b>Se ha producido un error en la operacion.</b></H3> </td> </tr> <td align="center"> <input type="button" name="volver" value="Volver" onclick="javascript:history.back()"> </td> </tr> </table> </body> <!-- Esta etiqueta de struts devuelve TODOS los mensajes de error guardados en ActionErrors con el nombre "alta" a lo largo del request --> <h3><center><html:errors property="alta" /><center><h3> </html:html>

24

STRUTS:Implementacin del patrn MVC en aplicaciones Web Configuracion del fichero struts-config.xml para este sencillo caso. Se debiera aadir, dentro de action mappings:
<!--Alta form Formulario definido en la zona de formularios--> <form-bean name="altaForm" type="pxai.struts.alta.form.AltaForm"/> <!-- Edit/Save alta--> <!-- path: el nombre que debe especificarse en la url para acceder --> <!-- type: la clase asociada a la accion, con la ruta del paquete si la tuviere --> <!-- name: nombre del formulario asociado con esta accion Normalmente No requerido para una carga de pagina o accion Edit--> <!-- scope: ambito de validez de ese formulario (request o peticion): puede ser session-> <!-- input: origen de los datos. No imprescindible --> <!-- validate: si se va a validar el formulario o no.--> <action path="/editAlta" type="pxai.struts.alta.action.EditAltaAction" name="" scope="request" validate="false"> <forward name="success" path="/alta.jsp"/> </action> <action path="/saveAlta" type="pxai.struts.alta.action.SaveAltaAction" name="altaForm" scope="request" input="/alta.jsp" validate="true"> <forward name="success" path="/confirmacionalta.jsp"/> <forward name="failure" path="/erroralta.jsp"/> </action>

Este sera el formulario de alta, al que accedemos a travs de la url editAlta.do, tal como se especifica en struts-config.xml. Al invocar editAlta.do, segn el mapa de acciones de Struts, se invoca la clase EditAltaAction y esta a su vez carga la JSP alta.jsp.

25

http://www.javahispano.com El formulario se enva a la url saveAlta.do, que segn el mapa de acciones de struts especificado en strtus-config.xml, provoca la carga de SaveAltaAcion; esta instancia invoca la lgica de negocio (AltaBean) y devuelve un resultado (un objeto ActionErrors que puede estar cargado o ser nulo). Si el bean de lgica de negocio devuelve un valor nulo en el ActionErrors, todo ha ido correctamente y se mostrar la siguiente pgina.

En caso contrario, segn el struts-config.xml se redirigira el flujo a la pgina de error erroralta.jsp, que sencillamente mostrara un mensaje de error al usuario.

26

STRUTS:Implementacin del patrn MVC en aplicaciones Web

TIPS
A continuacin se explican una serie de soluciones para ciertas necesidades frecuentes en la programacin Web; bsicamente se trata de modos de comunicar las clases de la capa de negocio con los JSP. Entre la logica de negocio y un JSP de presentacin media una clase de la capa Controller. Lo que las une a las tres es el la instancia actual de javax.servlet.http.HttpServletRequest; En ese request se pueden cargar resultados que podemos presentar mas tarde en JSP. Struts lo hace implicitamente con el las instancias de lal clases Formulario. -Mostrar valores de los Bean por pantalla: Dentro de un objeto action, debemos guardar el Bean en la sesion: .. // En un bean de negocio se puede cargar un objeto en el request // para poder recuperarlo en el JSP con etiquetas STRUTS // Tambin se podra hacer en el objeto action (editXAction, saveXAction, // etc...), aunque no quedara muy limpio. // Creamos el objeto Red, le asignamos valores, y lo aadimos a las // propiedades del request, para poder recuperarlo en la JSP. Red red2 = new Red(); red2.setNombre("SuperRed"); red2.setCodigo(747); red2.setTipo("Red IP de telefonica"); red2.setIp("166.166.166.100"); request.setAttribute("red2",red2); ... // en el JSP <bean:write name="red2" property="nombre" scope="request"/> //eso sacaria por pantalla: SuperRed -Mostrar valores en Iteracion. Es parecido a mostrar un bean por pantalla, salvo que hay que definir un bean de tipo Vector, Lista, etc... // Supongamos que definimos un objeto llamado Redes public class Redes extends Vector {...} .. // Al igual que antes, en un Bean de negocio cargamos un objeto // en el request para poder recuperarlo mas tarde. // Creamos el objeto Redes, le asignamos valores, y lo aadimos a las // propiedades del request, para poder recuperarlo en la JSP. Redes redes = new Redes(); redes.addElement("www.el-mundo.es"); redes.addElement("www.elpais.es"); redes.addElement("www.cisco.com"); redes.addElement("www.a3n.tv"); request.setAttribute("misredes",redes); ... // en el JSP utilizamos el tag logic:iterate

27

http://www.javahispano.com

// donde: //lista: bean en el que se guarda cada elemento de iteracion //type: el tipo Java de ese elemento //name: nombre del atributo que contiene los valores // que debe coincidir con el que usamos en "setAttribute" <logic:iterate id="lista" name="misredes" type="java.lang.String"> <bean:write name="lista" /><br> </logic:iterate> // Lo cual mostrara por pantalla: www.cisco.com www.el-mundo.es www.elpais.es www.jazztel.com www.a3n.tv Nota: a traves de los tag logic se pueden realizar comapraciones de valores y se puede condicionar los valores a mostrar. Para conocer estos y otros tags mirar documentacion sobre tags. (http://jakarta.apache.org/struts/userGuide/index.html) (http://jakarta.apache.org/struts/api-1.0/org/apache/struts/taglib/logic/packagesummary.html) -Mostrando valores de ResultSet. El caso mas usual en aplicaciones web es el de mostrar el resultado de una consulta por pantalla. Esto se puede hacer de manera parecida a la anterior, pero habria que mapear el ResultSet a una estructura que pueda recorrerse iterativamente; segun la documentacion de Struts la estructura puede ser Enumeration,Hashtable, Vector o un array de Objetos. -Fichero con mensajes y etiquetas: AplicationResources.properties, debe estar colocado junto a los ficheros .class de struts.Si se realizan cambios en el, hay que reiniciar jrun. Para mostrar estas etiquetas, debe crearse el siguiente tag: <bean:message key="mensaje01"/> En el fichero de AplicationResources.properties mensaje01=Introduzca el usuario Para mostrar mensajes de error (los que cargamos en el ActionErrors) En las clases actio, Form o Bean capturamos un error ActionErrors errors = new ActionErrors(); errors.add(alta,new ActionError(alta.error)); saveErrors(errors); En el fichero JSP aadimos el TAG: <html:errors property="alta" /> En el fichero de AplicationResources.properties alta.error=Se ha producido un error al dar de alta.

28

STRUTS:Implementacin del patrn MVC en aplicaciones Web

Errores comunes con Struts - Erorres en el mapa de acciones. Es muy frecuente a la hora de desarrollar aplicaciones con Struts no indicar correctamente el nombre de una aplicacin, de una clase de formulario, etc hay que revisar el struts-config.xml para comprobar que los nombres de clases que ah se especifican son los correctos y se corresponden con las clases generadas. Hay que tener especial cuidado tambin (como en cualquier otra aplicacin Java) con la nomenclatura de los paquetes que precede al nombre de la clase. De todas formas, la plataforma struts nos avisa sobre los errores de este tipo y nos dice que tal accin no existe en el mapa, o que tal formulario tampoco esta definido o no se corresponde con la accin. Lo veremos en forma de excepcin de mapping. A veces, como consecuencia de un copy-paste en el struts-config.xml, pueden quedar mapeadas acciones que existen pero que no se corresponden con lo que queremos; en esos casos no hay error por la inexistencia de un fichero, y se puede hacer difcil detectar el problema. La solucin universal siempre ser REVISAR bien los nombres hasta que nos lloren los ojos; la evidencia emprica a demostrado que la mayora de problemas en ese sentido vienen por errores en los nombres. - java.lang.NullPointerException Este error ser el pan nuestro de cada da en el desarrollo de Struts ya que los datos de los formularios deben viajar desde una jsp pasando por 3 clases, y es fcil que no todos los datos lleguen cargados. Lo que se recomienda es que cuando se desarrolle el Bean de lgica de negocio, en principio solo se haga una traza de los valores del formulario, para comprobar que llegan como se espera. Una vez depurado el paso de datos, conviene tener la costumbre (como en cualquier otra aplicacin, en cualquier otro lenguaje), de comprobar los objetos para ver si realmente traen un valor distinto de nulo, y en caso afirmativo asignarlo. En una sola linea se puede comprobar y asignar: //aqu va un atentado contra la legibilidad:(<condicion>)?val1:val2;
codigo = (formulraio.getCodigo() != null) ?formulario.getCodigo():new Integer(0);

El formulario puede traer valores vacos (Strings ) o nulos. Dependiendo de nuestra lgica de negocio habr que comprobar lo que llega desde la jsp y transformarlo. Por ejemplo, en el caso de una cadena de caracteres, en caso de venir vaca o con espacios quiz nos interese convertirla a null: // Dentro de la clase Form public void setNombre (String nombre) { if (nombre.trim().compareTo() == 0) // si es nulo this.nombre = null; else this.nombre = nombre; } o ms brevemente: public void setNombre (String nombre) { this.nombre = (nombre.trim().compareTo() == 0)?null:nombre; }

29

También podría gustarte