Issuu on Google+

Desarrollo de Aplicaciones Web I


2

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

3

ÍNDICE

Página

Presentación

5

Red de contenidos

6

Unidad de aprendizaje 1: Modelo Vista Controlador – Patrón MVC 1.1 Tema 1

: Fundamentos de Struts 2

9

1.1.1. : Arquitectura y Configuración de aplicaciones

9

1.1.2. : La clase Action

13

1.1.3. : Librerías de etiquetas de Struts 2

29

1.1.4. : Internacionalización – I18N

51

1.2 Tema 2

: Acceso optimizado a base de datos y otras

63

características Struts 2 1.2.1. : Uso de un pool de conexiones para acceso a la fuente

63

de datos 1.2.2. : Librería de Etiquetas de Struts 2 – Principales

72

componentes 1.2.3. : Patrón Composite View – Struts 2 Tiles

87

Unidad de aprendizaje 2: Persistencia de datos – Framework IBATIS 2.1 Tema 3

: Introducción a IBATIS

101

2.1.1. : IBATIS – Introducción

101

2.1.2. : Operaciones básicas de acceso a base de datos con

110

IBATIS 2.2 Tema 4

: Otras operaciones con IBATIS

119

2.2.1. : Otras operaciones y características de IBATIS

119

2.2.2. : Tópicos avanzados de IBATIS e Integración con

128

Struts 2

Unidad de aprendizaje 3: Reportes en Sistemas empresariales 3.1 Tema 5

CIBERTEC

: Reportes con JasperReport

139

CARRERAS PROFESIONALES


4

3.1.1. : Dise帽o e implementaci贸n de reportes con la

141

herramienta Ireport 3.2 Tema 6

: Struts 2 y JasperReport

3.2.1. : Integraci贸n de Struts 2 y JasperReport

142 142

Anexo 1

157

Anexo 2

167

Anexo 3

172

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

5

PRESENTACIÓN Desarrollo de Aplicaciones Web I pertenece a la línea de Programación y Desarrollo de Aplicaciones. Es un curso de especialidad sólo en la carrera de Computación e Informática. Permite al estudiante concretizar proyectos informáticos web, aplicando conocimientos previos aprendidos en diferentes cursos y poniendo en práctica la teoría adquirida. De esta manera, consolida conocimientos de diversos cursos de especialidad. Es práctico y desarrollado en laboratorio. Se implementarán soluciones web que utilizarán los Frameworks Struts 2 e IBATIS en forma combinada.

El manual para el curso ha sido diseñado bajo la modalidad de unidades de aprendizaje, las que se desarrollan durante semanas determinadas. En cada una de ellas, hallará los logros, que debe alcanzar al final de la unidad; el tema tratado, el cual será ampliamente desarrollado; y los contenidos, que debe desarrollar, es decir, los subtemas. Por último, encontrará las actividades que deberá desarrollar en cada sesión, que le permitirán reforzar lo aprendido en la clase.

El curso es eminentemente práctico y se desarrolla íntegramente en laboratorio. En primer lugar, se inicia con el reconocimiento de los principales patrones de arquitectura de software, destacándose el patrón Model View Controller (MVC). Luego, continúa con la presentación del Framework MVC Struts 2. Se profundiza en sus principales características y componentes. Después, se desarrollan conceptos de persistencia de datos utilizando para ello el Framework IBATIS. Por último, se concluye con la elaboración de reportes empresariales, utilizando la herramienta IReport, el lenguaje jasperReport e integrándolos a aplicaciones web creadas con Struts 2.

CIBERTEC

CARRERAS PROFESIONALES


6

RED DE CONTENIDOS

Desarrollo de Aplicaciones Web 1

Modelo Vista Controlador – Patrón MVC

Fundame ntos de Struts 2

Otras Características Struts 2

CARRERAS PROFESIONALES

Persistencia de datos – Framework IBATIS

Introducción a IBATIS

Otras operaciones IBATIS

Reportes en sistemas empresariales

Tema 5 JasperReport

CIBERTEC

Tema 6 Struts 2 y Jasper


DESARROLLO DE APLICACIONES WEB I

7

UNIDAD DE APRENDIZAJE

1

MODELO VISTA CONTROLADOR – PATRÓN MVC LOGRO DE LA UNIDAD DE APRENDIZAJE •

Al finalizar la unidad, el alumno, utilizando el framework MVC STRUTS 2, implementa una aplicación web que contenga, en su estructura, el componente Action, las principales etiquetas del framework y acceso a base de datos a través de un pool de conexiones.

Al finalizar la unidad, el alumno se integra a un equipo de trabajo que refleja en su estructura los roles de un equipo de proyecto de desarrollo de software.

TEMARIO 1.1 Tema 1 : Fundamentos de Struts 2 1.1.1. : Arquitectura y Configuración de aplicaciones 1.1.2. : La clase Action 1.1.3. : Librerías de etiquetas de Struts 2 1.1.4. : Internacionalización – I18N

1.2 Tema 2 : Acceso optimizado a base de datos y otras características de Struts 2 1.2.1. : Uso de un Pool de conexiones para acceso a la fuente de datos 1.2.2. : Librería de Etiquetas de Struts 2 – Principales componentes. 1.2.3. : Patrón Composite View – Struts 2 Tiles

ACTIVIDADES PROPUESTAS •

Los alumnos implementan una aplicación web básica, utilizando las principales características del framework MVC Struts 2.

1.1 Fundamentos de Struts 2

CIBERTEC

CARRERAS PROFESIONALES


8

Struts 2 es un framework que implementa el patrón de arquitectura MVC en Java. Éste organiza de manera independiente las capas: Model (Objetos del Modelo del Negocio), View (interfaz con el usuario u otro sistema) y la capa Controller (controlador del flujo de la aplicación. Se muestra, a continuación, el esquema básico de funcionamiento de esta arquitectura. La capa Model en Struts 2 inicia con los componentes Action. Debajo de éstos, se tendrán diversos componentes: 9 Services (Lógica pura de negocio) 9 DAOs (objetos de persistencia de datos), entre otros. Se muestra, a continuación, el esquema básico de la arquitectura MVC implementado por el framework Struts 2.

Figura 1.1

Una característica típica de la capa View de Struts 2 es el uso de unos componentes especiales denominados Results. Éstos normalmente son representados por una página JSP; sin embargo, puede constituir, también, flujos de bytes, objetos del framework Tiles, etc.

1.1.1. Arquitectura y configuración de aplicaciones La arquitectura MVC funciona en Struts 2 básicamente de la siguiente manera: a través de un navegador se genera una solicitud. Ésta es capturada por la capa Controller (implementada por el componente FilterDispathcher representado por un único filtro especializado). Este filtro analizará la solicitud y verificará si el componente invocado se encuentra registrado en el archivo de configuración XML de Struts 2. Éste tiene por defecto el nombre struts.xml.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

9

El componente invocado, normalmente un Action de Struts 2, instanciará y/o utilizará diversos objetos de negocio para concretar la tarea solicitada. Según el resultado que retorne el componente Action, la capa Controller derivará la respuesta generada a un objeto Result (normalmente una página JSP).

1.1.1.1. Ejercicio 1: Aplicación web básica de Struts 2 Se probará una aplicación web con los componentes mínimos para el correcto funcionamiento del framework Struts 2. a) Paso 1: mportar el archivo struts2-blank-2.1.8.1.war Al descargar el framework struts2 ,se tendrá acceso a una aplicación web de prueba, que cuenta con las características mínimas para que pueda ser ejecutada. Esta aplicación viene empaquetada dentro del archivo struts2-blank-2.1.8.1.war. Luego, de importarla, se visualizará un proyecto web, tal como se muestra a continuación:

1

2

Notas: 1) El principal archivo de configuración del Framework es el archivo struts.xml. En él, se registrarán sus principales

CIBERTEC

CARRERAS PROFESIONALES


10

componentes. Se inicia esta sesión con el registro de la clase Action. 2) Puede observar las librerías mínimas con las que todo proyecto basado en Struts 2 debería contar. Dentro de ellas, destaca el archivo struts2-core-2.1.8.1.jar.

b) Paso 2: Revisar el archivo web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>

