Monografias.com > Computación > Internet
Descargar Imprimir Comentar Ver trabajos relacionados

Aplicación paso a paso con Struts



    En numerosas ocasiones me escriben usuarios del Web
    consultándome como comenzar a construir aplicaciones Web
    con Java. Hoy vamos a
    ver un posible modo…. y, como siempre, vamos a tratar cambiar
    la perspectiva típica….

    Os advierto que en este caso no va a ser un tutorial muy
    básico….

    Análisis del
    Problema

    No debemos confundir el medio y el fin. Nuestro objetivo es
    construir una aplicación y struts es unos
    más de los componentes técnicos que vamos a
    utilizar.

    Lo más importante es definir de un modo
    inequívoco que es lo que queremos hacer, es decir, tomar
    los requisitos:

    Queremos construir un subsistema para el
    Web www.adictosaltrabajo.com
    que nos permita:

    1. Proporcionar a los usuarios la capacidad de
      decir de donde nos escriben e introducir algunos
      datos que nos permitan obtener estadísticas.
    2. Posteriormente querríamos mostrar en
      un mapa visual los datos adquiridos (esto lo dejamos
      para otro tutorial)

    Los objetivos
    vemos que nos son excesivamente ambiciosos pero nos puede valer.
    Los requisitos son independientes de la tecnología….

    Ahora vamos a, antes de tirar una sola línea de
    código,
    profundizar en los problemas para
    anticipar posibles riesgos
    ligados a la indeterminación de los requisitos o la falta
    de análisis de potenciales riesgos.

    Análisis
    del problema

    Debemos hacernos algunas preguntas

    • ¿Cuales son los datos que queremos que nos
      introduzcan (directa e indirectamente a través de su
      navegación)?
    • ¿Que rechazo puede producir introducir esos
      datos por parte del usuario?
    • ¿Como puede afectar esta información al tratamiento de datos que
      hacemos en el Web asociados a la LOPD (Ley
      Orgánica de Protección de Datos)?
    • ¿Cual va a ser el volumen de
      datos a manejar?
    • ¿Que potenciales riesgos de seguridad
      puede tener la aplicación para nuestro sistema?

    Nos respondemos

    • Para favorecer que a los usuarios no le de
      mucho apuro rellenar la información, vamos a
      solicitar solamente el país  y darles la
      oportunidad de hacer algún comentario del
      Web.
    • Como no les pedimos datos personales
      (vinculados a un usuario en concreto) no afecta al tratamiento
      personal de datos.
    • El volumen de datos se plantea que sea
      pequeño pero debemos establecer mecanismos de
      seguridad para que algún usuario maliciosos no
      nos saturase el Web con la entrada masiva de
      información (siempre hay alguien que nos
      complica la vida )

    También nos debemos preguntar ¿estas son
    todas las preguntas que nos tenemos que hacer? ¿estamos
    planteando bien la toma de requisitos?

    Ya os adelanto que no lo estamos haciendo demasiado bien
    aunque esto es otra guerra que ya
    lucharemos algún día (conceptualización y
    acotamiento de un problema, valoración rápida de
    esfuerzo y coste, identificación de riesgos típicos
    y particulares, etc. )

    Si no somos capaces de hacer una buena
    definición del problema utilizando buenas técnicas de análisis, los
    problemas en la fase de desarrollo serán mucho más
    grandes,

    Además se nos juntarán muchos
    problemas más:

    • La introducción de nueva
      funcionalidad (el tiempo pasa y las necesidades
      evolucionan)
    • Las correcciones de errores
      conceptuales
    • Las prisas por no haber llevado un ritmo de
      trabajo estable y habernos confiado en
      un principio
    • La complejidad de ciertas funciones que en principio
      parecían mucho mas sencillas.

    Diseño de la
    solución

    Primer problema

    Realizamos una descomposición del trabajo a
    realizar (WBS Work Breakdown Structure)

    • Definir la tabla de países (y llenarla).
      Estudiar como luego podríamos situar en un plano los
      resultados
    • Definir la tabla de visitantes (con el campo para
      observaciones)
    • Definir el componente que sea capaz de interaccionar
      con estas tablas (acceso a datos)
    • Definir las reglas para validar si los campos que
      introduce el usuario son válidos
      • Numero de inserciones introducidas en un
        día (para que no nos boqueen el sistema)
      • Rango de valores
        (no nos podemos fiar de las peticiones que
        recibimos)
    • Diseñar el interfaz de usuario y los posibles
      mensajes de error.

    E incluso nos planteamos una posible solución
    (aplicando nuestro conocimiento
    sobre patrones de asignación de responsabilidad [GRASP])

    Si diseñamos, podemos cuestionar el diseño
    y hacernos preguntas del estilo.

    ¿Qué es más conveniente a la hora
    de validar los parámetros?

    1. ¿Que el gestor de visitas valide el
      país (el componente de negocio
      GestorVisitas)?
    2. ¿Que el objeto Visita sea quien valide que los
      campos con los que se inicializa sean correctos (Visita en el
      constructor)?
    3. ¿Que el interfaz (struts) valide los
      parámetros antes de continuar?

    Pues no es tan sencillo y dependerá de distintas
    cosas:

    • ¿Es posible que cambiemos de
      FrameWork?
    • ¿Es posible que creemos otros interfaces
      (consola Windows o
      proceso
      nocturno) a la misma aplicación?
    • ¿Cual es el potencial del utilización
      simultanea de uso de validaciones?  ¿Y de
      reutilización en distintas aplicaciones de la misma
      validación?
    • ¿Qué facilidades nos proporciona el
      FrameWork?

     Con estas preguntas podríamos sacar unas
    conclusiones que se podrían transportar al resto de
    componentes de mi aplicación (podemos prototipar para
    determinar si las conclusiones son correctas antes de haber
    tirado demasiado código en paralelo).

    Nosotros (sin entrar en más detalles) vamos a
    tomar las siguientes decisiones (que pueden ser más o
    menos acertadas):

    La comprobación del país la realizamos en
    GestorVisitas (configurando una consulta sobre la clase
    Validador)

    • Porque así no ligamos la capa de negocio a la
      de presentación y podríamos reaprovechar la
      validación si cambiamos la interfaz y decidimos que no
      sea Web.
    • No la ponemos en la clase Visita porque en
      algún otro subsistema nos puede interesar volver a hacer
      la comprobación sin estar ligada la validación
      con la clase Visita

    La eliminación de palabras conflictivas la
    hacemos en la capa de presentación

    • Porque puede ser general para todos los
      parámetros de nuestra aplicación Web (esto es un
      potencial problema de seguridad) y el FrameWork nos lo facilita
      (aunque no vamos a profundizar en la resolución del
      problema)
    • Porque en otros subsistemas (como en procesos
      batch nocturnos) podríamos requerir llamar a esta
      función de negocio y no es necesario
      realizar las comprobaciones de seguridad por cada llamada (el
      entorno no debería ser tan hostil)

    Otras consideraciones de
    diseño

    La obtención de una conexión  a la
    base de datos
    (en sistemas
    concurrentes) es un potencial riesgo en las
    aplicaciones Web (cuello de botella) y vamos a tratar de
    anticipar el problema. Suerte que ya hicimos otro tutorial donde
    analizamos como
    configurar un pool de conexiones a la base de datos con
    Struts
    .

    Aún así tenemos que hacernos más
    preguntas:

    • ¿La capa de negocio y presentación van
      a estar en la misma máquina? ¿Y en el
      fututo?
      • Si es así, es muy posible que queramos
        utilizar las facilidades del servidor
        Web de configuración y administración de pilas de
        conexiones.
      • Sino es así, es posible que mi
        aplicación sea más compleja y/o que tenga que
        obtener las conexiones de otros sitios (un servidor de
        aplicaciones o mi propio gestor)

    Bueno, se ponga como se ponga, parece que hace falta que
    nuestras funciones de negocio no sean las encargadas de gestionar
    las conexiones a la base de datos. Si ellas no las gestionan,
    significa que les debe llegar algo que les permita acceder a la
    conexión a la base de datos cuando sea necesario (esto es
    una posible aplicación del patrón de diseño
    de inversión de responsabilidad).
    Además este algo debe ser independiente del tipo de
    aplicación que estemos construyendo (del tipo de interfaz
    de usuario).

    De momento hemos pintado unos cuantos elementos que es
    posible que no entendamos:

    • Nuestro GestorVisitas tendrá siempre
      una variable llamada fuenteDatos (inicialmente nula) que
      nos permitirá acceder a un conexión a la base de
      datos.
    • El GestorVisitas  implementa un interfaz
      marcador (sin métodos)
      que nos permitirá determinar en ejecución que
      esta clase requiere acceder a la base de datos
    • La clase Visita implementa el interfaz VO
      (Value Object) que nos será útil cuando queramos
      que clases que representen valores sean tratadas de un modo
      homogéneo (por ejemplo caches y
      paginaciones)

    (No estaría mal repasar un poquito los patrones
    de
    diseño generales
    y los
    J2EE
    )

    Conclusiones del
    diseño

    Todavía no hemos tirado una línea y ya
    tenemos claras bastantes cosas.

    ¿SORPRENDIDOS? Es que para esto vale
    DISEÑAR

    Pensar así (aunque el diseño no sea muy
    avanzado) requiere formación y entrenamiento.
    Nno os pongáis nerviosos que todo llega (yo todos los
    días aprendo algo nuevo).

    Construcción

    Jamás debemos anticiparnos a la hora de empezar a
    escribir código.

    Cuanto mejor esté definido lo que tenemos
    que hacer, menos nos costará hacerlo y menos frustrados
    nos encontraremos por retocar constantemente nuestro
    desarrollo.

    Instalación del
    entorno

    Lo primero que hacemos es buscar una herramienta
    moda para
    construir. A mi me gusta NetBeans y aunque ya hay una primera
    versión 4, vamos a dejarla un poco que se estabilice antes
    de usarla (estar siempre a la última es asumir demasiado
    riesgo)

    Construimos un nuevo proyecto (da
    igual la versión 3.5 o 3.6)

    Lo creamos

    Le asignamos nombre

    Nos descargamos la última versión de
    Struts (en este caso si utilizo la última versión
    porque me interesa comprobar su estado)

    Descomprimimos el fichero y localizamos la
    aplicación Web ejemplo en blanco

    Situamos el fichero en nuestra instalación del
    TOMCAT

    Arrancamos TOMCAT y automáticamente se
    descomprime el directorio y está ya lista la
    aplicación Web para ser utilizada.

    Montamos en NetBeans el directorio
    descomprimido

    Y ya tenemos todo lo necesario para empezar a construir
    nuestra aplicación

    Arrancamos la aplicación para verificar que no
    hay ningún problema de compatibilidad

    Decisión del punto donde empezar a
    construir

    Ahora tenemos que empezar por algún sitio (esto
    es normalmente lo más difícil de
    decidir).

    • Si empezamos por la parte de presentación, es
      muy posible que construyamos una aplicación demasiado
      vinculada al FrameWork y al problema particular (a corto plazo)
      por lo que tendremos poca capacidad de
      reutilización.
    • Si empezamos por la capa de acceso a negocio, es muy
      posible que despistemos que algunas cosas que dependen de
      contexto, como por ejemplo como obtener una conexión a
      la base de datos.

    Si utilizamos siempre el mismo FrameWork (sea el que
    sea), esta pregunta solo nos la tenemos que hacer solo una vez y
    aplicarla en la fase de diseño. Si estamos constantemente
    cambiando el modo de hacer las cosas, será difícil
    anticipar conclusiones. Si en una organización grande se deja esta
    decisión a criterio de cada equipo, sacar conclusiones
    globales es difícil y más aún extrapolar
    soluciones de
    problemas encontrados en producción.

    Os recomiendo que empecéis siempre por la base de
    datos…. esto es realmente lo importante. Si en el futuro se
    pusiera de moda otro lenguaje y
    tenemos bien modelada la base de datos, la sustitución
    será menos traumática.

    Diseño de la base de
    datos

    Creamos una nueva base de datos con el panel de control
    de MySQL.
    Podéis ver como
    instalar MySQL y su

    consola en este otro tutorial

    .

    Le asignamos un nombre a la base de datos

    Creamos las tablas

    Definimos los campos de la primera tabla

    Le asignamos el nombre a la tabla

    Y comprobamos el resultado

    Y repetimos la operación con la tabla visitas
    (ojo que el país ahora no debe ser clave
    única)

    Insertamos los primeros valores de prueba con lo que
    conseguimos descubrir las sentencias SQL que
    necesitaríamos en nuestros programas.
    Podéis ver en otro de nuestro tutoriales
    como
    generar el código Java para acceder a estas tablas

    sin saber demasiado.

    Introducimos también algún valor en la
    tabla de países

    Construcción de la
    aplicación

    Lo primero que hacemos es construir el formulario de
    entrada de datos.

    En un formulario pueden ocurrir distintos
    problemas:

    1. Que el usuario por equivocación haga un doble
      click e introduzca dos veces los datos
    2. Que inserte valores incorrectos y necesitemos volver
      a mostrar los campos y destacar de algún modo el campo
      incorrecto.

     Utilizaremos un JSP con las etiquetas particulares
    que proporciona Struts para resolver los problemas anteriormente
    mencionados (aunque con el primero hay que hacer algo
    más).

    Tenemos que entender como funciona un poquito el
    FrameWork Struts

    1. Un usuario hace una petición
    2. Cada petición está asociada a una
      acción que contiene la regla de negocio
      particular
    3. La acción suele necesitar un conjunto de datos
      que se encapsulan en un objeto llamado Form (este Form puede
      ser una clase física o un
      elemento general cuyo comportamiento se define en el fichero de
      configuración, también llamado
      DynaForm)
    4. Los datos se pueden validar y si falla la
      validación se puede volver a mostrar el formulario de
      entrada.
    5. Una vez ejecutada la acción, puede que el
      resultado sea favorable o desfavorable por lo que se delega
      sobre distintos elementos de presentación en cada
      caso.
    6. Todo mensaje mostrado puede sacarse a un fichero de
      recursos para
      favorecer su mantenimiento y la internacionalización
      de las aplicaciones (aunque ahora no nos haga
      falta).
    7. Cada elemento se construye por separado y se
      relacionan en el fichero struts-config.xml

    Ya se que no es fácil la primera vez (y menos
    aún identificar los errores según aparecen). Vamos
    a construir únicamente el código que es particular
    del interfaz que hemos elegido y marcaremos en el código
    los puntos en los que hace falta acceder a las reglas de negocio
    y los datos (que eso ya es Java puro y duro)

    La
    estructura

    Aunque la aplicación no es plenamente funcional
    con esta estructura de
    ficheros seréis capaz de reproducir el ejemplo. En rojo
    hemos marcado los únicos ficheros que hemos cambiado o
    creado. Debéis tener precaución con los ficheros en
    el directorio lib (ver
    el tutorial sobre como configura el pool de conexiones a la base
    de datos con struts
    ). No os preocupéis de
    momento en la posición de los ficheros creados (eso es un
    problema menor a estas alturas aunque en el futuro si nos
    deberá preocupar)

    * index.jsp

    * resultadocorrecto.jsp

    * visitas.jsp

    *

    ****META-INF

    * context.xml

    * MANIFEST.MF

    *

    ****pages

    * Welcome.jsp

    *

    ****WEB-INF

    * struts-bean.tld

    * struts-config.xml

    * struts-html.tld

    * struts-logic.tld

    * struts-nested.tld

    * struts-tiles.tld

    * tiles-defs.xml

    * validation.xml

    * validator-rules.xml

    * web.xml

    *

    ****classes

    * * MessageResources.properties

    * *

    * ****resources

    * * MessageResources.properties

    * *

    * ****webstruts

    * InsertaVisitasAction.class

    * InsertaVisitasAction.java

    *

    ****lib

    * commons-beanutils.jar

    * commons-collections.jar

    * commons-dbcp-1.1.jar

    * commons-digester.jar

    * commons-fileupload.jar

    * commons-lang.jar

    * commons-logging.jar

    * commons-pool-1.1.jar

    * commons-validator.jar

    * jakarta-oro.jar

    * jdbc2_0-stdext.jar

    * jstl.jar

    *
    mysql-connector-java-3.0.8-stable-bin.jar

    * standard.jar

    * struts-legacy.jar

    * struts.jar

    *

    ****src

    * build.xml

    *

    ****java

    ****resources

    application.properties

    A mi me gusta tocar los ficheros de configuración
    a mano, sobre todo al principio, pero no olvidéis que hay
    herramientas
    gráficas (consolas
    para struts
    ) para poder hacerlo
    (incluso se integran fácilmente con nuestro
    editor)

    El fichero de
    configuración     *  
    struts-config.xml

    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <!DOCTYPE struts-config PUBLIC

    "-//Apache Software
    Foundation//DTD Struts Configuration 1.2//EN"

    "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">

    <struts-config>

    <!–
    ============================================ Data Source
    Configuration –>

    <data-sources>

    <data-source
    type="org.apache.commons.dbcp.BasicDataSource">

    <set-property property="driverClassName"
    value="com.mysql.jdbc.Driver" />

    <set-property property="url"
    value="jdbc:mysql://localhost/visitasadictos"
    />

    <set-property property="username"
    value="root" />

    <set-property property="password" value=""
    />

    <set-property property="maxActive" value="10"
    />

    <set-property property="maxWait" value="5000"
    />

    <set-property property="defaultAutoCommit"
    value="false" />

    <set-property property="defaultReadOnly"
    value="false" />

    <set-property property="validationQuery"
    value="SELECT COUNT(*) FROM paises" />

    </data-source>

    </data-sources>

    <!–
    ================================================ Form
    Bean Definitions –>

    <form-beans>

    <form-bean

    name="VisitasForm"

    type="org.apache.struts.action.DynaActionForm">

    <form-property name="pais"
    type="java.lang.Integer"/>

    <form-property name="observaciones"
    type="java.lang.String"/>

    </form-bean>

    </form-beans>

    <!–
    ========================================= Global
    Exception Definitions –>

    <global-exceptions>

    <!– sample exception handler
    <exception

    key="expired.password"
    type="app.ExpiredPasswordException"
    path="/changePassword.jsp"/>

    end sample –>

    </global-exceptions>

    <!–
    =========================================== Global
    Forward Definitions –>

    <global-forwards>

    <!– Default forward to "Welcome" action
    –>

    <!– Demonstrates using index.jsp to forward
    –>

    <forward name="welcome"
    path="/Welcome.do"/>

    <forward name="correcto"
    path="/resultadocorrecto.jsp"/>

    </global-forwards>

    <!–
    =========================================== Action
    Mapping Definitions –>

    <action-mappings>

    <!– Default "Welcome" action
    –>

    <!– Forwards to Welcome.jsp
    –>

    <action path="/Welcome"
    forward="/pages/Welcome.jsp"/>

    <action path="/InsertaVisistas"

    type="webstruts.InsertaVisitasAction"

    name="VisitasForm"

    scope="request"

    validate="true"

    input="/visitas.jsp"/>

    </action-mappings>

    <!–
    ============================================= Controller
    Configuration –>

    <controller
    processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>

    <!– ========================================
    Message Resources Definitions –>

    <message-resources
    parameter="MessageResources" />

    <!–
    =============================================== Plug Ins
    Configuration –>

    <plug-in
    className="org.apache.struts.tiles.TilesPlugin"
    >

    <!– Path to XML definition file
    –>

    <set-property property="definitions-config"
    value="/WEB-INF/tiles-defs.xml" />

    <!– Set Module-awareness to true
    –>

    <set-property property="moduleAware"
    value="true" />

    </plug-in>

    <plug-in
    className="webstruts.InsertaVisitasAction"
    >

    </plug-in>

    <!–
    ===================================================
    Validator plugin –>

    <plug-in
    className="org.apache.struts.validator.ValidatorPlugIn">

    <set-property property="pathnames"

    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>

    </plug-in>

    </struts-config>

    La acción    
    *          
    InsertaVisitasAction.java

    /*

    * InsertaVisitasAction.java

    *

    * Created on October 31, 2004, 12:27
    PM

    *

    * Roberto Canales Mora

    */

    package webstruts;

    import org.apache.struts.action.*;

    import javax.servlet.http.*;

    import java.util.*;

    public class InsertaVisitasAction extends
    Action implements org.apache.struts.action.PlugIn
    {

    public ActionForward
    execute
    (ActionMapping actionMapping,ActionForm
    actionForm,

    HttpServletRequest
    httpServletRequest,

    HttpServletResponse httpServletResponse) throws
    Exception {

    ActionForward retValue = null;

    try // ejecutamos la funcion de
    negocio

    {

    // Obtenemos acceso al formulario

    DynaActionForm formulario = (DynaActionForm)
    actionForm;

    // aqui va la inserción de los
    datos

    System.out.println("El pais es: " +
    formulario.get("pais"));

    System.out.println("Observaciones: " +
    formulario.get("observaciones"));

    // redirigimos a la
    presentación

    retValue =
    actionMapping.findForward("correcto");

    }

    catch(Exception e) // en caso de problemas
    retornar a la página origen

    {

    // recuperamos acceso al JSP deorigen

    retValue =
    actionMapping.getInputForward();

    // damos de alta los errores

    ActionErrors errores = new
    ActionErrors();

    errores.add(errores.GLOBAL_ERROR, new
    ActionError("error.logica"));

    errores.add("pais", new
    ActionError("error.enpais"));

    this.addErrors(httpServletRequest,
    errores);

    }

    return retValue; // redirigimos a la
    presentacion

    }

    /*

    * Los métodos destroy e init son
    obligatorios al implementar el interfaz PlugIn

    */

    public void destroy() {

    }

    public void
    init
    (org.apache.struts.action.ActionServlet
    actionServlet,

    org.apache.struts.config.ModuleConfig
    moduleConfig) throws javax.servlet.ServletException
    {

    Hashtable vPaises = new Hashtable();

    // aqui hay que poner el código que nos
    proporcione los datos de la base de datos

    vPaises.put("1","España"); // este codigo
    hay que quitarlo

    vPaises.put("2","Chile");

    // mostramos un mensaje para asegurarnos que los
    datos están en memoria

    System.out.println("Tenemos el
    Vector");

    // ponemos la tabla en el ambito de la
    aplicación

    actionServlet.getServletContext().setAttribute("tablapaises",vPaises);

    }

    }

    Esta acción tiene una peculiaridad y es que
    implementa en interfaz  plugIn (métodos destroy e
    init) que nos permite que se ejecute código nada mas
    inicializarse el componente. La tabla de países no creo
    que cambie demasiado a menudo por lo que nos puede interesar
    recuperarla solo una vez para todos los usuarios del
    sistema.

    El JSP de entrada de datos *  
    visitas.jsp

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

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

    <html>

    <head>

    <title><bean:message
    key="index.titulo"/></title>

    </head>

    <body>

    <center>

    <h2><bean:message
    key="index.cuentanostuorigen"/></h2>

    <hr width='60%'>

    <html:form
    action='/InsertaVisistas'>

    <table border="0">

    <tr>

    <td>Pais</td><td>

    <html:select property="pais" >

    <html:options collection="tablapaises"
    property="key" labelProperty="value" />

    </html:select>

    </td><td><html:errors
    property="pais" /> </td>

    </tr>

    <tr>

    <td><!– podría ser una clave en
    el fichero de recursos –>

    Observaciones</td><td>
    <html:textarea property="observaciones" cols="50"
    rows="3" />

    </td><td><html:errors
    property="observaciones" /></td>

    </tr>

    <tr><td> <html:submit
    value="Enviar"/></td> </tr>

    </table>

    </html:form>

    <br/> <font color="#FF0000"> <html:errors/>
    </font>

    </center>

    </body>

    </html>

    Analizamos este código con detenimiento porque
    tiene muchas más cosas de las que puede parecer en un
    principio.

     ¿De donde salen los
    valores del formulario? De los datos que ha puesto el
    plugIn en la aplicación

    <html:select property="pais" >
    <html:options collection="tablapaises" property="key"
    labelProperty="value" />
    </html:select>

    ¿De donde salen los textos de la
    página que no están directamente escritos?
    Del fichero de recursos

    <bean:message
    key="index.titulo"/>

    ¿Para que vale esta línea? Para
    mostrar errores cuando se produzcan problemas en
    validaciones

    <html:errors property="pais" />

    Debemos buscar en la acción este
    código para entenderlo correctamente

      errores.add("pais", new
    ActionError("error.enpais"));

    JSP resultante *  
    resultadocorrecto.jsp

    <%@page
    contentType="text/html"%>

    <html>

    <head><title>JSP
    Page</title></head>

    <body>

    <h2>La acción se ejecutó
    satisfactoriamente</h2>

    </body>

    </html>

    Añadir el código de acceso a
    datos

    Ahora que ya tenemos el código particular de
    Struts  y nos queda el código de acceso a la base de
    datos. Esto es Java puro y duro.

    Creamos el resto de las clases (aunque el código
    no es definitivo ya que el tratamiento de errores de momento es
    pésimo)

    Visita.java

    package webstruts;

    /*

    * Visita.java

    * Created on October 31, 2004, 6:17
    PM

    * @author Roberto Canales

    */

    public class Visita {

    private int id;

    private int pais;

    private String observaciones;

    private String ip;

    /** Creates a new instance of Visita
    */

    public Visita() {}

    /** Creates a new instance of Visita
    */

    public Visita(int pais, String
    observaciones,String ip) {

    this.pais = pais;

    this.observaciones = observaciones;

    this.ip = ip;

    }

    /** Getter for property id.

    * @return Value of property id.

    */

    public int getId() {return
    id;}

    /** Setter for property id.

    * @param id New value of property id.

    */

    public void setId(int id) {this.id =
    id;}

    /** Getter for property
    observaciones.

    * @return Value of property
    observaciones.

    */

    public java.lang.String
    getObservaciones() {return
    observaciones;}

    /** Setter for property
    observaciones.

    * @param observaciones New value of property
    observaciones.

    */

    public void
    setObservaciones(java.lang.String observaciones)
    {

    this.observaciones = observaciones;}

    /** Getter for property pais.

    * @return Value of property pais.

    */

    public int getPais() {return
    pais;}

    /** Setter for property pais.

    * @param pais New value of property
    pais.

    */

    public void setPais(int pais) {this.pais
    = pais;}

    /** Getter for property ip.

    * @return Value of property ip.

    */

    public java.lang.String getIp() {return
    ip;}

    /** Setter for property ip.

    * @param ip New value of property ip.

    */

    public void setIp(java.lang.String ip)
    {this.ip = ip;}

    }

    GestorVisitas.java

    /*

    * GestorVisitas.java

    *

    * Created on October 31, 2004, 6:21
    PM

    */

    package webstruts;

    import javax.sql.*;

    import java.sql.*;

    /**

    *

    * @author Roberto Canales Mora

    */

    public class GestorVisitas extends
    ClaseNegocio {

    /** Creates a new instance of GestorVisitas
    */

    public GestorVisitas() {

    }

    void depura(String mensaje)

    {

    System.out.println("GestorVisitas – " +
    mensaje);

    }

    public boolean insertaVisita(Visita
    pVisita) {

    try

    {

    Connection con = this.dameConexion();

    PreparedStatement pstmt =

    con.prepareStatement("insert into visitas
    (pais,observaciones,ip) values (?,?,?)");

    // establecemos los valores variables

    pstmt.setInt(1,pVisita.getPais()); //
    establecemos el entero

    pstmt.setString(2,pVisita.getObservaciones());
    // establecemos el entero

    pstmt.setString(3,pVisita.getIp()); //
    establecemos el entero

    // ejecutamos la consulta

    int resultado =
    pstmt.executeUpdate();

    depura("El número de elementos afectados
    es " + resultado);

    // retornamos la conexion al pool

    con.close();

    return true;

    }

    catch (SQLException e)

    {

    depura("Error al insertar " +
    e.getMessage());

    return false;

    }

    }

    }

    ClaseNegocio.java

    /*

    * ClaseNegocio.java

    * Created on October 31, 2004, 6:20
    PM

    */

    package webstruts;

    import javax.sql.*;

    import java.sql.*;

    /**

    *

    * @author Roberto Canales Mora

    */

    public class ClaseNegocio {

    private javax.sql.DataSource fuenteDatos =
    null;

    /** Creates a new instance of ClaseNegocio
    */

    public ClaseNegocio() {

    }

    public boolean
    inicializaFuenteDatos(javax.sql.DataSource
    pFuenteDatos) {

    fuenteDatos = pFuenteDatos;

    return true;

    }

    public java.sql.Connection dameConexion()
    {

    try

    {

    return fuenteDatos.getConnection();

    }

    catch(Exception e)

    {

    }

    return null;

    }

    }

    InsertaVisistasAction.java (todavía hay que
    recuperar los países de la base de datos pero no queremos
    mezcla demasiadas cosas)

    /*

    * InsertaVisitasAction.java

    *

    * Created on October 31, 2004, 12:27
    PM

    *

    * Roberto Canales Mora

    */

    package webstruts;

    import org.apache.struts.action.*;

    import javax.servlet.http.*;

    import java.util.*;

    public class InsertaVisitasAction extends Action
    implements org.apache.struts.action.PlugIn {

    public ActionForward execute(ActionMapping
    actionMapping,

    ActionForm actionForm,HttpServletRequest
    httpServletRequest,

    HttpServletResponse httpServletResponse) throws
    Exception {

    ActionForward retValue = null;

    try // ejecutamos la funcion de
    negocio

    {

    // Obtenemos acceso al formulario

    DynaActionForm formulario = (DynaActionForm)
    actionForm;

    // Construimos el objeto de negocio

    GestorVisitas gestorVisitas = new
    GestorVisitas();

    // le damos acceso a la fuente de
    datos

    gestorVisitas.inicializaFuenteDatos(this.getDataSource(httpServletRequest));

    // recuperamos el pais y
    observaciones

    Integer pais =
    (Integer)formulario.get("pais");

    String observaciones =
    formulario.get("observaciones").toString();

    // llamamos al metodo de negocio

    boolean resultado =
    gestorVisitas.insertaVisita(new
    Visita(pais.intValue(),

    observaciones,

    httpServletRequest.getRemoteAddr()));

    // redirigimos a la
    presentación

    if(resultado == true)

    retValue =
    actionMapping.findForward("correcto");

    else

    retValue =
    actionMapping.findForward("incorrecto");

    }

    catch(Exception e) // en caso de problemas
    retornar a la página origen

    {

    // recuperamos acceso al JSP deorigen

    retValue =
    actionMapping.getInputForward();

    // damos de alta los errores

    ActionErrors errores = new
    ActionErrors();

    errores.add(errores.GLOBAL_ERROR, new
    ActionError("error.logica"));

    errores.add("pais", new
    ActionError("error.enpais"));

    this.addErrors(httpServletRequest,
    errores);

    }

    return retValue; // redirigimos a la
    presentacion

    }

    /*

    * Los métodos destroy e init son
    obligatorios al implementar el interfaz PlugIn

    */

    public void destroy() {

    }

    public void
    init(org.apache.struts.action.ActionServlet
    actionServlet,

    org.apache.struts.config.ModuleConfig
    moduleConfig)

    throws javax.servlet.ServletException
    {

    Hashtable vPaises = new Hashtable();

    // aqui hay que poner el código que nos
    proporcione los datos de la base de datos

    vPaises.put("1","España"); // este codigo
    hay que quitarlo

    vPaises.put("2","Chile");

    // mostramos un mensaje para asegurarnos que los
    datos están en memoria

    System.out.println("Tenemos el
    Vector");

    // ponemos la tabla en el ambito de la
    aplicación

    actionServlet.getServletContext().setAttribute("tablapaises",vPaises);

    }

    }

    Obtención de los
    datos

    Para que el ejemplo sea completamente utilizable
    necesitamos las tablas.

    Vamos a recuperar la estructura de la tabla
    valiéndonos de phpMyAdmin (recordamos
    otro de nuestro tutoriales
    )

    Elegimos las tablas y el modo de
    extracción.

    Y nos genera algo tal que esto

    #

    # Table structure for table `paises`

    #

    DROP TABLE IF EXISTS `paises`;

    CREATE TABLE `paises` (

    `id` int(4) NOT NULL auto_increment,`pais`
    varchar(50) NOT NULL default '',

    `x` int(4) default '0',`y` int(4) default
    '0',

    PRIMARY KEY (`id`),UNIQUE KEY `paisesindex`
    (`pais`)

    ) TYPE=MyISAM AUTO_INCREMENT=5 ;

    #

    # Dumping data for table `paises`

    #

    INSERT INTO `paises` VALUES (1, 'España',
    0, 0);

    INSERT INTO `paises` VALUES (2, 'Chile', 0,
    0);

    INSERT INTO `paises` VALUES (3, 'Guatemala', 0, 0);

    INSERT INTO `paises` VALUES (4, 'Francia', 10, 10);

    #
    ——————————————————–

    #

    # Table structure for table `visitas`

    #

    DROP TABLE IF EXISTS `visitas`;

    CREATE TABLE `visitas` (

    `id` int(11) NOT NULL auto_increment,

    `pais` int(4) unsigned zerofill NOT NULL default
    '0000',

    `observaciones` varchar(100) NOT NULL default
    '12',

    `ip` varchar(255) NOT NULL default
    '',

    PRIMARY KEY (`id`), KEY `indexpais`
    (`pais`)

    ) TYPE=MyISAM AUTO_INCREMENT=5 ;

    #

    # Dumping data for table `visitas`

    #

    INSERT INTO `visitas` VALUES (1, 0002,
    'comentario1', '127.0.0.1');

    INSERT INTO `visitas` VALUES (2, 0001,
    'comentario2', '127.0.0.1');

    INSERT INTO `visitas` VALUES (3, 0001,
    'comentario3', '127.0.0.1');

    INSERT INTO `visitas` VALUES (4, 0002,
    'comentario4', '127.0.0.1');

    Con esto ya tenemos todo lo necesario para orientar el
    programa.

    Conclusiones

    Si tienes las ideas medianamente claras y eres capaz de
    descomponer un problema grande en problemas pequeñitos, no
    es tan difícil construir una aplicación.

    Parece que hemos invertido demasiado esfuerzo para algo
    aparentemente trivial y que podríamos haber resuelto
    prácticamente con un par de JSPs o Servlets pero no nos
    engañemos: Todas las aplicaciones tiende a complicarse y
    si ha hemos constuido así será fácil
    ampliarla por cualquier sitio.

    Aunque parezca contradictorio con el párrafo
    anterior, francamente creo que tendemos a tecnificar demasiado
    los problemas y nos dejamos llevar por las modas; No en todos los
    casos es necesario solucionar los problemas de un modo tan
    flexible (esto implica un coste inicial muy alto que puede hacer
    inviable un plan de
    negocio).

    Struts es un buen posible punto de partida pero tampoco
    nos tenemos que equivocar:

    • Es solo un modo más de plantear el Front-End
      (interfaz con el cliente) de una
      aplicación y hay 200 modos más.
    • Requiere un entrenamiento y aprendizaje que
      se justificará si lo utilizamos habitualmente o queremos
      construir sistemas altamente robustos.
    • Muchas empresas crean
      su propios FrameWorks y puedes llevarte sorpresas si te
      acostumbras solo a utilizar Struts
    • Algunas empresas tienen desaconsejado el uso de
      Struts (normalmente porque han tenido malas experiencias con
      consultoras que han construido soluciones muy acopladas por
      entender mal el producto)
    • El mantenimiento es enrevesado y puede despistar a
      equipos poco cualificados
    • Es necesario ampliarlo para resolver problemas en
      entornos profesionales

    Roberto Canales Mora

    www.adictosaltrabajo.com

    Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

    Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

    Categorias
    Newsletter