Notas: 1) Note el registro del filtro controlador del framework Struts 2. Este componente “atrapará” todas las solicitudes (request) generadas desde un cliente, dado que tiene como alias /*.

c) Paso 3: Ejecutar la aplicación

CARRERAS PROFESIONALES

CIBERTEC

1


DESARROLLO DE APLICACIONES WEB I

11

d) Paso 4: 隆Excelente!, ha culminado el proceso de probar exitosamente la aplicaci贸n web struts2-blank-2.1.8.1

1.1.2. La clase Action

CIBERTEC

CARRERAS PROFESIONALES


12

Un action es, en Struts 2, el primer componente de la capa Model dentro de la arquitectura MVC. Un actions realiza básicamente tres pasos dentro de una aplicación web. En primer lugar, recibe las solicitudes (request) enviadas por un cliente y realiza el trabajo inicial para atenderla. Es el componente que interactúa con la capa controladora y la capa view. En segundo lugar, actúa como un transportador natural de datos entre el objeto request y los componentes de la capa view, esto gracias a las características de transferencia automática de datos que tiene struts 2 entre estos. Finalmente, apoya al framework determinando qué result será retornado en la respuesta que se genere a la solicitud realizada.

Se detalla, a continuación, un ejercicio, en el cual se apreciarán los principales componentes de la arquitectura MVC utilizando Struts 2.

1.1.2.1. Ejercicio 1: Funcionalidad de Logueo Versión 1 Se simulará la funcionalidad de logueo con los componentes básicos del framework Struts 2 y sin acceso a base de datos.

a) Paso 1: Copiar las principales librerías y archivos de configuración al proyecto web funcionalidadLogueov1_Inicial

1

2

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

13

Notas: 1) Observe que solo se puede copiar el archivo struts.xml dentro de la carpeta src, utilizando la vista Navigator. 2) Distinga las principales librerías y archivos de configuración en las ubicaciones correctas: librerías en la carpeta lib y archivo de configuración struts.xml en la carpeta src junto a los archivos fuente.

b) Paso 2: Registrar el filtro controlador de Struts 2 dentro del archivo web.xml <!-- registramos el filtro controlador de struts 2 --> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

c) Paso 3: Crear el primer componente Struts 2 de la aplicación, la clase LogueoAction

1

Notas: 1) Agregue el paquete aprendamos.java.action y, dentro de él, genere la clase LogueoAction. La clase LogueoAction debe contar con la siguiente lógica:

CIBERTEC

CARRERAS PROFESIONALES


14

package aprendamos.java.action; public class LogueoAction { private String usuario; private String clave;

public String getUsuario() { return usuario; } public void setUsuario(String usuario) { this.usuario = usuario; } public String getClave() { return clave; } public void setClave(String clave) { this.clave = clave; } public String execute(){ String vista="exito"; return vista; } }

d) Paso 4: Registrar la clase LogueoAction en el archivo struts.xml 1

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

<action name="logueo" class="aprendamos.java.action.LogueoAction" > <result name="error" <result name="exito" </action> </package>

>/logueo.jsp </result> >/bienvenida.jsp </result>

Notas: 1) El “alias” de la clase action es logueo; por lo tanto, debe modificar el archivo logueo.jsp. Ya no invocará a la clase LogueoServlet sino a LogueoAction.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

15

e) Paso 5: Ejecutar la aplicación web 1

Notas: 1) Se puede observar en el url que el alias invocado es logueo. Recuerde que en Struts 2 todas las solicitudes son atrapadas por el filtro controlador del framework. Éste invocará al action respectivo sobre la base del registro realizado en el archivo struts.xml. f) Paso 6: ¡Bien!, ha culminado la funcionalidad de logueo

versión 1

1.1.2.2. Ejercicio 2: Funcionalidad de Logueo Versión 2 Se efectúa la funcionalidad de logueo con los componentes básicos del framework e implementando los patrones de diseño DAO (Data Access Object), Service y Business Delegate.

a) Paso 1: Modificar la clase MySqlClienteDAO y verificar su correcta relación con las clases que implementan el patrón de diseño DAO.

CIBERTEC

CARRERAS PROFESIONALES


16

Dentro de la clase MySqlClienteDAO, debe modificar el método buscaPorUsuario. Complete el código con la lógica mostrada a continuación: //ejecutamos ResultSet rs=pst.executeQuery(); //si hay datos, recuperamos un regsitro if(rs.next()){ objClienteDTO = new ClienteDTO(); objClienteDTO.setUsuario(rs.getString(1)); objClienteDTO.setClave(rs.getString(2)); objClienteDTO.setNombre(rs.getString(3)); objClienteDTO.setSueldo(rs.getDouble(4)); objClienteDTO.setSexo(rs.getString(5)); objClienteDTO.setFecnac(rs.getDate(6)); } cn.close();

9 El patrón de diseño DAO (Data Access Object) permite que un componente pueda acceder a diferentes orígenes de datos de manera independiente y transparente. En este proyecto, se cuentan con componentes DAO para acceder al motor de base de datos MySql. Adicionalmente, se podrían contar con DAOs para acceder a otros orígenes de datos, tales como Oracle, Microsoft SQL Server, archivos XML, etc. 9 Por cada entidad dentro del modelo de datos, se debe crear un componente DAO.

Verifique si existe la interface ClienteDAO. Ésta debe ser implementada por la clase MySqlClienteDAO: public interface ClienteDAO {

public int registraCliente(ClienteDTO objCliente) throws Exception; public ClienteDTO buscaPorUsuario(String usuario) throws Exception; . . . }

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

17

9 Una interface permite exponer “al mundo” las operaciones de la clase que la implementa. Verifique si MySqlClienteDAO es retornado por la fábrica de DAOs para MySql:

public class MySqlDAOFactory extends DAOFactory { // Esta es una fabrica que crea DAOs especificos para Mysql

@Override public ClienteDAO getClienteDAO() { // TODO Auto-generated method stub return new MySqlClienteDAO(); }

Verifique si la clase MySqlClienteDAO ha sido “registrada” en la “fábrica de fábricas” DAOFactory:   public abstract class DAOFactory { public public public public public

static static static static static

final final final final final

int int int int int

MYSQL = 1; ORACLE = 2; DB2 = 3; SQLSERVER = 4; XML = 5;

1 // Existirá un método por cada DAO que pueda ser creado. // Ejemplo: //public abstract ArticuloDAO getArticuloDAO(); // registramos nuestros daos public abstract ClienteDAO getClienteDAO(); //public abstract ProductoDAO getProductoDAO();

public static DAOFactory getDAOFactory(int whichFactory){ switch(whichFactory){ case MYSQL: return new MySqlDAOFactory(); case XML: return new XmlDAOFactory(); case ORACLE: return new OracleDAOFactory();

CIBERTEC

CARRERAS PROFESIONALES


18

Notas: 1) El registro de la clase MySqlClienteDAO es la creaci贸n de un m茅todo abstracto en la clase DAOFactory que retorna a la interface que implementa MySqlClienteDAO.

b) Paso 2: Crear la clase LogueoService y la interface LogueoService_I

1

2 public class LogueoService implements LogueoService_I { // Referenciamos a la fabrica de daos para mysql DAOFactory fabrica = DAOFactory.getDAOFactory(DAOFactory.MYSQL); // Referenciamos al dao de la entidad cliente ClienteDAO objClienteDAO = fabrica.getClienteDAO();

public ClienteDTO validaUsuario(ClienteDTO cliente) throws Exception { // aqui podriamos tener mas logica return objClienteDAO.buscaPorUsuario(cliente.getUsuario()); } }

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

19

Notas: 1) Agregue el paquete aprendamos.java.action y dentro de él genere la clase LogueoAction. 2) Un servicio es un componente, que pertenece a la capa Model del patrón de diseño MVC. Representa, en la programación, el inicio de la lógica de negocio. Por cada caso de uso de sistema identificado en la aplicación, se debe implementar un servicio. Éste puede invocar a uno o más DAOs.

Debe “exponer” las operaciones de la clase LogueoService; por lo tanto, debe crear la interface LogueoService_I

public interface LogueoService_I { public abstract ClienteDTO validaUsuario(ClienteDTO cliente) throws Exception; }

c) Paso 3: Crear la clase PaqueteBusinessDelegate

1

CIBERTEC

CARRERAS PROFESIONALES


20

2 public class PaqueteBusinessDelegate { private PaqueteBusinessDelegate() { // TODO Auto-generated constructor stub } public static LogueoService_I getLogueoService(){ return new LogueoService(); } // agregar aqui mas llamadas a otros servicios

}

Notas: 1) Dentro del paquete aprendamos.java.service, genere la clase PaqueteBusinessDelegate. 2)

Por cada paquete de un modelo de análisis, se debe tener un componente BusinessDelegate. Esta clase será invocada por los actions y retornará componentes tipo Service.

d) Paso 4: Invocar los componentes de lógica de negocio, desde la clase LogueoService, y crear la sesión web.

Genere, dentro de la clase LogueoAction, el atributo mensaje para poder visualizar posibles “mensajes de error” en la capa de presentación. No debe olvidar crear los métodos setter y getter para el nuevo atributo.

public class LogueoAction {

private String usuario; private String clave; private String mensaje;

public String getMensaje() { return mensaje; } public void setMensaje(String mensaje) { this.mensaje = mensaje; }

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

21

Agregue la l贸gica que permitir谩 validar los datos ingresados y almacenarlos en la sesi贸n web.

public String execute(){ String vista="exito"; System.out.println("dentro de nuestro primer action"); System.out.println(this.getUsuario()); System.out.println(this.getClave()); // invocamos a nuestro servicio (logica de negocio) LogueoService_I logueoservice = PaqueteBusinessDelegate.getLogueoService();

ClienteDTO usuarioCandidato= new ClienteDTO(); usuarioCandidato.setUsuario(this.getUsuario());

ClienteDTO objUsuario=null; try { objUsuario = logueoservice.validaUsuario(usuarioCandidato); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if(objUsuario!=null){ if(objUsuario.getClave().equals(this.getClave())){ // creamos la sesion web al estilo struts 2 Map<String,Object> lasesion= ActionContext.getContext().getSession(); lasesion.put("b_usuario", objUsuario);

}else{ vista="error"; this.setMensaje( "Lo sentimos, la clave es incorrecta"); } }else{ vista="error"; this.setMensaje("Es una pena, el usuario no existe!"); } return vista; }

CIBERTEC

CARRERAS PROFESIONALES


22

Recuerde que debe utilizar Expression Language (EL) en el JSP logueo.jsp para visualizar el mensaje de error definido en la clase LogueoAction. <tr> <td class="error general"> <!-- podemos visualizar el mensaje de error usando EL --> ${requestScope.mensaje} </td> </tr>

Recuerde que debe utilizar Expression Language (EL) en el JSP bienvenida.jsp para visualizar los datos del cliente cargados en la sesión web.             </tr>   <tr>

<td class="error general"> <!-- podemos visualizar el mensaje de error usando EL --> ${requestScope.mensaje} </td>

e) Paso 5: Ejecutar la aplicación Primero, ingrese un usuario inválido.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

23

Luego, ingrese el usuario correcto, pero la clave equivocada.

Por último, ingrese los datos correctamente.    

¡Excelente!, ha culminado la funcionalidad de logueo versión 2

CIBERTEC

CARRERAS PROFESIONALES


24

1.1.3. Librerías de etiquetas de Struts 2 1.1.3.1. Ejercicio 1: Funcionalidad de Logueo Versión 3 Agregue una nueva funcionalidad al logueo implementado, a través del uso de archivos de recursos y nuevas características del framework Struts 2.

a) Paso 1: Definir el archivo de recursos para Struts 2 Se copia el archivo struts.properties dentro de la carpeta src del proyecto.

Se puede observar que, a través de la key struts.custom.i18n.resources, se define la ubicación del archivo de recursos.

struts.custom.i18n.resources=aprendamos.java.recursos.MisRecursos struts.ui.theme=simple struts.action.extension=action,,dudu

b) Paso 2: Agregar nuevas keys al archivo de recursos MisRecursos.properties Puede agregar las keys correspondientes a los mensajes de error del logueo.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

25

# Definiremos keys y sus respectivos valores # Una key es un identificador asociado a alguna descripcion #keys para el logueo : completar logueo.titulo = Pagina de Inicio - Que facil es JEE :):) logueo.mensaje.error.usuario=Lo sentimos, el usuario ingresado no existe :( logueo.mensaje.error.clave=Es una pena, la clave ingresada no

c) Paso 3: Referenciar las keys dentro de la clase LogueoAction Para poder referenciar las keys, la clase LogueoAction debe heredar de la clase ActionSupport. Esto permitirĂĄ incluir funcionalidad adicional dentro de la misma.

package aprendamos.java.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.LogueoService_I; import aprendamos.java.service.PaqueteBusinessDelegate; public class LogueoAction extends ActionSupport {

private String usuario; private String clave; private String mensaje;

Invoque el mĂŠtodo getText, heredado de la clase ActionSupport.

. . . }else{ vista="error"; this.setMensaje( this.getText( "logueo.mensaje.error.clave")); } }else{ vista="error"; this.setMensaje(this.getText("logueo.mensaje.error.usuario")) ; } . . .

CIBERTEC

CARRERAS PROFESIONALES


26

d) Paso 4: Modificar el JSP logueo.jsp Debe referenciar a la librerĂ­a de etiquetas de struts 2.

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

Transforme las etiquetas html en sus equivalentes de Struts 2.

<s:form action="logueo"

method="post"

>

<table > <tr class="etiqueta" > <td colspan="2" > <img alt="El loguito" src="imagenes/logo_tiny.png" </td> </tr> <tr class="etiqueta" > <td> <fmt:message key="logueo.usuario" /> </td> <td> <s:textfield name="cliente.usuario" /> </td> </tr>

>

<tr class="etiqueta" > <td > <fmt:message key="kclave" /> </td> <td> <s:password name="cliente.clave" /> </td> </tr> <tr> <td colspan="2" align="right" > <s:submit name="boton01" value="Ingresar" type="submit" /> </td> </tr> <tr> <td class="error general"> ${requestScope.mensaje} </td> </tr> <tr> <td > <fmt:message key="logueo.imagen" /> </td> </tr>

</table> </s:form> CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

27

9 Note que se han modificado los nombres de los campos usuario y clave por cliente.usuario y cliente.clave. e) Paso 5: Referenciar a los campos cliente.usuario y cliente.clave dentro de la clase LogueoAction Agregue el atributo cliente en la clase LogueoAction. public class LogueoAction extends ActionSupport {

private ClienteDTO cliente=null; public ClienteDTO getCliente() { return cliente; } public void setCliente(ClienteDTO cliente) { this.cliente = cliente; }

Modifique el mĂŠtodo execute. public String execute(){ String vista="exito"; System.out.println("dentro de nuestro primer action"); System.out.println(this.cliente.getUsuario()); System.out.println(this.cliente.getClave());

// invocamos a nuestro servicio (logica de negocio) LogueoService_I logueoservice = PaqueteBusinessDelegate.getLogueoService();

ClienteDTO usuarioCandidato= new ClienteDTO(); usuarioCandidato.setUsuario(this.getCliente().getUsuario());

ClienteDTO objUsuario=null; try { objUsuario = logueoservice.validaUsuario(usuarioCandidato); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); Notas: }

2

if(objUsuario!=null){

if(objUsuario.getClave().equals(this.getCliente().getClave())){ CIBERTEC

CARRERAS PROFESIONALES

1


28

1) Los datos son obtenidos a partir del nuevo atributo cliente. 2) Se obtienen nuevamente los datos a partir del atributo cliente. Esta vez invocando al método getCliente().

f)

Paso 6: Ejecutar la aplicación

Primero, ingrese un usuario inválido.

Luego, ingrese el usuario correcto, pero la clave equivocada.

Por último, ingrese los datos correctamente.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

29

g) Paso 7: ยกMuy buen trabajo!

CIBERTEC

CARRERAS PROFESIONALES


30

1.1.3.2. Ejercicio 2: Funcionalidad Registro de cliente Se implementa la funcionalidad indicada, haciendo uso de de las utilidades incluidas en el framework para procesar archivos (en el ejemplo la imagen del cliente) a través de un formulario HTML y gestionarlos dentro de la aplicación web implementada. a) Paso 1: Importar el proyecto FuncionalidadRegistraImagen_Inicial.war

web

1

Notas: 1) Note que, dentro del proyecto, cuenta con el script de base de datos FacilitoBaseDatos.sql. En él, se debe verificar que la tabla tbcliente cuenta con un tipo de dato adecuado para almacenar un archivo de cualquier modelo.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

31

b) Paso 2: Verificar que la tabla tbcliente cuente con un campo de tipo longblog

CREATE DATABASE IF NOT EXISTS facilito; USE facilito; --- Definition of table `tbcliente` -DROP TABLE IF EXISTS `tbcliente`; CREATE TABLE `tbcliente` ( `nombre` varchar(100) DEFAULT NULL, `sueldo` double DEFAULT NULL, `sexo` char(1) DEFAULT NULL, `fecnac` datetime DEFAULT NULL, `usuario` varchar(15) NOT NULL DEFAULT '', `clave` varchar(15) NOT NULL DEFAULT '', `foto` longblob DEFAULT NULL, PRIMARY KEY (`usuario`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

1

Notas: 1) Observe que, en el campo “foto”, se almacenará la imagen asociada al cliente que registrará en su aplicación web.

CIBERTEC

CARRERAS PROFESIONALES


32

c) Paso 3: Modificar el archivo nuevoCliente.jsp

Dentro de la página nuevoCliente.jsp, se debe modificar el formulario HTML. Complete el código con la lógica mostrada a continuación: <s:form action="ingresaCliente" method="post"

1

enctype="multipart/form-data"

>

<table> <tr class="titulo" > <td colspan="2" align="center" > Registro de Clientes </td> </tr> <tr class="control" > <td> <s:text name="key.cliente.nombre" /> </td> <td> <s:textfield name="cliente.nombre" /> </td> </tr>

. . .

. . . <tr class="control" > <td> Fotografía: </td> <td> <s:file name="cliente.foto" </tr> <tr class="control" > <td align="right" > <input type="submit" name="boton01" value="Registrar" > </td> </tr> </table> </s:form>

/>

2

</td>

Notas: 1) Debe utilizar el atributo enctype del formulario con el valor multipart/form-data. De esta manera,se habilita el formulario para soportar campos tipo File. 2) Agregue la etiqueta file de Struts 2., cuyo nombre es cliente.foto, es decir, hará referencia a un objeto de nombre cliente que cuente con un atributo llamado foto.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

33

d) Paso 4: Registrar el alias ingresaCliente en el archivo struts.xml

1

<action name="ingresaCliente" class="aprendamos.java.action.ClienteAction" method="registra" > <result name="exito"

>/listado.jsp</result>

</action>

Notas: 1) El alias ingresaCliente fue definido en el formulario de la página nuevoCliente.jsp. Note que al invocar este alias se ejecutará dentro de la clase ClienteAction el método registrar.

e) Paso 5: Crear el método registrar en la clase ClienteAction

La clase ClienteAction debe contar con la siguiente lógica:

package aprendamos.java.action; import java.util.List; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.ClienteService_I; import aprendamos.java.service.PaqueteBusinessDelegate; public class ClienteAction { // creamos un atributo de tipo Lista de Clientes ClienteDTO cliente; List<ClienteDTO> clientes;

...

CIBERTEC

CARRERAS PROFESIONALES

1


34

... 2

ClienteService_I servicioCliente = PaqueteBusinessDelegate.getClienteService();

// creamos el metodo registra public String registra(){ String vista="exito";

3 4

try { servicioCliente.registraElCliente(cliente); // lo retornado por el servicio lo asignamos al atributo de tipo Lista de clientes cliente.setNombre(""); clientes= servicioCliente. listaClientesPorNombre(cliente.getNombre()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return vista; }

Notas: 1) Se ha definido la variable cliente de tipo ClienteDTO. De manera automática, el Framework instancia el objeto y almacena en él los datos que llegan desde la página nuevoCliente.jsp. Note que en la página nuevoCliente.jsp todos los campos llevan como prefijo en el nombre la palabra cliente, la cual hace referencia a la variable definida en ClienteAction. 2) El objeto servicioCliente es un componente de la lógica de negocio y expone las operaciones que puede realizar la clase ClienteAction. 3) Note que el método registraCliente recibe como parámetro el objeto cliente. Dentro de él, deben existir los campos necesarios para poder gestionar la imagen del cliente seleccionada en la página nuevoCliente.jsp 4) Una vez registrado el nuevo cliente se “blanquea” el atributo nombre del objeto cliente y se invoca la funcionalidad de listado antes de retornar a la vista respectiva.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

f)

35

Paso 6: Modificar la clase ClienteDTO

La clase ClienteDTO debe contar con la siguiente lógica: public class ClienteDTO implements Serializable {

private static final long serialVersionUID = 1L; private private private private private private

1

String nombre; Date fecnac; String sexo; double sueldo; String usuario; String clave;

2

private File foto; private String fotoContentType; private String fotoFileName; private InputStream isFoto; public String getFotoContentType() { return fotoContentType; } public void setFotoContentType(String fotoContentType) { this.fotoContentType = fotoContentType; }

. . .

Notas: 1) Dado que en la página nuevoCliente.jsp se ha definido un campo tipo file con el nombre cliente.foto, es necesario definirlo en la clase ClienteDTO, de modo que se pueda recepcionar la imagen enviada desde el formulario. 2) Es necesario, también, por requerimiento del Framework, definir los campos fotoContentType y fotoFileName. Ambos se “cargarán” de manera automática y proporcionarán importante información relacionada con la variable foto. Adicionalmente, se define la variable isFoto de tipo InputStream, debido a que ésta será utilizada por el componente MySqlClienteDAO en el registro de la imagen en la tabla tbcliente.

CIBERTEC

CARRERAS PROFESIONALES


36

g) Paso 7: Modificar la clase ClienteService La clase ClienteService debe contar con la siguiente lógica en el método registraElCliente:

public int registraElCliente(ClienteDTO objCliente) throws Exception { // aqui agremos un poco de logica // como sabemos que el atributo isFoto esta llegando nulo // lo generamos a partir del atributo foto (de tipo File)

1

if(objCliente.getFoto()!=null){ InputStream tempo = new FileInputStream(objCliente.getFoto()); objCliente.setIsFoto(tempo); } return objClienteDAO.registraCliente(objCliente); }

Notas:

1) Si el cliente seleccionó en la página nuevoCliente.jsp una imagen, el atributo foto debe ser diferente del valor null. De ser el caso, se crea un objeto temporal de tipo InputStream en base al atributo foto. Luego, se asigna el objeto tempo al atributo isFoto (utilizado en la clase MySqlClienteDAO para grabar la imagen en la tabla tbcliente).

9 Recuerde que el método registraElCliente debe ser “expuesto” registrándolo en la interface ClienteService_I. La clase ClienteService implementa la interface ClienteService_I.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

37

h) Paso 8: Modificar la clase MySqlClienteDAO La clase MySqlClienteDAO debe implementar la siguiente lógica en el método registraCliente:

public int registraCliente(ClienteDTO objCliente) throws Exception{ int resultado =0; Connection cn = MySqlDBConn.obtenerConexion(); String sql = "insert into tbcliente(nombre,sueldo,sexo,fecnac," + "usuario,clave,foto) values (?,?,?,?,?,?,?)"; PreparedStatement pst = cn.prepareStatement(sql);

1

// asignamos valores a las interrogantes pst.setString(1, objCliente.getNombre()); pst.setDouble(2, objCliente.getSueldo()); pst.setString(3, objCliente.getSexo());

2

// no olvidemos insertar la fecha :) java.sql.Date bdfecha= new java.sql.Date(objCliente.getFecnac().getTime()); pst.setDate(4, bdfecha); pst.setString(5, objCliente.getUsuario()); pst.setString(6, objCliente.getClave()); pst.setBinaryStream(7, null,0); if(objCliente.getFoto()!=null){ pst.setBinaryStream(7, objCliente.getIsFoto(), objCliente.getIsFoto().available()); }

// ejecutamos la sentencia resultado = pst.executeUpdate(); cn.close(); return resultado; }

Notas: 1) Recuerde que para insertar una fecha en base de datos debe convertir las fechas de tipo java.util.Date al tipo java.sql.Date.

2) Por defecto, se asume que no insertará ninguna imagen en el campo foto:

CIBERTEC

CARRERAS PROFESIONALES


38

pst.setBinaryStream(7, null,0); Sin embargo, si el valor del atributo es diferente de null, registra la imagen, tomando como base al atributo de tipo InputStream isFoto: pst.setBinaryStream(7, objCliente.getIsFoto(), objCliente.getIsFoto().available());

9 El método available() de un objeto de tipo InputStream retorna la cantidad de bytes (el tamaño), en este caso, de la imagen a insertar en la tabla. De esta manera, se envía como tercer parámetro del método setBinaryStream().

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

i)

39

Paso 9: Ejecutar la aplicaci贸n web

Seleccione del listado de Clientes el enlace Nuevo Cliente:

CIBERTEC

CARRERAS PROFESIONALES


40

En la pantalla mostrada, ingrese los campos solicitados.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

41

Al hacer clic sobre el botรณn Registrar, se grabarรก un nuevo registro en la base de datos y se visualizarรก nuevamente el listado de Clientes.

CIBERTEC

CARRERAS PROFESIONALES


42

Se puede verificar el correcto registro de la imagen, utilizando la herramienta MySql Query Browser:

1

Notas: 1) Al hacer clic sobre la lupa, visualizará en una nueva ventana la imagen registrada en la tabla tbcliente.

j)

Paso 10: ¡Bien!, ha culminado la funcionalidad “registra imagen” exitosamente.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

43

1.1.4. Internacionalización – I18n Tradicionalmente, los desarrolladores de software se centran en construir aplicaciones que resuelvan en forma inmediata problemas de negocio. Mientras hacen eso es fácil y a veces necesario realizar asunciones acerca del lenguaje o lugar de residencia de los usuarios. En muchos casos, estas asunciones son válidas y no hay preguntas sobre quién será la audiencia. Sin embargo, es probable, alguna vez, que se deba reconstruir una aplicación, porque estas asunciones fueron incorrectas. Internacionalización (I18N) es el proceso de diseñar su software con soporte en tiempo real de múltiples lenguajes y regiones. Dada esta característica, no será necesario rediseñar nuestras aplicaciones cada vez que se necesite soporte para un nuevo lenguaje. Una aplicación que dice tener soporte para internacionalización debe contar con las siguientes características: • Puede soportar lenguajes adicionales sin requerir cambios adicionales de código. • Los elementos de texto, mensajes e imágenes son almacenados externamente al código fuente. • Dependencia culturales de datos, tales como fecha y hora, y valores decimales son correctamente formateados para el lenguaje del usuario y localización geográfica. • Caracteres no estándares son soportados. • La aplicación puede ser fácilmente adaptada a nuevos lenguajes y regiones.

Cuando se internacionaliza una aplicación, no se puede producirla para elegir qué opciones desea soportar. Se deben implementar todas ellas o el proceso colapsará. Si un usuario visita un sitio web y todos sus textos, imágenes y botones están en el lenguaje correcto, pero los números y fechas no son formateados correctamente, ésta será una experiencia desagradable para el usuario. Asegurar que una aplicación puede soportar múltiples lenguajes y regiones solo es el primer paso. Se deben crear versiones localizadas de la aplicación para cada lenguaje específico y región que debe soportar. Afortunadamente, aquí es donde los beneficios de I18N en la plataforma java se ejecutan. Para aplicaciones que están siendo apropiadamente internacionalizadas, todo el trabajo para soportar nuevos lenguajes o naciones, son externas al código fuente. Una clase locale es una región (usualmente geográfica, pero no necesariamente) que comparte personalizaciones, cultura y lenguaje. Aplicaciones que son escritas para una sola localización son comúnmente referenciadas como miopes. Localización (L10N) es el proceso de adaptar su aplicación, la cual ha sido internacionalizada apropiadamente con la específica. Para aplicaciones donde el soporte I18N no ha sido planeado o incorporado, esto usualmente significa cambios de texto, imágenes y mensajes que son incluidos dentro

CIBERTEC

CARRERAS PROFESIONALES


44

del código fuente. Después de los cambios aplicados, éste debe de ser recopilado. Imagine hacer eso cada vez para una nueva localización soportada. De acuerdo con Richard Gillam, miembro del Grupo de Tecnología Unicote (autor del diseño de muchas de las librerías Java para soporte I18N), los usuarios esperarán que los productos que utilizan trabajen para ellos en su lenguaje nativo. Se pueden obtener experiencias negativas si los usuarios no están satisfechos cuando las asunciones que se realizan son incorrectas. Se debe iniciar planificando, en forma temprana, el soporte para I18N en las aplicaciones.

1.1.4.1. Ejercicio 1: Funcionalidad Registra imagen con i18N Se agregará nueva funcionalidad al registro de imágenes implementado. La aplicación web soportará el uso de tres idiomas distintos.

a) Paso 1: Importar el proyecto FuncionalidadRegistraImagenI18N_Inicial.war

web

1

Notas: 1) Note que, dentro del proyecto, cuenta con el paquete aprendamos.java.recursos y dentro de él cuenta con tres archivos de recursos (archivos .properties) que soportan los

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

45

idiomas italiano (it), portugués (pt) y español. El primero está configurado en el archivo sin indicador de idioma. Note que los prefijos it y pt o cualquier otro que se desea usar deben ser códigos ISO 639-1.

b) Paso 2: Editar los archivos .properties. Se crearán, como ejemplos, las keys que serán utilizadas en la página bienvenida.jsp.

Defina las keys para el idioma portugués en el archivo MisRecursos_pt.properties

#keys para la pagina de bienvenida key.usuario = Usuário: key.nombre = Nome: key.fecnac = data de nascimento: key.sexo = sexo: key.saludo = Bem-vindo Caro usuário, seus dados são:

#keys para el menu menu.bienvenida = Ir à página inicial menu.logueo = Vá para a entrada menu.listado = Ir para a lista

CIBERTEC

CARRERAS PROFESIONALES


46

Defina las keys para el idioma italiano en el archivo MisRecursos_it.properties

#keys para la pagina de bienvenida key.usuario = Utente: key.nombre = Nome: key.fecnac = Data di Nascito: key.sexo = sesso: key.saludo = Benvenuto Caro utente, i dati sono:

#keys para el menu menu.bienvenida = Vai alla pagina di benvenuto menu.logueo = Ir al logueini menu.listado = Ir al listadini

Defina las keys para el idioma espaĂąol en el archivo MisRecursos.properties (archivo de recursos por defecto).

#keys para la pagina de bienvenida key.usuario = Usuario: key.nombre = Nombre: key.fecnac = Fecha de Nacimiento: key.sexo = Sexo: key.saludo= Bienvenido estimado usuario, sus datos son:

#keys para el menu menu.bienvenida = Ir a la pĂĄgina de Bienvenida menu.logueo = Ir al logueo menu.listado = Ir al listado

CARRERAS PROFESIONALES

CIBERTEC

1


DESARROLLO DE APLICACIONES WEB I

47

Notas: 1) El archivo de recursos por defecto es aquel que no tiene código ISO asociado a un idioma en particular. Cuando se seleccione en la aplicación web un idioma que no haya sido configurado en ningún archivo de recursos, automáticamente, struts 2 recupera las keys del archivo de recursos por defecto.

c) Paso 3: Modificar el archivo cabecera.jsp

<body class="titulo" > <img alt="" src="imagenes/logo.png" border="0" > <table> <tr><td> <a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=it"> <img src="imagenes/banderaItalia.png" alt="Italiana" border="0"> </a> </td> <td><a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=pt"> <img src="imagenes/BanderaBrasil.png" alt="Portugues" border="0"> </a> 2 </td> <td><a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=es"> <img src="imagenes/banderaPeru.png" alt="Español" border="0"> </a> </td> </tr> </table> </body>

Notas: 1) Struts 2 soporta cuenta con un parámetro especial llamado request_locale. Cuando se utiliza éste, de manera automática, se configura sul valor como el idioma actual de la aplicación web. 2) Es recomendable utilizar variables al referenciar cualquier recurso dentro de una aplicación web. En el ejemplo, en

CIBERTEC

CARRERAS PROFESIONALES

1


48

lugar de colocar el nombre de la aplicación web, se realiza lo siguiente: FuncionalidadRegistraImagenI18N_Inicial Se coloca un “expression language” equivalente:

${pageContext.request.contextPath}

d) Paso 4: Registrar el action a_bienvenida en el archivo struts.xml

. . . <package name="default" namespace="/" extends="strutsdefault"> 1

<action name="a_bienvenida" > <result > /bienvenida.jsp </result> </action> <action name="a_logueo" > <result > /logueo.jsp </action>

1 </result>

. . . Notas: 1) Note que el action a_bienvenida es solo un action de atajo que invoca automáticamente a la página bienvenida.jsp. Se puede crear dentro de la aplicación múltiples actions de atajo para invocar a través de links a las páginas JSP.

e) Paso 5: Recuperar las keys del menú y de la página de bienvenida, utilizando la etiqueta <s:text> de struts 2.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

49

Modifique el archivo menu.jsp

. . . <tr> <td class="control" > <s:a action="a_bienvenida"

> 1

<s:text name="menu.bienvenida" /> </s:a> </td> </tr> <tr> <td class="control" > <s:a action="a_logueo"

1

>

<s:text name="menu.logueo" /> </s:a> </td> </tr> <tr> <td class="control" > <s:a action="a_listado" > <s:text name="menu.listado" /> </s:a> </td> </tr> . . .

Notas: 1) Debe usar la etiqueta <s:text> para referenciar a las keys del archivo de recursos. Es importante recordar que para utilizar las etiquetas de struts 2 se debe referenciar la librerĂ­a, utilizando la siguiente directiva: <%@ taglib prefix="s" uri="/struts-tags" %>

CIBERTEC

CARRERAS PROFESIONALES


50

Modifique el archivo bienvenida.jsp

. . .

<table class="control" > <tr> <td colspan="2" > <s:text name="key.saludo" /> </td> </tr> <!--

recuperamos los atributos del usuario logueado utilizando EL (Expression Language) --> 1 <tr> <td><s:text name="key.usuario" /> </td> <td>${sessionScope.b_usuario.usuario}</td> </tr> <tr> <td> <s:text name="key.nombre" /> </td> <td>${sessionScope.b_usuario.nombre}</td> </tr> <tr> <td> <s:text name="key.fecnac" /> </td> <td>${sessionScope.b_usuario.fecnac}</td> </tr> <tr> <td> <s:text name="key.sexo" /> </td> <td>${sessionScope.b_usuario.sexo}</td> </tr> </table> . . .

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

f)

51

Paso 6: Ejecutar la aplicación web

Ingrese a la intranet a través de la página de logueo.

Se debe visualizar la pantalla de bienvenida y los enlaces a los idiomas definidos en la página cabecera.jsp. Seleccione la bandera italiana.

CIBERTEC

CARRERAS PROFESIONALES


52

Visualizará la siguiente pantalla con el menú y la bienvenida en idioma italiano. Seleccione la bandera de Brasil.

Se visualizará la siguiente pantalla con el menú y la bienvenida en idioma portugués. Finalmente, seleccione la bandera del Perú.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

53

Se visualizará la siguiente pantalla con el menú y la bienvenida en idioma castellano.

g) Paso 7: ¡Bien!, ha culminado la funcionalidad “registra imagen con I18n” exitosamente.

CIBERTEC

CARRERAS PROFESIONALES


54

1.2 Acceso optimizado a base de datos y otras características Struts 2

1.2.1. Uso de un Pool de conexiones para acceso a base de datos Un Pool de Conexiones (jdbc) es un conjunto de conexiones preinstanciadas que serán "prestadas" a los threads (hilos) de ejecución a medida que estos lo requieran para que la usen y luego la devuelvan al pool. En el caso de las aplicaciones abiertas en Internet o con gran cantidad de usuarios potenciales, el análisis es el mismo. El recurso es la conexión a la base de datos. Se tendrá un conjunto de “n” conexiones para asignarlas (o prestarlas) a los hilos que lo requieran. Lo recomendable al usar un Pool de Conexiones es que se optimice las consultas a la base de datos para tener mayor rapidez.

1.2.1.1. Ejercicio 1: Funcionalidad Registra Imagen “Pool” Se implementa la funcionalidad indicada haciendo uso de un pool de conexiones de MySql para optimizar el acceso a base de datos.

a) Paso 1: Importar el proyecto FuncionalidadRegistraImagenPool_Inicial.war

CARRERAS PROFESIONALES

web

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

55

1

Notas: 1) Observe que, dentro del proyecto, cuenta en la carpeta META-INF con el archivo context.xml. En él, se debe crear la configuración del pool de conexiones que utilizará para acceder a una base de datos.

CIBERTEC

CARRERAS PROFESIONALES


56

b) Paso 2: Editar el archivo context.xml y configurar el pool de conexiones.

<?xml version="1.0" encoding="UTF-8"?> --> <!-- Este es un comentario <!-- la etiqueta Context representa una zona de memoria que se crea cuando levantamos la aplicacion web. Esta zona de memoria estara "viva" mientras no reiniciemos la aplicacion web -->

<Context path="/jee-web"

>

<!-- registramos un recurso en esta zona de memoria. En este caso un pool de conexiones --> <Resource name="jdbc/sisepuede" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="root" password="" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/facilito"/>

1 2

3

</Context>

Notas: 1) jdbc/sisepuede es el nombre del pool de conexiones que utilizará para referenciar a la base de datos. 2) El número máximo de conexiones activas es 100 en el ejemplo. Este valor debe ser calculado para cada aplicación web sobre la base de la “experiencia” y el tráfico que normalmente se soporte. En algunos casos, se tendrá la necesidad de incrementar o redecir este valor por defecto. 3) El máximo tiempo de espera, 10000, está expresado en milisegundos. En este ejemplo, se esperará, como máximo, 10 segundos para obtener una conexión disponible (de las 100 existentes). De no conseguirla, se produciría un error.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

57

c) Paso 3: Modificar el archivo MySqlDbConn.java

package aprendamos.java.util; // Esta clase nos retornara una conexion a base de datos import java.sql.*; import javax.naming.*; import javax.sql.*;

1 2

public class MySqlDBConn { // Utilizaremos mas bien un pool de conexiones // creamos el metodo que nos permite obtener una conexion . . .

Notas: 3) Debe importar el paquete javax.naming.*, ya que en él se encuentran las clases para utilizar JNDI y acceder al pool de conexiones. 4) Debe importar el pauete javax.sql.* debido a que dentro de él se encuentra la clase DataSource. Ésta representa un pool de conexiones en java.

CIBERTEC

CARRERAS PROFESIONALES


58

. . . public static Connection obtenerConexion(){ // 1. Para referenciar al pool creamos un contexto JNDI // Java Naming and Directory Interface Connection cn=null; try { // creamos el contexto JNDI Inicial, JDNI valida los nombres , utiliza la infor de META INF para hacer un pool de conexiones., JNDI maneja nombres y objetos Context ctx = new InitialContext(); // ahora vamos a ubicar un nombre dentro // de este contexto, para ello usamos el // famoso metodo lookup. //Base standar JND String raizContexto ="java:comp/env/";

1

// obtenemos a traves de su nombre a nuestro // pool de conexiones DataSource ds=

2

(DataSource)ctx.lookup(raizContexto+"jdbc/sisepuede"); // le pedimos al pool que nos de una conexion cn = ds.getConnection(); System.out.println( "Mision cumplida, hemos obtenido la conexion del pool");

} catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return cn; }

Notas: 1) El nombre del contexto JNDI por default es java:comp/env. Todas las denominaciones de objetos JNDI (como nuestro pool), se crean debajo de este nombre raíz. Por lo tanto, para referenciar al pool, se pasar primero por el nombre raíz. 2) A través del método lookup y utilizando el nombre raíz del contexto, se referencia al pool de conexiones: jdbc/sisepuede.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

59

Se obtiene un objeto de tipo DataSource que representa el pool almacenado en memoria.

d) Paso 4: Copiar el conector de mysql dentro de la carpeta lib del servidor de aplicaciones TomCat

1

Notas: 1) Este paso es necesario debido a que es el servidor Tomcat y no la aplicaci贸n web, quien solicita al servidor de base de datos las conexiones (en el ejemplo cien), que ser谩n almacenadas en la memoria del servidor y que juntas constituyen el pool de conexiones.

CIBERTEC

CARRERAS PROFESIONALES


60

e) Paso 5: Ejecutar la aplicación web

Ingrese a la intranet a través de la página de logueo.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

61

Debe visualizar la pantalla de bienvenida con los datos del usuario logueado.

También, se visualizará en la consola de Eclipse los mensajes del Logueo y el que se colocó en la clase MySqlDbConn: misión cumplida, se ha obtenido la conexión del pool.

CIBERTEC

CARRERAS PROFESIONALES


62

f)

CARRERAS PROFESIONALES

Paso 6: ¡Bien!, ha culminado la funcionalidad “registra imagen pool” exitosamente.

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

63

1.2.2. Librerías de etiquetas de Struts 2. Principales componentes Dentro de la familia de nuevas etiquetas de Struts 2, es importante destacar que, en esta versión, todas las etiquetas básicas del framework se encuentran en una sola librería, la cual es referenciada en un JSP de la siguiente manera: <%@ taglib prefix="s" uri="/struts-tags" %> Se detalla, a continuación, ejercicios de aplicación en los que se utilizan las principales etiquetas de Interface de usuario y datos de Struts 2: 9 <s:url> 9 <s:action> 9 <s:form>

1.2.2.1. Ejercicio 2: Funcionalidad carga datos del Cliente Se implementa la funcionalidad indicada haciendo uso de las utilidades incluidas en el Framework para procesar archivos (en el ejemplo la imagen del cliente) a través de un formulario HTML y el uso de un Action de Struts 2 que utiliza un nuevo tipo de Result: stream.

a) Paso 1: Importar el proyecto proyecto web FuncionalidadCargaDatosCliente_Inicial.war

1

CIBERTEC

CARRERAS PROFESIONALES


64

Notas: 1) Debe modificar la pรกgina listado.jsp para agregar un enlace que permita visualizar los datos de un cliente en particular.

b) Paso 2: Modificar el archivo listado.jsp Dentro de la pรกgina listado.jsp, debe crear un nuevo enlace para visualizar los datos del cliente seleccionado. Complete el cรณdigo con la lรณgica mostrada a continuaciรณn:

. . . 1

<td align="center" > <s:url id="carga" action="cargaModificaCliente" > <s:param name="usuario" > ${elcli.usuario} </s:param> </s:url> <a

href="${carga}" >

M </a>

</td>

. . .

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

65

2

Notas: 1) Utilizando la etiqueta <s:url > defina un enlace que permitirรก invocar al alias cargaModificaCliente. Adicionalmente, determine el parรกmetro usuario utilizando la etiqueta <s:param>. Su valor es asignado usando el siguiente expression language (EL): ${elcli.usuario}

2) Culminado el cambio en listado.jsp, visualizarรก el enlace, tal como se muestra en la pantalla previa.

CIBERTEC

CARRERAS PROFESIONALES


66

c) Paso 3: Registrar el alias cargaModificaCliente en el archivo struts.xml

<action name="cargaModificaCliente" class="aprendamos.java.action.ClienteAction" method="cargaModifica" >

1

<result name="exito" >/modificaCliente.jsp </result> </action>

Notas: 1) El alias cargaModificaCliente fue referenciado en el enlace definido para modificar (M) de la página listado.jsp. Note que al invocar este alias se ejecutará dentro de la clase ClienteAction el método cargaModifica.

d) Paso 4: Crear el método cargaModifica en la clase ClienteAction

La clase ClienteAction debe contar con la siguiente lógica:

package aprendamos.java.action; import java.util.List; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.ClienteService_I; import aprendamos.java.service.PaqueteBusinessDelegate;

1

public class ClienteAction { // creamos un atributo de tipo Lista de Clientes ClienteDTO cliente; List<ClienteDTO> clientes; String usuario;

...

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

67

... public String cargaModifica(){ String vista="exito"; try {

2

cliente= servicioCliente.buscaClientePorUsuario( this.getUsuario());

} catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }

return vista;

3

}

...

Notas: 1) Se ha definido la variable usuario de tipo String. Se definen también los métodos setUsuario() y getUsuario(), respectivamente. De manera automática, el Framework instancia el objeto y almacena en éste el parámetro usuario, que llega desde la página listado.jsp. . 2) Note que el método buscaClientePorUsuario recibe como parámetro la variable usuario y retorna un objeto de tipo ClienteDTO que es asignada a la variable cliente. 3) Luego, se retorna a la vista respectiva, es decir, se invocará a la página modificaCliente.jsp

CIBERTEC

CARRERAS PROFESIONALES


68

e) Paso 5: Verificar la clase MySqlClienteDAO La clase MySqlClienteDAO debe implementar la siguiente lógica en el método buscaPorUsuario:

public ClienteDTO buscaPorUsuario(String usuario) throws Exception{ ClienteDTO objClienteDTO=null;

1

Connection cn = MySqlDBConn.obtenerConexion(); //definimos la sentencia String sql="select usuario,clave,nombre,sueldo,sexo,fecnac,foto " + " " + "from tbcliente where usuario = ?"; //la preparamos PreparedStatement pst=cn.prepareStatement(sql); //asignamos valores a las interrogantes pst.setString(1,usuario);

2

//ejecutamos ResultSet rs=pst.executeQuery(); //si hay datos, recuperamos un regsitro if(rs.next()){ objClienteDTO = new ClienteDTO(); objClienteDTO.setUsuario(rs.getString(1)); objClienteDTO.setClave(rs.getString(2)); objClienteDTO.setNombre(rs.getString(3)); objClienteDTO.setSueldo(rs.getDouble(4)); objClienteDTO.setSexo(rs.getString(5)); objClienteDTO.setFecnac(rs.getDate(6)); objClienteDTO.setIsFoto(rs.getBinaryStream(7)); } cn.close(); return objClienteDTO; }

Notas: 1) Note que se obtiene el campo de tipo longblob foto. 2) El campo foto es asignado al atributo isFoto del objeto objClienteDTO. Este atributo es de tipo InputStream, por ello, debe ser recuperado con el método getBinaryStream del objeto ResultSet rs: rs.getBinaryStream(7)

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

f)

69

Paso 6: Ejecutar la aplicaci贸n web

Seleccione del listado de Clientes el enlace M asociado a cualquiera de los clientes listados:

1

Notas: 1) Enlace para visualizar los datos del cliente y, opcionalmente, modificarlos.

CIBERTEC

CARRERAS PROFESIONALES


70

En la pantalla mostrada, se visualizarán los datos asociados al cliente seleccionado. Sin embargo, no reconoce aún la fotografía.

g) Paso 7: ¡Bien!, ha culminado la primera parte de la funcionalidad “carga imagen”

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

71

h) Paso 8: Modificar la página modificaCliente.jsp

Dentro de la página modificaCliente.jsp debe utilizar la etiqueta HTML <img> para visualizar la fotografía asociada al cliente mostrado:

. . . <tr class="control" > <td> Fotografía: </td> <td> <s:file name="cliente.foto" /> <td> <img alt="Fotografia del Cliente:) "

</td>

1

src="cargaImagenCliente?usuario=${cliente.usuario}" /> </td> </tr>

. . .

Notas: 1) Note cómo en el atributo src de la etiqueta <img> se hace referencia al alias cargaImagenCliente. Se envía adicionalmente el parámetro usuario con el valor ${cliente.usuario}.

CIBERTEC

CARRERAS PROFESIONALES


72

i)

Paso 9: Registrar el alias cargaImagenCliente en el archivo struts.xml

1

<action name="cargaImagenCliente" class="aprendamos.java.action.ImagenAction" method="recuperaImagenCliente" > <result name="exito" type="stream" >

2

<!-- en inputName colocamos el nombre del atributo del action que permitira generar el flujo (stream) --> <param name="inputName">imagenClienteRecuperada</param>

3

</result> </action>

Notas: 1) El alias cargaImagenCliente fue referenciado en la etiqueta <img> de la página modificaCliente.jsp. Note que al invocarlo se ejecutará dentro de la clase ImagenAction el método recuperaImagenCliente. 2) Se utiliza un nuevo tipo de result: stream. A través de él, la etiqueta <img> de la página modificaCliente.jsp visualizará la imagen a partir de un campo de tipo InputStream.

3) El campo imagenClienteRecuperada es el valor asociado al parámetro del result: inputName. Éste debe ser de tipo InputStream y estar definido en el action ImagenAction.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

j)

73

Paso 10: Crear el m茅todo recuperaImagenCliente en la clase ImagenAction

La clase ImagenAction debe contar con la siguiente l贸gica:

package aprendamos.java.action; import java.io.*; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.ClienteService_I; import aprendamos.java.service.PaqueteBusinessDelegate; public class ImagenAction {

1

String usuario; InputStream imagenClienteRecuperada;

...

... public String recuperaImagenCliente(){ String vista="exito"; try { ClienteDTO cli=

2

servicioCliente.buscaClientePorUsuario(usuario); // del objeto cli solo nos importa la foto como InputStream // recuperamos ese atributo y lo asignamos al campo // imagenClienteRecuperada this.imagenClienteRecuperada = cli.getIsFoto(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return vista; }

...

CIBERTEC

CARRERAS PROFESIONALES

3


74

Notas: 1) Se ha definido la variable imagenClienteRecuperada de tipo InputStream. Ésta es referenciada en el archivo struts.xml, en el registro del action ImagenAction. 2) El método buscaClientePorUsuario retorna un objeto de tipo ClienteDTO que es asignado a la variable cli. 3) Se invoca el método getIsFoto() de la variable cli para obtener la imagen recuperada de base de datos y asignarla a la imagenClienteRecuperada.

k) Paso 11: Ejecutar la aplicación web Seleccione, nuevamente, del listado de Clientes el enlace M asociado a cualquiera de los clientes listados:

1

Notas: 1) Enlace para visualizar los datos del cliente y, opcionalmente, modificarlos.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

75

En la pantalla mostrada, se visualizarán los datos asociados al cliente seleccionado. En esta oportunidad, sí visualizará la fotografía asociada al cliente.

l)

CIBERTEC

Paso 12: ¡Muy Bien!, ha culminado exitosamente la funcionalidad completa “carga imagen”.

CARRERAS PROFESIONALES


76

1.2.3. Patrón Composite View – Struts 2 Tiles Al momento de crear el diseño de un sitio web típico, éste puede sufrir muchos cambios durante su ciclo de vida. Utilizar diseños y gestores de diseño puede ayudar a organizar las diferentes partes de un JSP de modo que éstos se puedan alterar con un mínimo impacto para el resto de la aplicación. Surge, de esta manera, el patrón de diseño Composite View, el cual permite, de manera eficiente y escalable, gestionar diversos diseños para un sitio web. Desafortunadamente, la tecnología JSP no proporciona ningún soporte directo para diseños o gestores de diseño, es por ello que surgen librerías en el mercado que pueden ser utilizadas para mejorar la estructura de nuestras aplicaciones web. Se muestra, a continuación, a través de un ejercicio, la configuración y uso de la librería Tiles. Ésta es de código abierto e implementa el patrón Composite View.

1.2.3.1. Ejercicio 1: Mantenimiento Completo con Tiles Sobre un mantenimiento completo e implementado con Struts 2, se harán las modificaciones necesarias para implementar el patrón Composite View. Para ello, se utilizará el framework Tiles y se integrará a la aplicación web construida sobre Struts 2.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

77

a) Paso 1: Importar el proyecto web MantenimientoTiles_Inicial.war

1

2

3

4

Notas: 1) En general, las páginas JSP de la aplicación se encontrarán dentro de carpetas específicas. En este ejemplo, se cuenta con dos tipos: •

CIBERTEC

Páginas. Para todas aquellas de la aplicación web.

CARRERAS PROFESIONALES


78

Plantillas. Para las diferentes plantillas tiles sobre las cuales se distribuirán las páginas de la aplicación web.

2) Para utilizar Tiles e integrarlo a struts 2, es necesario contar con las librerías de Tiles y el plug in de Struts 2 para ésta. 3) El archivo de configuración de tiles es tiles.xml y debe copiarse por defecto en la carpeta WEB-INF de la aplicación web. 4) No todos los archivos JSP deben, necesariamente, estar dentro de una carpeta. En el ejemplo, la página logueo.jsp mantiene su ubicación original: dentro de la carpeta WebContent.

b) Paso 2: Modificar el archivo web.xml Se deben agregar en el archivo web.xml las siguientes etiquetas:

<!-- registramos e l listener de strtus 2 titles --> <listener> <listener-class> org.apache.struts2.tiles.StrutsTilesListener </listener-class> </listener>

1

...

Notas: 1) Debe agregar el listener de Tiles para struts 2.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

79

c) Paso 3: Modificar el archivo struts.xml

<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd"> <tiles-definitions> <definition name="d_bienvenida" template="/plantillas/diseno01.jsp"> <put-attribute <put-attribute <put-attribute <put-attribute

1 name="menu" value="/paginas/menu.jsp" /> name="pie" value="/paginas/pie.jsp" /> name="cabecera" value="/paginas/cabecera.jsp" /> name="body" value="/paginas/bienvenida.jsp" />

</definition> <definition name="d_listado" extends="d_bienvenida"> <put-attribute name="body" value="/paginas/listado.jsp" /> </definition> <definition name="d_nuevoCliente" extends="d_bienvenida"> <put-attribute name="body" value="/paginas/nuevoCliente.jsp" /> </definition> ...

3

Notas: 1) Debe crear definiciones de Tiles. Ésta determina qué componentes (JSPs normalmente) se despliegan sobre una plantilla en particular. En el ejemplo, el definition d_bienvenida referencia a la plantilla diseno01.jsp, 2) Un definition puede ser heredado. De esta manera, solo es necesario “sobre escribir” los puts que queramos modificar. En el ejemplo, el definition d_listado hereda del definition d_bienvenida. 3) Note que los puts dentro de los definitions están referenciando a páginas JSP dentro de la carpeta páginas. Ésta debe existir y ahí deben encontrarse las páginas referenciadas.

CIBERTEC

CARRERAS PROFESIONALES

2


80

d) Paso 4: Modificar el archivo struts.xml

... <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="false" /> <package name="default" namespace="/" extends="tiles-default"> <!-- creamos un action de atajo --> <action name="a_nuevoCliente" > <result type="tiles"> d_nuevoCliente </action>

</result> 2

<action name="a_bienvenida" > <result type="tiles"> d_bienvenida </action>

</result> 3

<action name="a_logueo" > <result > /logueo.jsp </action>

</result>

<action name="a_listado" > <result type="tiles"> d_listado </action>

</result>

<!-- registramos nuestro primer action --> <action name="logueo" class="aprendamos.java.action.LogueoAction" > <result name="error" >/logueo.jsp </result> <result name="exito" type="tiles"> d_bienvenida

</result>

</action> ...

Notas: 1) Para trabajar con Tiles y struts 2, es obligatorio heredar del paquete tiles-default. 2) Cada <result> de un action, ya no invoca directamente a una pรกgina JSP, sino, mรกs bien, a un definition de tiles. 3) Para que un <result> pueda invocar a un definition de tiles es necesario indicar en su atributo type el valor tiles.

CARRERAS PROFESIONALES

CIBERTEC

1


DESARROLLO DE APLICACIONES WEB I

81

e) Paso 5: Crear el archivo diseno01.jsp

1

Notas: 1) El archivo debe ser creado tal como se referenci贸 en el archivo tiles.xml, es decir, dentro de una carpeta llada plantillas.

CIBERTEC

CARRERAS PROFESIONALES


82

f)

Paso 6: Modificar el archivo diseno01.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 1 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-88591"> <title>Insert title here</title> </head> <body> <!-- en esta plantilla definimos el orden de distribucion de los puts del definition --> <table> <tr> <td colspan="2"><tiles:insertAttribute /></td> </tr> <tr> <td><tiles:insertAttribute name="menu" <td><tiles:insertAttribute name="body" </tr> <tr> <td colspan="2"><tiles:insertAttribute </tr> </table>

name="cabecera"

2

/></td> /></td>

name="pie" /></td>

</body> ...

Notas: 1) Para poder utilizar las etiquetas de tiles dentro de la página JSP, es necesario referenciar a la librería de etiquetas tags-tiles. 2) Note cómo se ha creado una tabla con filas y columnas, dentro de las cuales, haciendo uso de la etiqueta <tiles:insertAttribute>, se insertan los diferentes puts definidos en el archivo tiles.xml.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

83

g) Paso 7: Copiar las pรกginas JSP dentro de la carpeta pรกginas

1

Notas: 1) Tal como se indicรณ en el archivo tiles.xml, las pรกginas JSP deben estar dentro de una carpeta denominada pรกginas.

CIBERTEC

CARRERAS PROFESIONALES


84

h) Paso 8: Eliminar las directivas <include> de todas las páginas JSP.

<table> <tr> <td colspan="2" align="center" > <!-- aqui va la cabecera --> <jsp:include page="cabecera.jsp"

1

/>

</td> </tr> <tr>

<td > <!-- aqui va el menu --> <jsp:include page="menu.jsp"

/>

</td> <!-- aqui va el cuerpo --> <td > ...

Notas: 1) Dado que ahora se trabajará con Tiles, ya no es necesario tener directivas include dentro de los JSPs. Importante: De dejarlas, se duplicaría la implementación del patrón de diseño Composite View.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

i)

85

Paso 9: Ejecutar la aplicación web

Ingrese a la intranet a través de la página de logueo.

CIBERTEC

CARRERAS PROFESIONALES


86

Visualizará la pantalla de bienvenida de la aplicación

j)

CARRERAS PROFESIONALES

Paso 10: ¡Bien!, ha culminado “Mantenimiento con Tiles” exitosamente.

la

funcionalidad

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

87

Resumen Las etiquetas de struts 2 se encuentran agrupadas dentro de una sola librerĂ­a: <%@ taglib prefix="s" uri="/struts-tags" %>

Las etiquetas de struts 2 son parte de la capa de presentaciĂłn dentro de una arquitectura MVC. Con Tiles, se puede, fĂĄcilmente, cambiar de una estructura de aplicaciĂłn a otra. A travĂŠs de ĂŠste, Ăşnicamente de plantillas, permite tener mayor flexibilidad al momento de una posible migraciĂłn. Si desea saber mĂĄs acerca de estos temas, puede consultar las siguientes pĂĄginas:  http://struts.apache.org/2.x/index.html AquĂ­ encontrarĂĄ importante documentaciĂłn oficial y ejemplos de uso del framework Struts 2  http://struts.apache.org/1.x/struts-tiles/ AquĂ­ encontrarĂĄ documentaciĂłn oficial sobre el uso de plantillas Tiles dentro de una aplicaciĂłn implementada con el framework Struts. TambiĂŠn, encontrarĂĄ referencias para utilizar Tiles independientemente de Struts: Tiles 2.

CIBERTEC

CARRERAS PROFESIONALES


88

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

89

UNIDAD DE APRENDIZAJE

2

PERSISTENCIA DE DATOS – FRAMEWORK IBATIS LOGRO DE LA UNIDAD DE APRENDIZAJE •

Al finalizar la unidad, los alumnos, utilizando el frameworks IBATIS, implementan la capa de persistencia de datos y la integran con el framework Struts 2.

TEMARIO 2.1 Tema 3 : Introducción a IBATIS 2.1.1.

: IBATIS – Introducción

2.1.2.

: Operaciones básicas de acceso a base de datos con IBATIS

2.2 Tema 4 : Otras operaciones con IBATIS 2.2.1.

: Otras operaciones y características de IBATIS

2.2.2.

: Tópicos avanzados de IBATIS e Integración con Struts 2

ACTIVIDADES PROPUESTAS •

CIBERTEC

Los alumnos implementan una aplicación web básica, utilizando las principales características del framework MVC Struts 2 y el framework IBATIS.

CARRERAS PROFESIONALES


90

2.1 Introducción a IBATIS 2.1.1. IBATIS - Introducción Ibatis es un framework (marco de trabajo) de código abierto basado en capas desarrollado por Apache Software Foundation, que se ocupa de la capa de Persistencia (se sitúa entre la lógica de Negocio y la capa de la Base de Datos). Puede ser implementado en Java y .NET (también existe un port para Ruby on Rails llamado RBatis). Ibatis asocia objetos de modelo (JavaBeans) con sentencias SQL o procedimientos almacenados mediante archivos XML, simplificando la utilización de bases de datos. Dentro de sus principales características se destacan: A. Es posible subdividir la capa de persistencia en tres subcapas: • La capa de abstracción será la interfaz con la de la lógica de negocio, haciendo las veces de fachada (Patrón Facade) entre la aplicación y la persistencia. Se implementa de forma general, mediante el patrón Data Access Object (DAO) y, particularmente en Ibatis, se implementa utilizando su framework DAO (ibatis-dao.jar). • La capa de framework de persistencia será el interfaz con el gestor de Base de Datos, ocupándose de la gestión de los datos mediante un API. Normalmente, en Java, se utiliza JDBC. Ibatis utiliza su framework SQL-MAP (ibatis-sqlmap.jar). • La capa de driver se ocupa de la comunicación con la propia base de datos, utilizando uno específico para la misma.

B. Toda implementación de Ibatis incluye los siguientes componentes: • Data Mapper proporciona una forma sencilla de interacción de datos entre los objetos Java y .NET y bases de datos relacionales. • Data Access Object es una abstracción que oculta la persistencia de objetos en la aplicación y proporciona un API de acceso a datos al resto.

El marco de trabajo SQL Maps es muy tolerante, tanto con las malas implementaciones de los modelos de datos como con los modelos de objetos.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

91

A pesar de ello, es muy recomendable que se usen las mejores prácticas, tanto cuando se diseñe la base de datos (normalización apropiada, etc.) como el modelo de objetos. Al hacer esto, se garantizará un mejor rendimiento y un diseño más claro.

2.1.1.1. Ejercicio 1: Funcionalidad IBATIS - Introducción Se implementará una aplicación web con los componentes básicos para el correcto funcionamiento del framework IBATIS. a) Paso 1: Importar el archivo FuncionalidadIbatisIntro_Inicial.war

1

Notas: 1) Observe que debe contar con las librerías básicas de IBATIS para integrar el framework a su aplicación web.

CIBERTEC

CARRERAS PROFESIONALES


92

b) Paso 2: Copiar los archivos de configuración y la clase UtilSqlConfig

1

2

Notas: 1) SqlMapConfig.xml es el archivo de configuración por excelencia de IBATIS. En él, se define, por ejemplo, el pool de conexiones a utilizar y otros archivos XML (llamados SqlMaps), que serán referenciados en la aplicación web. En el ejemplo, se muestran dos archivos SqlMaps: Cliente.xml y Producto.xml. (Por cada entidad del modelo de datos, normalmente se tendrá un SqlMap).

2) UtilSqlConfig permite tener una representación en java como objeto del archivo SqlMapConfig.xml.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

93

c) Paso 3: Modificar el archivo SqlMapConfig.xml

<sqlMapConfig> <!-- referenciamos a nuestro pool de conexiones, archivo de confiracion por excelncia de IBatis --> <transactionManager type="JDBC"> <dataSource type="JNDI"> <property name="DataSource" value="java:comp/env/nomerindo" /> </dataSource> </transactionManager>

1

<!-- registramos nuestros SqlMaps. Normalmente por cada entidad tendremos un SqlMap, tener cuidado estos archivos como cualquierr refrerncia de xml de be existir --> <sqlMap resource="aprendamos/java/ibatis/Cliente.xml" /> <sqlMap resource="aprendamos/java/ibatis/Producto.xml"/> <!-- podemos registrar muchos mas sqlmaps --> </sqlMapConfig> ...

Notas: 1) A través de la etiqueta <transactionManager>, se define, en IBATIS, el pool de conexiones, que se utilizará para acceder a un origen de datos. En el ejemplo, el pool se llama: nomerindo. 2) A través de la etiqueta <sqlMap>, se referencia a los archivos XML, que contienen las sentencias SQL para operar sobre las entidades que referencian. En el ejemplo, se referencian los archivos XML Cliente y Producto.

CIBERTEC

CARRERAS PROFESIONALES

2


94

d) Paso 4: Modificar la clase UtilSqlConfig

import java.io.Reader; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; // Esta clase retorna un objeto que representa el archivo // SqlMapConfig.xml. Este es el principal archivo de // cofiguracion de ibatis

1

//Permite representa sqlMapConfig como un objeto public class UtilSqlConfig { private static final SqlMapClient sqlMap; static { try { String resource = "aprendamos/java/ibatis/SqlMapConfig.xml"; Reader reader = Resources.getResourceAsReader(resource); //Este objeto presenta al SQLmApConfig.xml estos es lo que se trata de hacer sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException( "Error inicializando la clase UtilSqlConfig class. Cause: " + e); } } public static SqlMapClient getSqlMapInstance() { return sqlMap; } } ...

CARRERAS PROFESIONALES

CIBERTEC

2


DESARROLLO DE APLICACIONES WEB I

95

e) Paso 5: Modificar el archivo Cliente.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlMap namespace="Cliente"> <!-- Referencia al DTO --> <typeAlias alias="cli" type="aprendamos.java.bean.ClienteDTO" /> <resultMap

<result <result <result <result <result <result <result </resultMap>

class="cli" id="clienteRes"

>

1

2

property="nombre" column="nombre" /> property="sueldo" column="sueldo" /> property="sexo" column="sexo" /> property="fecnac" column="fecnac" /> property="usuario" column="usuario" /> property="clave" column="clave" /> property="laFoto" column="foto" />

<!-- Definimos un operacion , el dao llamara a las operaciones por su ID --> <select id="ibatis_logueo" parameterClass="java.lang.String" resultMap="clienteRes"> select usuario,clave,nombre,sueldo,sexo,fecnac,foto from tbcliente where usuario = #value#; </select> ...

Notas: 1) A través de la etiqueta <typeAlias>, es posible crear diversos alias de clases java para ser usados dentro del archivo XML. 2) La etiqueta <resultMap> es utilizada cuando los nombres de las columnas de una tabla no coinciden con los atributos de la clase que recibirá los datos de una consulta. En el ejemplo, la columna foto es mapeada al atributo laFoto. 3) A través de la etiqueta <select>, se puede utilizar SQL estándar para realizar consultas. Los parámetros simples que llegan a la consulta son referenciados, utilizando la sintaxis #value#

CIBERTEC

CARRERAS PROFESIONALES

3


96

f) Paso 6: Modificar el archivo MySqlClienteDAO

public ClienteDTO buscaPorUsuario(String usuario) throws Exception{ //Metodo modificado para Ibatis ClienteDTO objClienteDTO=null; System.out.println("Validamos con ibatis"); SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance();

1

objClienteDTO=(ClienteDTO)sqlMap.queryForObject("ibatis_logueo ", usuario); 2

System.out.println("busca por usuario usando Ibatis"); return objClienteDTO; } ...

Notas: 1) A través de la clase UtilSqlConfig, se crea una instancia de la clase SqlMapClient. En el ejemplo, el objeto sqlMap es la representación en java del archivo SqlMapConfig. 2) Se invoca al método queryForObject del objeto sqlMap. Se envía como parámetros lo siguiente: • El nombre de la operación que se desea ejecutar (definida en el archivo Cliente.xml) • El código de usuario a través del cual se validará el logueo.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

97

g) Paso 7: Ejecutar la aplicación web

Ingrese a la intranet a través de la página de logueo.

CIBERTEC

CARRERAS PROFESIONALES


98

Se visualizará la pantalla de bienvenida de la aplicación.

Se visualizará en consola el mensaje generado por la clase MySqlClienteDAO

h)

Paso 8:

¡Bien!, ha culminado la funcionalidad

“Introducción IBATIS” exitosamente.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

99

2.1.2. Operaciones básicas de Acceso a base de datos con IBATIS Para implementar las operaciones básicas con IBATIS, es necesario conocer las principales etiquetas del Framework. Éstas se muestran a continuación: Sentencias Atributos

Elementos Hijos

id parameterClass resultClass parameterMap <statement> resultMap cacheModel xmlResultName (Java only)

insert update All dynamic elements delete All query methods

Métodos

<insert>

id parameterClass parameterMap

All dynamic elements insert <selectKey> update <generate> (.NET delete only)

<update>

id parameterClass parameterMap

All dynamic elements insert <generate> (.NET update only) delete

<delete>

id parameterClass parameterMap

All dynamic elements insert <generate> (.NET update only) delete

<select>

id parameterClass resultClass parameterMap resultMap cacheModel

All dynamic elements All query <generate> (.NET methods only)

id parameterClass resultClass <procedure> parameterMap resultMap xmlResultName (Java only)

insert update All dynamic elements delete All query methods

Se desarrollan, a continuación, diversos ejercicios en los que se utilizarán y describirán las principales etiquetas del Framework.

CIBERTEC

CARRERAS PROFESIONALES


100

2.1.2.1. Ejercicio 1: Funcionalidad IBATIS - Mantenimiento

Se implementará una aplicación que permita ejecutar las operaciones básicas de un mantenimiento, utilizando el framework IBATIS. a) Paso 1: Modificar el archivo Cliente.xml

. . . <resultMap

<result <result <result <result <result <result <result

class="cli" id="clienteRes"

>

property="nombre" column="nombre" /> property="sueldo" column="sueldo" /> property="sexo" column="sexo" /> property="fecnac" column="fecnac" /> property="usuario" column="usuario" /> property="clave" column="clave" /> property="laFoto" column="foto" />

</resultMap>

<parameterMap class="java.util.Map" id="clienteMap" <parameter <parameter <parameter <parameter <parameter <parameter <parameter

>

property="nombre" jdbcType="VARCHAR" /> property="sueldo" jdbcType="DOUBLE" /> property="sexo" jdbcType="CHAR" /> property="fecnac" jdbcType="DATETIME" /> property="usuario" jdbcType="VARCHAR" /> property="clave" jdbcType="VARCHAR" /> property="foto" jdbcType="BLOB" />

</parameterMap>

Notas: 1) Al utilizar la etiqueta <parameterMap>, se ha creado un párametro especial llamado clienteMap. Éste será enviado desde la clase DAO y estará representado por la clase java.util.Map. Note cómo se identifica cada campo de la clase Map con el tipo de dato al que se referirá en la base de datos.

CARRERAS PROFESIONALES

CIBERTEC

1


DESARROLLO DE APLICACIONES WEB I

101

Se crean las operaciones para insertar y listar clientes por nombre.

<select id="ibatis_clienteLista" parameterClass="java.lang.String" resultClass="cli"> <!-- Para poner wildcards aqui en value seria '%$value$%'--> select usuario,clave,nombre,sueldo,sexo,fecnac from tbcliente where nombre like #value# </select> <!-- cuando utilizamos parameterMap o resultMap nuestras sentencias pueden utilizar las interrogantes de un prepareStatement tipico --> <insert id="ibatis_insertaCliente" parameterMap="clienteMap" insert into tbcliente(nombre,sueldo,sexo,fecnac, usuario,clave,foto) values (?,?,?,?,?,?,?) </insert> ...

Notas: 1) Observe cómo la operación ibatis_insertaCliente recibe como parámetro “clienteMap” definido en líneas previas. Los campos son automáticamente asociados a las interrogantes de la sentencia SQL.

CIBERTEC

CARRERAS PROFESIONALES

> 1


102

b) Paso 2: Modificar la clase MySqlClienteDAO Se prepara la invocación a las operaciones IBATIS definidas en el archivo Cliente.xml.

public int registraCliente(ClienteDTO objCliente) throws Exception{ System.out.println("Insertando con ibatis :) "); int resultado =0; SqlMapClient cliente = UtilSqlConfig.getSqlMapInstance(); // En vez de enviar objCliente, enviaremos una estructura // preparada para soportar un tipo LongBloB y registrar // el cliente con IBATIS HashMap<String, Object> map = new HashMap<String, Object>(); map.put("nombre", objCliente.getNombre()); map.put("sueldo", objCliente.getSueldo()); map.put("sexo", objCliente.getSexo()); map.put("fecnac", objCliente.getFecnac()); map.put("usuario", objCliente.getUsuario()); map.put("clave", objCliente.getClave()); // intento 01: asumimos que ibatis soporta como parametro // un arreglo de bytes // Asumimos que esta llegando la foto InputStream is = objCliente.getIsFoto(); byte[] losbytes = new byte[is.available()]; // a partir del inputStream cargamos el arreglo los bytes is.read(losbytes); 1

map.put("foto", losbytes); cliente.insert("ibatis_insertaCliente",map);

2

System.out.println("registro exitoso con IBATIS :) "); return resultado; } ... Notas: 1) A partir del campo isFoto (de tipo InputStream), se prepara un arreglo de bytes, el cual se carga en el objeto map con el nombre “foto”. 2) Se invoca a la sentencia insert de IBATIS, pasándole como parámetros el nombre de la operación a ejecutar y el objeto map.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

103

public List<ClienteDTO> listaPorNombre(String vnombre) throws Exception{ ArrayList<ClienteDTO> clientes= new ArrayList<ClienteDTO>(); /** Para manejar transacciones usar las clasese de Ibatis de sqlMapClient**/ System.out.println("Validamos con ibatis"); SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance(); clientes=(ArrayList<ClienteDTO>)sqlMap.queryForList("ibatis_cl ienteLista", "%"+vnombre+"%"); System.out.println("listado por nombre usando Ibatis");

return clientes;

1

} ...

Notas: 1) Se invoca al método queryForList para ejecutar operaciones que retornen más de un registro como resultado. Note que se envía la variable vnombre junto con los caracteres “%” a ser utilizados en la consulta definida en el archivo Cliente.xml (como parte del parámetro like).

c) Paso 3: Ejecutar la aplicación

Ingrese a la intranet y ejecute la funcionalidad de Listado. Se visualizará la siguiente pantalla:

CIBERTEC

CARRERAS PROFESIONALES


104

En la consola, se visualizará el mensaje definido en la clase MySqlClienteDAO.

Ahora, seleccione el enlace “Nuevo Cliente” y registre uno nuevo con el botón Registrar.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

105

Se visualizará la siguiente ventana con el nuevo registro ingresado. En el ejemplo, se ha registrado al cliente “Don Ramón”.

CIBERTEC

CARRERAS PROFESIONALES


106

También, se visualizará, en consola, el mensaje definido en la clase MySqlClienteDAO.

d) Paso 4: ¡Bien!, ha culminado la funcionalidad “Mantenimiento IBATIS” exitosamente.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

107

2.2 Otras operaciones con IBATIS 2.2.1. Otras operaciones y características de IBATIS Los procedimientos almacenados se crean con la declaración <procedure>. El siguiente ejemplo muestra un procedimiento almacenado con parámetros de salida. procedure.xml

<parameterMap id= "swapParameters" class= "map"> <parameter property= "email1" jdbcType= "VARCHAR" javaType= "java.lang.String "mode= "INOUT" /> <parameter property= "email2" jdbcType= "VARCHAR" javaType= "java.lang.String "mode= "INOUT" /> </ parameterMap> <procedure id= "swapEmailAddresses" parameterMap= "swapParameters"> (call swap_email_address (?,?)) </ procedimiento>

Se implementan, a almacenados IBATIS.

continuación,

ejercicios

con

procedimientos

2.2.1.1. Ejercicio 1: Registro de Clientes utilizando Stored Procedures Se implementará una aplicación web que permita registrar los datos de un cliente (incluida su fotografía), utilizando IBATIS y Stored Procedures. a)

Paso 1: Importar FuncionalidadIbatisProcedure_Inicial.war

el

archivo

1

CIBERTEC

CARRERAS PROFESIONALES


108

Notas: 1) Cuenta, en esta oportunidad, dentro de la carpeta bd con archivos adicionales dentro de los cuales destaca ps_nuevoCliente.sql. Este archivo contiene el stored procedure que deberรก crear en mysql. b) Paso 2: Ejecute el archivo sp_nuevoCliente.sql dentro de mysql

CREATE PROCEDURE `sp_nuevoCliente`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), in vfoto BLOB, inout resultado int ) BEGIN

1

declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable = 0 then set resultado = 777; insert into tbcliente(nombre,sueldo,sexo,fecnac,usuario,clave,foto) values( vnombre, vsueldo, vsexo, vfecnac, vusuario, vclave, vfoto); else set resultado = 666; end if; END $$ ...

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

109

Ejecute el stored procedure, utilizando la herramienta Mysql Query Browser (u otra equivalente)

2

Notas: 1) Se recibe como parรกmetro un campo de tipo BLOB. ร‰ste debe haber sido cargado previamente en la clase MySqlClienteDAO y reconocido por el archivo Cliente.xml.

2) Una vez ejecutado el script del stored procedure se debe visualizar su base de datos (en el ejemplo facilito) y el nombre del procedimiento creado.

CIBERTEC

CARRERAS PROFESIONALES


110

c) Paso 3: Modifique el método registraCliente dentro de la clase MySqlClienteDAO

byte[] losbytes = new byte[is.available()]; // a partir del inputStream cargamos el arreglo los bytes is.read(losbytes); map.put("foto", losbytes); 1

map.put("resultado", 0); System.out.println("resultado antes de insertar: " + map.get("resultado")); cliente.insert("ibatis_spInsertaCliente", map);

2

System.out.println("resultado despues de insertar: " + map.get("resultado"));

3

System.out.println("invocacion exitosa a SP IBATIS :) "); return resultado; ...

Notas: 1) Se carga en el objeto map un atributo adicional: el campo resultado. Éste permitirá recuperar el resultado retornado por el stored procedure. 2) Se debe invocar a una nueva operación definida en el archivo Cliente.xml: ibatis_spInsertaCliente. 3) Se recupera el resultado retornado por el stored procedure: En el ejemplo, en caso de ser exitosa la operación, retornará el valor 777, de lo contrario regresará a 666.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

111

d) Paso 4: Modifique el archivo Cliente.xml

<parameterMap class="java.util.Map" id="clienteMap" <parameter <parameter <parameter <parameter <parameter <parameter <parameter <parameter />

>

1

property="nombre" jdbcType="VARCHAR" mode="IN" /> property="sueldo" jdbcType="DOUBLE" mode="IN" /> property="sexo" jdbcType="CHAR" mode="IN" /> property="fecnac" jdbcType="DATETIME" mode="IN" /> property="usuario" jdbcType="VARCHAR" mode="IN" /> property="clave" jdbcType="VARCHAR" mode="IN" /> property="foto" jdbcType="BLOB" mode="IN" /> property="resultado" jdbcType="INT" mode="INOUT"

</parameterMap>

2

3

... <procedure id="ibatis_spInsertaCliente" parameterMap="clienteMap"

>

call sp_nuevoCliente(?,?,?,?,?,?,?,?) </procedure> Notas: 1) Se debe modificar cada una de las etiquetas <parameter> para indicar, a través del atributo mode, si el parámetro es de entrada o entrada/salida. 2) Note cómo el arreglo de bytes cargado con el nombre foto en el objeto java.util.map es mapeado a una columna en la tabla de tipo BLOB: jdbcType=”BLOB” 3) Note qué resultado es la única propiedad de tipo INOUT. A través de ella, se retornará al MySqlClienteDAO el resultado de la ejecución del stored procedure. 4) Debe invocar al stored procedure creado en base de datos a través de la sentencia call. Note que usa la etiqueta IBATIS <prodecure> para definir la operación ibatis_spInsertaCliente.

CIBERTEC

CARRERAS PROFESIONALES

4


112

e) Paso 5: Ejecute la aplicaciรณn Seleccione la opciรณn Nuevo Cliente una vez realizado el listado de Clientes. Visualizarรก la siguiente pantalla:

Luego de ingresar datos y seleccionar el botรณn Registrar, se visualizarรก la siguiente pantalla:

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

113

Se visualizará también, en la consola de Eclipse, los siguientes mensajes:

Insertando con ibatis :) resultado antes de insertar: 0 resultado despues de insertar: 777 invocacion exitosa a SP IBATIS :) dentro del listaCliente del Service Validamos con ibatis listado por nombre usando Ibatis 23/01/2011 05:38:41 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger INFO: Removing file cliente.foto C:\Users\plgarcia\workspace\.metadata\.plugins\org.eclipse.wst .server.core\tmp0\work\Catalina\localhost\FuncionalidadIBatisP rocedure_Final\upload__2a3c5961_12db5077826__8000_00000006.tmp 23/01/2011 05:38:41 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger warn f)

Paso 6:

¡Muy Bien!, ha culminado exitosamente la

funcionalidad “Registro de Clientes con Stored Procedures e IBATIS”.

CIBERTEC

CARRERAS PROFESIONALES


114

2.1.2. Tópicos Avanzandos de IBATIS e integración Struts 2 Es cada vez más común utilizar estructuras de base de datos capaces de almacenar grandes cantidades de información. IBATIS es capaz de gestionar objetos grandes (LOB), tales como los campos BLOB (Binary) o CLOB (de caracteres). A partir de la versión de IBATIS 2.0.9, este framework cuenta, por defecto, los campos BLOB y CLOB. Se implementa, a continuación, un ejemplo con Stored Procedures que utiliza este tipo de estructuras.

2.1.2.1. Ejercicio 1: Actualización de Clientes utilizando Stored Procedures

a) Paso 1: Ubique los Stored Procedures relacionados con la actualización de datos de un cliente almacenados en la carpeta bd de su proyecto.

1

Notas: 1) Observe que debe ejecutar los archivos sp_modificaCliente.sql y sp_modificaClienteConFoto.sql

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

115

b) Paso 2: Ejecute los archivos sp_modificaCliente.sql y sp_modificaClienteConFoto.sql dentro del entorno MySql

CREATE PROCEDURE `sp_modificaCliente`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), inout resultado int ) BEGIN declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable != 0 then set resultado = 777; 1

update tbcliente set nombre=vnombre, sueldo=vsueldo, sexo=vsexo, fecnac=vfecnac, clave=vclave where usuario=vusuario; else set resultado = 666; end if; END $$ ...

CIBERTEC

CARRERAS PROFESIONALES


116

CREATE PROCEDURE `sp_modificaClienteConFoto`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), in vfoto BLOB, inout resultado int ) BEGIN

2

declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable != 0 then set resultado = 777; update tbcliente set nombre=vnombre, sueldo=vsueldo, sexo=vsexo, fecnac=vfecnac, clave=vclave, foto=vfoto where usuario=vusuario; else set resultado = 666; end if;

END $$ ...

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

117

En el ejemplo, se ha utilizado la herramienta MySql WorkBench para ejecutar los Stored Procedures.

3

Notas: 1) La sentencia update no considera en su ejecución la actualización de la columna foto. Este procedure será invocado cuando el usuario del sistema no desee actualizar la fotografía del cliente.

2) Este procedure sí recibe como parámetro un campo denominado vfoto, de modo que se pueda actualizar la imagen del cliente. 3) Una vez ejecutados los procedures dentro de la herramienta gráfica de Mysql éstos se visualizan en la ventana de edición. En el ejemplo, en la ventana Object Browser.

CIBERTEC

CARRERAS PROFESIONALES


118

c) Paso 3: Modifique el método registraCliente dentro de la clase MySqlClienteDAO

HashMap<String, Object> map = new HashMap<String, Object>(); map.put("nombre", objCliente.getNombre()); map.put("sueldo", objCliente.getSueldo()); map.put("sexo", objCliente.getSexo()); map.put("fecnac", objCliente.getFecnac()); map.put("usuario", objCliente.getUsuario()); map.put("clave", objCliente.getClave()); if (objCliente.getFoto() != null) { InputStream is = objCliente.getIsFoto(); byte[] losbytes = new byte[is.available()]; // a partir del inputStream cargamos el arreglo los bytes is.read(losbytes); map.put("foto", losbytes); } map.put("resultado", 0); System.out.println("resultado antes de actualizar: " + map.get("resultado"));

1

SqlMapClient cliente = UtilSqlConfig.getSqlMapInstance(); if (objCliente.getFoto() != null) { cliente.update("ibatis_spModificaClienteConFoto", map); }else{ cliente.update("ibatis_spModificaCliente", map); } System.out.println("resultado despues de actualizar: " + map.get("resultado")); System.out.println("invocacion exitosa a SP MOD IBATIS :) "); } ... Notas: 1) Solo se carga en el objeto map el atributo foto, si éste es diferente de null. En el ejemplo, se controla esta situación a través de la condición:

if (objCliente.getFoto() != null)

CARRERAS PROFESIONALES

CIBERTEC

2

3


DESARROLLO DE APLICACIONES WEB I

119

2) Se invocará a una nueva operación: ibatis_spModificaClienteConFoto o ibatis_spModificaCliente.

3) Se recupera el resultado retornado por el stored procedure: En el ejemplo, en caso de ser exitosa la operación, retornará el valor 777, de lo contrario regresará a 666. d) Paso 4: Modifique el archivo Cliente.xml

<parameterMap class="java.util.Map" id="clienteMapBasico" > <parameter property="nombre" jdbcType="VARCHAR" mode="IN" /> <parameter property="sueldo" jdbcType="DOUBLE" mode="IN" /> <parameter property="sexo" jdbcType="CHAR" mode="IN" /> <parameter property="fecnac" jdbcType="DATETIME" mode="IN" /> <parameter property="usuario" jdbcType="VARCHAR" mode="IN" /> <parameter property="clave" jdbcType="VARCHAR" mode="IN" /> <parameter property="resultado" jdbcType="INT" mode="INOUT" />

1

</parameterMap> <parameterMap class="java.util.Map" id="clienteMap" > <parameter property="nombre" jdbcType="VARCHAR" mode="IN" /> <parameter property="sueldo" jdbcType="DOUBLE" mode="IN" /> <parameter property="sexo" jdbcType="CHAR" mode="IN" /> <parameter property="fecnac" jdbcType="DATETIME" mode="IN" /> <parameter property="usuario" jdbcType="VARCHAR" mode="IN" /> <parameter property="clave" jdbcType="VARCHAR" mode="IN" /> <parameter property="foto" jdbcType="BLOB" mode="IN" /> <parameter property="resultado" jdbcType="INT" mode="INOUT" /> </parameterMap> ... <procedure id="ibatis_spModificaClienteConFoto" parameterMap="clienteMap" > call sp_modificaClienteConFoto(?,?,?,?,?,?,?,?) </procedure>

2

3

<procedure id="ibatis_spModificaCliente" parameterMap="clienteMapBasico" > call sp_modificaCliente(?,?,?,?,?,?,?) </procedure> Notas: 1) Se ha creado un nuevo parameterMap: clienteMapBasico, que será utilizado para actualizar la información del cliente sin modificar su fotografía.

CIBERTEC

CARRERAS PROFESIONALES


120

2) Se mantiene el parameterMap clienteMap para actualizar la información del cliente modificando su fotografía.

3) Se han creado dos nuevas operaciones en el archivo Cliente.xml que serán invocadas por la clase MySqlClienteDAO para modificar la información del cliente modificando o no su fotografía, respectivamente.

e) Paso 5: Ejecute la aplicación Una vez realizado el listado de clientes, seleccione el enlace “M” para modificar uno de los clientes. En el ejemplo, se cambian los datos de Don Ramón. Se visualizará la siguiente pantalla:

Luego de modificar los datos y seleccionar el botón Actualizar, se visualizará la siguiente pantalla:

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

121

1

Nota: 1) Puede seleccionar nuevamente el enlace “M” para verificar los cambios realizados. Visualizará que se logró modificar exitosamente la fotografía de “Don Ramón”.

CIBERTEC

CARRERAS PROFESIONALES


122

f)

Paso

6:

¡Muy

Bien!,

ha

funcionalidad “Actualización

culminado

exitosamente

la

de Clientes con Stored

Procedures e IBATIS”.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

123

Resumen Para recoger un conjunto de elementos con la clase List, puede hacer lo siguiente: List<Coche> coches = sqlMap.queryForList("getCoches", null) Para recoger un conjunto de elementos con la clase Map, puede hacer lo

siguiente: Map hashCoche = (Map) sqlMap.queryForObject("getHashCoche", 3);

Para el manejo del campo BLOB, se tiene que realizar lo siguiente en el archivo de Ibatis:

<resultMap class= <result <result <result <result /> </ resultMap>

"Report" id= "ReportResult"> column= "id" property= "id" /> column= "name" property= "name" /> column= "description" property= "description" /> column= "data" property= "data" jdbcType= "BLOB"

Si desea saber mĂĄs acerca de estos temas, puede consultar la siguiente pĂĄgina.  http://www.nabble.com/iBATIS-f360.html AquĂ­ encontrarĂĄ un foro donde se ventilan varios puntos del manejo de Ibatis  http://www.javaworld.com/javaworld/jw-07-2008/jw-07-orm-comparison.html AquĂ­ hallarĂĄ comparaciones entre los frameworks de persistencia mĂĄs utilizados.

CIBERTEC

CARRERAS PROFESIONALES


124

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

125

UNIDAD DE APRENDIZAJE

3

REPORTES EN SISTEMAS EMPRESARIALES LOGRO DE LA UNIDAD DE APRENDIZAJE •

Al finalizar la unidad, los alumnos, utilizando el framework STRUTS 2, la librería JasperReport y la herramienta IReport, implementan una aplicación web que genera reportes con criterios de búsqueda dinámicos y acceso a base de datos.

TEMARIO 3.1 Tema 5

: Reportes con JasperReport

3.1.1.

: Diseño e implementación de reportes con la herramienta IReport

3.2 Tema 6

: Struts 2 y JasperReport

3.2.1.

: Integración de Struts 2 y JasperReport – Reportes Estándar

ACTIVIDADES PROPUESTAS •

CIBERTEC

Los alumnos implementan una aplicación web básica utilizando las principales características del framework MVC Struts 2 y la librería jasperReport.

CARRERAS PROFESIONALES


126

3.1 Reportes con JasperReport 3.1.1. Diseño e implementación de Reportes con la herramienta IReport La herramienta iReport es un constructor y/o diseñador de reportes visual, fácil de usar para JasperReport, un lenguaje para generación de reportes escrito en Java. Esta herramienta permite que los usuarios corrijan visualmente reportes complejos con cartas, imágenes, subreportes, etc. iReport está, además, integrado con la biblioteca gráfica “JFreeChart”, una de las más gráficas OpenSource y difundida para Java. Los datos para imprimir pueden ser recuperados por varios tipos de archivos, incluso múltiples uniones JDBC, TableModels, JavaBeans, archivos XML, etc. A continuación, se enumeran las principales características de esta herramienta: 9 100% escrito en JAVA y, además, de uso libre y gratuito 9 Maneja el 99% de las etiquetas de JasperReports 9 Permite diseñar con sus propias herramientas: rectángulos, líneas, elipses, campos de los textfields, cartas, subreports (subreportes) 9 Soporta internacionalización nativamente 9 Recopila y exporta integrados 9 Soporta JDBC 9 Soporta JavaBeans como orígenes de datos 9 Incluye asistentes para crear automáticamente informes.

3.1.1.1. Funcionamiento de JasperReport JasperReports trabaja en forma similar a un compilador y a un intérprete. El usuario diseña el reporte codificándolo en XML de acuerdo con las etiquetas y atributos definidos en un archivo llamado jasperreports.dtd (parte de JasperReports). Usando XML, el usuario define completamente el reporte, describiendo dónde colocar texto, imágenes, líneas, rectángulos, cómo adquirir los datos, cómo realizar ciertos cálculos para mostrar totales, etc. Este archivo fuente XML debe ser compilado para obtener un reporte real. La versión compilada del fuente es nombrada "archivo jasper" (este termina con .jasper). Un Archivo jasper es el compilado de un código fuente. Cuando se tiene éste, se necesita de datos para visualizar el resultado. Para generar reportes en Java, se necesita considerar la aplicación del archivo compilado (.jasper), que recibirá los datos a visualizar de la aplicación. El archivo generado por la herramienta iReport es de tipo “jrxml”, en el cual se encontrará el diseño y estilo del reporte, y podrá ser modificado en la herramienta iReport.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

127

3.2 Struts 2 y JasperReport 3.2.1. Integración de Struts 2 y JasperReport – Reportes Estándar Struts 2 permite implementar una integración natural con JasperReport a través del uso de una librería (plug in): struts2-jasperreports-plugin-2.1.8.1.jar Esta librería viene por defecto con la versión estándar de Struts 2 y permite crear en el archivo struts.xml un nuevo tipo de <result>: jasper Se implementará, a continuación, un ejercicio de aplicación, en el que se integra un reporte generado con la herramienta IReport (archivo compilado .jasper) y Struts 2. 3.2.1.1. Ejercicio 01: Funcionalidad Reporte de clientes con JasperReport Se implementará una aplicación web que permita listar los clientes por País, haciendo uso de la librería JasperReport e integrándola a Struts 2. a)

CIBERTEC

Paso 1: Importar el archivo FuncionalidadIbatisReportes_Inicial.war

CARRERAS PROFESIONALES


128

1

2

Notas: 1) Existe un nuevo archivo en la carpeta bd denominado FacilitoBaseDatosv2.sql. En él, se encontrarán nuevas tablas, a partir de las cuales se generará el reporte. 2) Existen nuevas librerías en la carpeta lib que permitirán integrar Struts 2 y JasperReport.

b) Paso 2: Ejecute el archivo FacilitoBaseDatosv2.sql dentro de mysql

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

129

create table pais ( `cod_pais` varchar(2) not null, `nom_pais` varchar(90) not null, primary key (`cod_pais`) ) ENGINE=InnoDB default CHARSET=latin1;

create table cliente ( `usuario` varchar(15) not null, `password` varchar(15) not null, `nombres` varchar(90) null, `apellidos` varchar(90) null, `sexo` varchar(1) not null, `fecha_nacimiento` datetime null, `dni` varchar(8) null, `cod_pais` varchar(2) null, `fecha_ingreso` datetime null, `email` varchar(80) null, `vip` varchar(1) not null, `flag_admin` varchar(1) not null default 'N', primary key (`usuario`)

Notas: 1) Debe crear las tablas cliente y paĂ­s en MySql. Sobre la base de estas tablas, se generarĂĄ el nuevo reporte. b) Paso 3: Modificar el archivo struts.xml

CIBERTEC

CARRERAS PROFESIONALES

1


130

. . . <result-types> <result-type name="jasper"

1

class="org.apache.struts2.views.jasperreports.JasperReportsR esult"/> </result-types> 2

<!-- creamos los actions del menu --> <action name="a_reporte" > <result type="tiles" >d_reporte</result> </action>

3

. . . <action name="reporteFacilito" class="aprendamos.java.action.ReporteAction" method="listaClientesPorPais" > <result name="exito" type="jasper"> <param name="location">/reportes/reporte01.jasper</param> <param name="dataSource">listaClientes</param> <param name="contentDisposition"> attachment;filename="contacts.pdf" </param> <param name="format">PDF</param> <!--<param name="connection">cnListaClientes</param> -> d_reporte </result> Notas: 1) Debe crear un nuevo result type para poder integrar jasperReport y Struts 2. 2) Cree el action a_reporte para invocar a un nuevo definition: d_reporte. Éste invocará a una página JSP para generar el reporte, usando JasperReport. 3) Cree un nuevo action: reporteFacilito. Este componente define un <result> de tipo jasper en donde se configuran los principales parámetros del reporte como por ejemplo:

CARRERAS PROFESIONALES

Formato del archivo a generar: PDF

Ubicación de archivos compilado ejecutar: /reportes/reporte01.jasper

.jasper

Origen de datos para generar (dataSource): atributo listaClientes.

el

a

listado

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

131

d) Paso 4: Modificar el archivo tiles.xml

<definition name="d_reporte" extends="d_bienvenida"> <put-attribute name="body" value="/paginas/reportes.jsp" /> </definition> ...

1

Notas: 1) Cree el definition d_reporte. Se invocarรก al JSP reportes.jsp

e) Paso 5: Cree el archivo reportes.jsp

<s:form method="post" action="reporteFacilito"> <table class="control" > <tr> <td> <s:text name="reporte.nombre" /> </td> <td> <s:textfield name="nombre" /> </td> <td align="right" > <input type="submit" name="boton01" value="Listar" > </td> </tr> </table> </s:form>su ID -->

...

Notas: 1) Debe invocar al action reporteFacilito, el cual ya ha sido registrado en el archivo struts.xm. Asimismo, debe generar el listado con jasperreport. f) Paso 6: Cree el action ReporteAction

CIBERTEC

CARRERAS PROFESIONALES

1


132

public class ReporteAction { private String nombre; private List<ReporteDTO> listaClientes;

1

public List<ReporteDTO> getListaClientes() { return listaClientes; } public void setListaClientes(List<ReporteDTO> listaClientes) { this.listaClientes = listaClientes; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String listaClientesPorPais(){ String vista="exito"; //JasperReportConstants.FORMAT_HTML //JasperReportConstants.FORMAT_PDF //JasperReportConstants.FORMAT_XLS System.out.println("dentro de listaClientesPorPais :)"); try { this.setListaClientes( PaqueteBusinessDelegate.getClienteService(). listaClientesReporte(nombre)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("nombre del cliente"+this.getNombre()); System.out.println("redireccionamos a la vista exito!"); return vista; } } ... Notas: 1) El atributo listaClientes es referenciado en el archivo struts.xml como origen de datos para el Reporte. Note que es una lista de objetos de tipo ReporteDTO. Esta clase tiene como atributos los campos que ser谩n mostrados en el reporte. 2) Se define la lista de clientes a obtener, considerando la selecci贸n del usuario (el atributo nombre).

CARRERAS PROFESIONALES

CIBERTEC

2


DESARROLLO DE APLICACIONES WEB I

133

g) Paso 7: Modifica la clase ClienteService

public List<ReporteDTO> listaClientesReporte(String nombre) throws Exception{ System.out.println("dentro del listaCliente del Service"); // Aqui podemos colocar logica adicional antes de invocar al metodo // del DAO return objClienteDAO.listaPorNombreReporte(nombre); ...

Notas: 1) Debe crear el mĂŠtodo listaClientesReporte para que la clase ReporteAction pueda invocarlo y generar el reporte.

CIBERTEC

CARRERAS PROFESIONALES

1


134

h) Paso 8: Modificar el archivo MySqlClienteDAO

public List<ReporteDTO> listaPorNombreReporte(String nombre) throws Exception { ArrayList<ReporteDTO> clientes= new ArrayList<ReporteDTO>(); 1

Connection cn = MySqlDBConn.obtenerConexion(); //definimos la sentencia String sql="SELECT usuario,password,nombres,apellidos,sexo,fecha_nacimiento,dni, c.cod_pais,p.nom_pais" + " FROM cliente c,pais p WHERE c.nombres like and c.cod_pais = p.cod_pais order by c.cod_pais"; //la preparamos PreparedStatement pst=cn.prepareStatement(sql); //asignamos valores a las interrogantes pst.setString(1,"%"+nombre+"%"); //ejecutamos ResultSet rs=pst.executeQuery(); while(rs.next()){ //hay dayos, recuperamos un ergsitro ReporteDTO cliente = new ReporteDTO(); cliente.setUsuario(rs.getString(1)); cliente.setPassword(rs.getString(2)); cliente.setNombres(rs.getString(3)); cliente.setApellidos(rs.getString(4)); cliente.setSexo(rs.getString(5)); cliente.setFecha_nacimiento(rs.getString(6)); cliente.setDni(rs.getString(7)); cliente.setCod_pais(rs.getString(8)); cliente.setNom_pais(rs.getString(9)); clientes.add(cliente); } cn.close(); return clientes; } ...

Notas: 1) Note cómo, de manera “clásica”, se obtiene una conexión para hacer la consulta respectiva. Debe transformar este código a su equivalente en ibatis. i) Paso 9: Modifique el archivo menu.jsp

CARRERAS PROFESIONALES

CIBERTEC

?


DESARROLLO DE APLICACIONES WEB I

135

<tr> <td class="control" > <s:a action="a_reporte"

1

>

<s:text name="menu.reporte"

/>

</s:a> </td> </tr> ...

Notas: 1) Debe invocar al action a_reporte para cargar la página JSP a partir de la cual se generará el reporte.

i)

Paso 10: Ejecutar la aplicación web

Ingrese a la intranet a través de la página de logueo. Se visualizará la siguiente pantalla:

Seleccione la opción reporte utilizando JasperReport

CIBERTEC

CARRERAS PROFESIONALES


136

Se visualizará la siguiente pantalla. Luego, ingrese un criterio de búsqueda. Finalmente, seleccione el botón Listar.

Visualizará una pantalla a través de la que se le consultará si desea abrir o guardar el archivo. Seleccione abrir el archivo.

Visualizará el reporte en una pantalla similar a la siguiente:

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

j)

Paso 11:

137

¡Muy Bien!, ha culminado la funcionalidad

“reportes con JasperReport y Struts 2” de manera exitosa!

CIBERTEC

CARRERAS PROFESIONALES


138

Resumen Se pueden construir reportes visualmente en Java, utilizando la herramienta iReport. ร‰sta usa como estructura base jasperReport, un lenguaje basado en etiquetas xml y especialmente creado para generar reportes. IReport genera archivos fuente con extensiรณn .jrxml. Los archivos compilados tienen extensiรณn .jasper y pueden ser ejecutados desde una aplicaciรณn java web. Si desea saber mรกs acerca de estos temas, puede consultar la siguiente pรกgina. http://jasperforge.org/website/ireportwebsite/IR%20Website/iReport_documentati on.html?group_id=243&header=project&leftnav=yes&target=ireport

Aquรญ, encontrarรก tutoriales que le permitirรกn crear reportes utilizando IReport.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

139

ANEXOS

ANEXO 1: SOFTWARE REQUERIDO

Este curso requiere las siguientes herramientas de software: • • • • • • •

CIBERTEC

Java JDK Entorno integrado de desarrollo o IDE Servidor de Aplicaciones Base de datos Framework Struts 2 Framework MyIbatis MyIbatis Generator

CARRERAS PROFESIONALES


140

HERRAMIENTA #1: Java Development Kit Desde la página de Oracle, descargue la última versión del JDK (Java Development Kit). Se debe considerar que los “updates” de las versiones son periódicos. Se puede navegar por http://java.sun.com, el cual redirecciona a http://www.oracle.com/technetwork/java/javase/downloads/index.html

Para entornos de programación, se requiere el JDK, pero para los de producción basta con el JRE. Por último, ejecute el instalador y siga los pasos indicados en el wizard.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

141

HERRAMIENTA #2: Entorno Integrado de Desarrollo En un entorno de desarrollo Java, el IDE ( Integrated Development Environment ) es la herramienta de software que permite obtener mayor productividad al programar las aplicaciones. En el mercado, existen varias opciones disponibles, pero las más utilizadas y conocidas son las siguientes: • • • •

Eclipse IDE : Sitio web http://www.eclipse.org NetBeans : Sitio web http://www.netbeans.org JDeveloper : Información disponible en http://www.oracle.com Rational Application Developer: Información disponible en http://www.ibm.com

Eclipse IDE: Primero, descargue Eclipse Helios desde la página de la fundación Eclipse ( http://www.eclipse.org ). Luego, busque la zona de descarga. Por último, seleccione la versión Java EE:

Al terminar la descarga, el .ZIP generado se puede extraer en una carpeta cualquiera (normalmente en la raíz de uno de los discos de la PC). Se puede crear un acceso directo desde el Escritorio apuntando al archivo eclipse.exe

CIBERTEC

CARRERAS PROFESIONALES


142

Rational Application Developer IDE : Descargue el software “IBM Rational Application Developer for WebSphere Software” desde la página web de IBM: http://www.ibm.com/developerworks/downloads/r/rad/?S_CMP=TRIALS

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

143

HERRAMIENTA #3: Servidor de aplicaciones Apache Tomcat Desde la página de la Fundación Apache ( http://tomcat.apache.org ), se debe obtener el servidor de aplicaciones Tomcat. La última versión probada en otros tutoriales ha sido la 6.0.20. Actualmente se encuentra disponible la versión 7 en beta.

Sólo es necesario el “Core”. Descargar el .ZIP y extraerlo en una carpeta.

WebSphere Application Server Desde la página web de IBM, se puede descargar el software del servidor de aplicaciones: http://www-01.ibm.com/software/webservers/appserv/was/

CIBERTEC

CARRERAS PROFESIONALES


144

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

145

HERRAMIENTA #4: Motor de Base de Datos Se necesita un motor de base de datos: En http://www.mysql.com, se puede decargar la Base de Datos MySQL (versión “Community Server” )

Es preferible descargar la versión “NO-INSTALL” para que no afecte el registry de la PC:

Basta con descargar el .ZIP y extraerlo en cualquier carpeta. El servicio de base de datos se activa por línea de comandos de la manera siguiente:

CIBERTEC

CARRERAS PROFESIONALES


146

También, se requiere el “Connector” o driver JDBC:

Las herramientas de Query Browser y MySQL Administrator han sido reemplazadas por MySQL WorkBench:

De igual forma, seleccionar el .ZIP ( que sea del tipo “No Install” ) y extraerlo en alguna carpeta de la PC.

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

147

HERRAMIENTA #5: Librerías de Struts 2 Del sitio web de la Fundación Apache, se obtienen las librerías del framework Struts 2 La última versión liberada es la 2.2.1

Se debe escoger una de las opciones de los archivos .ZIP. Con la alternativa de “Full Distribution”, es más que suficiente.

Extraer el contenido del .ZIP en una carpeta de la PC.

CIBERTEC

CARRERAS PROFESIONALES


148

HERRAMIENTA #6: MyIbatis La p谩gina principal se encuentra en http://www.mybatis.org/

En la zona de downloads, la direcci贸n es http://code.google.com/p/mybatis/

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

149

HERRAMIENTA #7: MyIbatis Generator La pรกgina principal se encuentra: http://code.google.com/p/mybatis/downloads/detail?name=mybatis-generator-core1.3.1-bundle.zip&can=3&q=Product%3DGenerator

CIBERTEC

CARRERAS PROFESIONALES


150

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

151

ANEXOS

ANEXO 2: MANEJO DE MYIBATIS Ejemplo de una aplicaci贸n con MyIbatis

CIBERTEC

CARRERAS PROFESIONALES


152

La Clase entidad

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

153

El Data Access Object para Vendedor

CIBERTEC

CARRERAS PROFESIONALES


154

El Mapper de MyIbatis para el mantenimiento de vendedor es el siguiente:

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

El Archivo de Configuración de MyIbatis • los datos de la cadena de conexión • los tipos de datos de los mappers • la ubicación de los mappers

CIBERTEC

155

Se configura Se configura Se configura

CARRERAS PROFESIONALES


156

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

157

ANEXOS

ANEXO 3: MYIBATIS DynamicSQL Una de las características más potentes de MyBatis siempre ha sido su capacidad de SQL dinámico. MyBatis, sin duda, mejora la situación en el lenguaje SQL, que se pueden utilizar dentro de cualquier mapa instrucciónSQL. Los elementos de SQL dinámico debe ser familiar para cualquiera que haya usado JSTL o cualquier XML, similares a base procesadores de texto. En versiones anteriores de MyBatis, había una gran cantidad de elementos para conocer y comprender. M ejora en gran medida en esto y ahora hay menos de la mitad de esos elementos para trabajar. Asimismo, emplea potentes expresiones OGNL base para eliminar la mayoría de los demás elementos.

• If • choose (when, otherwise) • trim (where, set) • foreach Ejemplo de if: <select id=”findActiveBlogWithTitleLike” parameterType=”Blog” resultType=”Blog”> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test=”title != null”> AND title like #{title} </if> </select> <select id=”findActiveBlogLike” parameterType=”Blog” resultType=”Blog”> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test=”title != null”> AND title like #{title} </if> <if test=”author != null and author.name != null”> AND title like #{author.name} </if> </select>

CIBERTEC

CARRERAS PROFESIONALES


158

choose, when, otherwise <select id=”findActiveBlogLike” parameterType=”Blog” resultType=”Blog”> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test=”title != null”> AND title like #{title} </when> <when test=”author != null and author.name != null”> AND title like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>

trim, where, set <select id=”findActiveBlogLike” parameterType=”Blog” resultType=”Blog”> SELECT * FROM BLOG WHERE <if test=”state != null”> state = #{state} </if> <if test=”title != null”> AND title like #{title} </if> <if test=”author != null and author.name != null”> AND title like #{author.name} </if> </select> <select id=”findActiveBlogLike” parameterType=”Blog” resultType=”Blog”> SELECT * FROM BLOG <where> <if test=”state != null”> state = #{state} </if> <if test=”title != null”> AND title like #{title} </if> <if test=”author != null and author.name != null”> AND title like #{author.name} </if> </where> </select>

Foreach <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

159

ANEXOS

ANEXO 3: DE IBATIS 2.X HACIA MYIBATIS En el sqlMapConfig.xml DTD:

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

En los mappers sqlMap (*.map.xml) DTD:

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

Configuración: •

La raíz era <sqlMapConfig>, ahora es <configuration>

Settings Ibatis 2.0:

<settings x="y" foo="bar"/>

MyIbatis 3.0:

<settings> <setting name="x" value="y"/> <setting name="foo" value="bar"/> </settings>

y

CIBERTEC

CARRERAS PROFESIONALES


160

<settings useStatementNamespaces="true"/>

<typeAlias> <typeAlias> deberia ser movido fuera de <sqlMap> hacia <configuration> <typeAliases></typeAliases> </configuration>

<configuration> <settings> ... </settings> <typeAliases> <typeAlias ... /> </typeAliases> </configuration>

<transactionManager> <dataSource> Ibatis 2.0:

<transactionManager type="JDBC" commitRequired="false"> <dataSource type="your.package.CustomDataSourceFactory" /> </transactionManager>

MyIbatis 3.0:

<environments default="env"> <environment id="env"> <transactionManager type="JDBC"> <property name="commitRequired" value="false"/> </transactionManager> <dataSource type="your.package.CustomDataSourceFactory" /> </environment> </environments>

<sqlMap>

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

161

Ibatis 2.0:

<sqlMap resource=... /> <sqlMap resource=... /> <sqlMap resource=... />

MyIbatis 3.0:

<mappers> <mapper resource=... /> </mappers>

Mapping • • • • • •

La raiz del elemento <sqlMap> es ahora <mapper> El atributo parameterClass debería ser cambiado por parameterType El atributo resultClass debería ser cambiado por resultType El atributo class debería ser cambiado por type El columnIndex atributo no existe algun resultado en la etiqueta <result> El groupBy atributo debería ser eliminado.

Ibatis 2.0:

<resultMap id="productRM" class="product" groupBy="id"> <result property="id" column="product_id"/> <result property="name" column="product_name"/> <result property="category" column="product_category"/> <result property="subProducts" resultMap="Products.subProductsRM"/> </resultMap>

MyIbatis 3.0:

<resultMap id="productRM" type="product" > <id property="id" column="product "/> <result property="name " column="product_name "/> <result property="category " column="product_category "/> <collection property="subProducts" resultMap="Products.subProductsRM"/> </resultMap>

CIBERTEC

CARRERAS PROFESIONALES


162

Nested resultMaps Édebería especificarse mediante <association> tag.

Ibatis 2.0:

<resultMap ...> <result property="client" resultMap="Client.clientRM"/> ... </resultMap>

MyIbatis 3.0:

<resultMap ...> <association property="client" resultMap="Client.clientRM"/> ... </resultMap>

Inline parameters Ibatis 2.0:

#value#

MyIbatis 3.0:

#{value}

jdbcType changes Ibatis 2.0:

jdbcType="ORACLECURSOR"

MyIbatis 3.0:

jdbcType="CURSOR"

CARRERAS PROFESIONALES

CIBERTEC


DESARROLLO DE APLICACIONES WEB I

163

Ibatis 2.0:

jdbcType="NUMBER"

MyIbatis 3.0:

jdbcType="NUMERIC"

Stored procedures â&#x20AC;˘

La etiqueta <procedure> no existe en MyIbatis. Use <select>, <insert> o <update>.

Ibatis 2.0:

<procedure id="getValues" parameterMap="getValuesPM"> { ? = call pkgExample.getValues(p_id => ?) } </procedure>

MyIbatis 3.0:

<select id="getValues" parameterMap="getValuesPM" statementType="CALLABLE"> { ? = call pkgExample.getValues(p_id => ?)} </select>

Caching Ibatis 2.0:

<cacheModel id="myCache" type="LRU"> <flushInterval hours="24"/> <property name="size" value="100" /> </cacheModel>

MyIbatis 3.0:

<cache flushInterval="86400000" eviction="LRU"/>

CIBERTEC

CARRERAS PROFESIONALES


164

Dynamic SQL Ibatis 2.0:

<isNotNull.*?property=\"(.*?)\"> </isNotNull>

MyIbatis 3.0:

<if test="$1 != null"> </if>

CARRERAS PROFESIONALES

CIBERTEC


Desarrollo de aplicaciones web i