164
Desarrollo de Aplicaciones Web I

5to ciclo desarrollo de aplicaciones web i

Embed Size (px)

Citation preview

Page 1: 5to ciclo   desarrollo de aplicaciones web i

Desarrollo de Aplicaciones Web I

Page 2: 5to ciclo   desarrollo de aplicaciones web i

2

CARRERAS PROFESIONALES CIBERTEC

Page 3: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3

CIBERTEC CARRERAS PROFESIONALES

Í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

características Struts 2

63

1.2.1. : Uso de un pool de conexiones para acceso a la fuente

de datos

63

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

componentes

72

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

IBATIS

110

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

Struts 2

128

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

Page 4: 5to ciclo   desarrollo de aplicaciones web i

4

CARRERAS PROFESIONALES CIBERTEC

3.1.1. : Diseño e implementación de reportes con la

herramienta Ireport

141

3.2 Tema 6 : Struts 2 y JasperReport 142 3.2.1. : Integración de Struts 2 y JasperReport 142

Anexo 1 157

Anexo 2 167

Anexo 3 172

Page 5: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5

CIBERTEC CARRERAS PROFESIONALES

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.

Page 6: 5to ciclo   desarrollo de aplicaciones web i

6

CARRERAS PROFESIONALES CIBERTEC

RED DE CONTENIDOS

Desarrollo de Aplicaciones Web 1

Modelo Vista Controlador – Patrón MVC

Fundamentos de Struts 2

Otras Características

Struts 2

Persistencia de

datos – Framework

IBATIS

Introducción a IBATIS

Otras operaciones

IBATIS

Reportes en

sistemas empresariales

Tema 5 JasperReport

Tema 6 Struts 2 y

Jasper

Page 7: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7

CIBERTEC CARRERAS PROFESIONALES

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

UNIDAD DE APRENDIZAJE

1

Page 8: 5to ciclo   desarrollo de aplicaciones web i

8

CARRERAS PROFESIONALES CIBERTEC

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:

Services (Lógica pura de negocio) 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.

Page 9: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9

CIBERTEC CARRERAS PROFESIONALES

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:

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

1

2

Page 10: 5to ciclo   desarrollo de aplicaciones web i

10

CARRERAS PROFESIONALES CIBERTEC

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

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

<?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>

1

Page 11: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1

CIBERTEC CARRERAS PROFESIONALES

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

Page 12: 5to ciclo   desarrollo de aplicaciones web i

12

CARRERAS PROFESIONALES CIBERTEC

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

Page 13: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3

CIBERTEC CARRERAS PROFESIONALES

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

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

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:

<!-- 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>

1

Page 14: 5to ciclo   desarrollo de aplicaciones web i

14

CARRERAS PROFESIONALES CIBERTEC

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

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.

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; } }

<package name="default" namespace="/" extends="struts-default"> <action name="logueo" class="aprendamos.java.action.LogueoAction" > <result name="error" >/logueo.jsp </result> <result name="exito" >/bienvenida.jsp </result> </action> </package>

1

Page 15: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5

CIBERTEC CARRERAS PROFESIONALES

e) Paso 5: Ejecutar la aplicación web

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.

1

Page 16: 5to ciclo   desarrollo de aplicaciones web i

16

CARRERAS PROFESIONALES CIBERTEC

Dentro de la clase MySqlClienteDAO, debe modificar el método buscaPorUsuario. Complete el código con la lógica mostrada a continuación:

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.

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:

//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();

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

Page 17: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 7

CIBERTEC CARRERAS PROFESIONALES

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:

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

 

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(); }

public abstract class DAOFactory { public static final int MYSQL = 1; public static final int ORACLE = 2; public static final int DB2 = 3; public static final int SQLSERVER = 4; public static final int XML = 5; // 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();

1

Page 18: 5to ciclo   desarrollo de aplicaciones web i

18

CARRERAS PROFESIONALES CIBERTEC

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

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()); } }

1

2

Page 19: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 9

CIBERTEC CARRERAS PROFESIONALES

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

c) Paso 3: Crear la clase PaqueteBusinessDelegate

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

1

Page 20: 5to ciclo   desarrollo de aplicaciones web i

20

CARRERAS PROFESIONALES CIBERTEC

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 PaqueteBusinessDelegate { private PaqueteBusinessDelegate() { // TODO Auto-generated constructor stub } public static LogueoService_I getLogueoService(){ return new LogueoService(); } // agregar aqui mas llamadas a otros servicios }

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; }

2

Page 21: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 2 1

CIBERTEC CARRERAS PROFESIONALES

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; }

Page 22: 5to ciclo   desarrollo de aplicaciones web i

22

CARRERAS PROFESIONALES CIBERTEC

Recuerde que debe utilizar Expression Language (EL) en el JSP logueo.jsp para visualizar el mensaje de error definido en la clase LogueoAction.

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

       

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

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

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

Page 23: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 2 3

CIBERTEC CARRERAS PROFESIONALES

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

Page 24: 5to ciclo   desarrollo de aplicaciones web i

24

CARRERAS PROFESIONALES CIBERTEC

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.

b) Paso 2: Agregar nuevas keys al archivo de recursos MisRecursos.properties

Puede agregar las keys correspondientes a los mensajes de error del logueo.

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

Page 25: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 2 5

CIBERTEC CARRERAS PROFESIONALES

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.

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

# 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

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;

. . . }else{

vista="error"; this.setMensaje( this.getText( "logueo.mensaje.error.clave"));

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

Page 26: 5to ciclo   desarrollo de aplicaciones web i

26

CARRERAS PROFESIONALES CIBERTEC

d) Paso 4: Modificar el JSP logueo.jsp

Debe referenciar a la librería de etiquetas de struts 2.

Transforme las etiquetas html en sus equivalentes de Struts 2.

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

<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>

Page 27: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 2 7

CIBERTEC CARRERAS PROFESIONALES

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.

Modifique el método execute.

Notas:

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

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(); } if(objUsuario!=null){ if(objUsuario.getClave().equals(this.getCliente().getClave())){

1

2

Page 28: 5to ciclo   desarrollo de aplicaciones web i

28

CARRERAS PROFESIONALES CIBERTEC

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.

Page 29: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 2 9

CIBERTEC CARRERAS PROFESIONALES

g) Paso 7: ¡Muy buen trabajo!

Page 30: 5to ciclo   desarrollo de aplicaciones web i

30

CARRERAS PROFESIONALES CIBERTEC

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 web

FuncionalidadRegistraImagen_Inicial.war

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.

1

Page 31: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3 1

CIBERTEC CARRERAS PROFESIONALES

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

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

1

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;

Page 32: 5to ciclo   desarrollo de aplicaciones web i

32

CARRERAS PROFESIONALES CIBERTEC

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:

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.

<s:form action="ingresaCliente"

method="post" 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" /> </td> </tr> <tr class="control" > <td align="right" > <input type="submit" name="boton01" value="Registrar" > </td> </tr> </table>

</s:form>

1

2

Page 33: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3 3

CIBERTEC CARRERAS PROFESIONALES

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

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; . . .

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

1

1

Page 34: 5to ciclo   desarrollo de aplicaciones web i

34

CARRERAS PROFESIONALES CIBERTEC

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.

. . . ClienteService_I servicioCliente = PaqueteBusinessDelegate.getClienteService(); // creamos el metodo registra public String registra(){ String vista="exito"; 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; }

2

3

4

Page 35: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3 5

CIBERTEC CARRERAS PROFESIONALES

f) Paso 6: Modificar la clase ClienteDTO

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

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.

public class ClienteDTO implements Serializable { private static final long serialVersionUID = 1L; private String nombre; private Date fecnac; private String sexo; private double sueldo; private String usuario; private String clave; 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; } . . .

2

1

Page 36: 5to ciclo   desarrollo de aplicaciones web i

36

CARRERAS PROFESIONALES CIBERTEC

g) Paso 7: Modificar la clase ClienteService

La clase ClienteService debe contar con la siguiente lógica en el método registraElCliente:

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).

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

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) if(objCliente.getFoto()!=null){ InputStream tempo =

new FileInputStream(objCliente.getFoto()); objCliente.setIsFoto(tempo); } return objClienteDAO.registraCliente(objCliente); }

1

Page 37: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3 7

CIBERTEC CARRERAS PROFESIONALES

h) Paso 8: Modificar la clase MySqlClienteDAO

La clase MySqlClienteDAO debe implementar la siguiente lógica en el método registraCliente:

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:

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); // asignamos valores a las interrogantes pst.setString(1, objCliente.getNombre()); pst.setDouble(2, objCliente.getSueldo()); pst.setString(3, objCliente.getSexo()); // 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; }

1

2

Page 38: 5to ciclo   desarrollo de aplicaciones web i

38

CARRERAS PROFESIONALES CIBERTEC

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());

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().

Page 39: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 3 9

CIBERTEC CARRERAS PROFESIONALES

i) Paso 9: Ejecutar la aplicación web

Seleccione del listado de Clientes el enlace Nuevo Cliente:

Page 40: 5to ciclo   desarrollo de aplicaciones web i

40

CARRERAS PROFESIONALES CIBERTEC

En la pantalla mostrada, ingrese los campos solicitados.

Page 41: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 4 1

CIBERTEC CARRERAS PROFESIONALES

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.

Page 42: 5to ciclo   desarrollo de aplicaciones web i

42

CARRERAS PROFESIONALES CIBERTEC

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

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.

1

Page 43: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 4 3

CIBERTEC CARRERAS PROFESIONALES

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

Page 44: 5to ciclo   desarrollo de aplicaciones web i

44

CARRERAS PROFESIONALES CIBERTEC

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 web FuncionalidadRegistraImagenI18N_Inicial.war

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

1

Page 45: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 4 5

CIBERTEC CARRERAS PROFESIONALES

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

Page 46: 5to ciclo   desarrollo de aplicaciones web i

46

CARRERAS PROFESIONALES CIBERTEC

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

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 = 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

#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

1

Page 47: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 4 7

CIBERTEC CARRERAS PROFESIONALES

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

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

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

1

2

Page 48: 5to ciclo   desarrollo de aplicaciones web i

48

CARRERAS PROFESIONALES CIBERTEC

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

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.

1

. . . <package name="default" namespace="/" extends="struts-default"> <action name="a_bienvenida" > <result > /bienvenida.jsp </result> </action> <action name="a_logueo" > <result > /logueo.jsp </result> </action> . . .

1

Page 49: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 4 9

CIBERTEC CARRERAS PROFESIONALES

Modifique el archivo menu.jsp

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" %>

1

. . . <tr> <td class="control" > <s:a action="a_bienvenida" > <s:text name="menu.bienvenida" /> </s:a> </td> </tr> <tr> <td class="control" > <s:a action="a_logueo" > <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> . . .

1

Page 50: 5to ciclo   desarrollo de aplicaciones web i

50

CARRERAS PROFESIONALES CIBERTEC

Modifique el archivo bienvenida.jsp

1

. . . <table class="control" > <tr> <td colspan="2" > <s:text name="key.saludo" /> </td> </tr> <!-- recuperamos los atributos del usuario logueado utilizando EL (Expression Language) --> <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> . . .

Page 51: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5 1

CIBERTEC CARRERAS PROFESIONALES

f) 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.

Page 52: 5to ciclo   desarrollo de aplicaciones web i

52

CARRERAS PROFESIONALES CIBERTEC

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ú.

Page 53: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5 3

CIBERTEC CARRERAS PROFESIONALES

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.

Page 54: 5to ciclo   desarrollo de aplicaciones web i

54

CARRERAS PROFESIONALES CIBERTEC

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 web FuncionalidadRegistraImagenPool_Inicial.war

Page 55: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5 5

CIBERTEC CARRERAS PROFESIONALES

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.

1

Page 56: 5to ciclo   desarrollo de aplicaciones web i

56

CARRERAS PROFESIONALES CIBERTEC

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

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.

1

<?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"/> </Context>

2

3

Page 57: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5 7

CIBERTEC CARRERAS PROFESIONALES

c) Paso 3: Modificar el archivo MySqlDbConn.java

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.

package aprendamos.java.util; // Esta clase nos retornara una conexion a base de datos import java.sql.*; import javax.naming.*; import javax.sql.*; public class MySqlDBConn { // Utilizaremos mas bien un pool de conexiones // creamos el metodo que nos permite obtener una conexion

. . .

1

2

Page 58: 5to ciclo   desarrollo de aplicaciones web i

58

CARRERAS PROFESIONALES CIBERTEC

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.

. . . 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/"; // obtenemos a traves de su nombre a nuestro // pool de conexiones DataSource ds= (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; }

1

2

Page 59: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 5 9

CIBERTEC CARRERAS PROFESIONALES

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

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.

1

Page 60: 5to ciclo   desarrollo de aplicaciones web i

60

CARRERAS PROFESIONALES CIBERTEC

e) Paso 5: Ejecutar la aplicación web

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

Page 61: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 6 1

CIBERTEC CARRERAS PROFESIONALES

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.

Page 62: 5to ciclo   desarrollo de aplicaciones web i

62

CARRERAS PROFESIONALES CIBERTEC

f) Paso 6: ¡Bien!, ha culminado la funcionalidad “registra

imagen pool” exitosamente.

Page 63: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 6 3

CIBERTEC CARRERAS PROFESIONALES

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:

<s:url> <s:action> <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

Page 64: 5to ciclo   desarrollo de aplicaciones web i

64

CARRERAS PROFESIONALES CIBERTEC

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:

. . . <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> . . .

1

Page 65: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 6 5

CIBERTEC CARRERAS PROFESIONALES

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.

2

Page 66: 5to ciclo   desarrollo de aplicaciones web i

66

CARRERAS PROFESIONALES CIBERTEC

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

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; public class ClienteAction { // creamos un atributo de tipo Lista de Clientes ClienteDTO cliente; List<ClienteDTO> clientes; String usuario; . . .

<action name="cargaModificaCliente" class="aprendamos.java.action.ClienteAction" method="cargaModifica" > <result name="exito" >/modificaCliente.jsp </result> </action>

1

1

Page 67: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 6 7

CIBERTEC CARRERAS PROFESIONALES

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

. . .

public String cargaModifica(){ String vista="exito"; try { cliente= servicioCliente.buscaClientePorUsuario( this.getUsuario()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return vista; } . . .

2

3

Page 68: 5to ciclo   desarrollo de aplicaciones web i

68

CARRERAS PROFESIONALES CIBERTEC

e) Paso 5: Verificar la clase MySqlClienteDAO

La clase MySqlClienteDAO debe implementar la siguiente lógica en el método buscaPorUsuario:

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)

public ClienteDTO buscaPorUsuario(String usuario) throws Exception{ ClienteDTO objClienteDTO=null; 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); //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; }

1

2

Page 69: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 6 9

CIBERTEC CARRERAS PROFESIONALES

f) Paso 6: Ejecutar la aplicación web

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

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

1

Page 70: 5to ciclo   desarrollo de aplicaciones web i

70

CARRERAS PROFESIONALES CIBERTEC

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”

Page 71: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7 1

CIBERTEC CARRERAS PROFESIONALES

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:

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}.

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

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

1

Page 72: 5to ciclo   desarrollo de aplicaciones web i

72

CARRERAS PROFESIONALES CIBERTEC

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

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.

<action name="cargaImagenCliente" class="aprendamos.java.action.ImagenAction" method="recuperaImagenCliente" > <result name="exito" type="stream" > <!-- en inputName colocamos el nombre del atributo del action que permitira generar el flujo (stream) --> <param name="inputName">imagenClienteRecuperada</param> </result> </action>

2

3

1

Page 73: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7 3

CIBERTEC CARRERAS PROFESIONALES

j) 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 { String usuario; InputStream imagenClienteRecuperada; . . .

1

. . . public String recuperaImagenCliente(){ String vista="exito"; try { ClienteDTO cli= 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; } . . .

2

3

Page 74: 5to ciclo   desarrollo de aplicaciones web i

74

CARRERAS PROFESIONALES CIBERTEC

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:

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

1

Page 75: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7 5

CIBERTEC CARRERAS PROFESIONALES

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) Paso 12: ¡Muy Bien!, ha culminado exitosamente la funcionalidad completa “carga imagen”.

Page 76: 5to ciclo   desarrollo de aplicaciones web i

76

CARRERAS PROFESIONALES CIBERTEC

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.

Page 77: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7 7

CIBERTEC CARRERAS PROFESIONALES

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

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:

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

1

2

3

4

Page 78: 5to ciclo   desarrollo de aplicaciones web i

78

CARRERAS PROFESIONALES CIBERTEC

• 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:

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

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

1

Page 79: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 7 9

CIBERTEC CARRERAS PROFESIONALES

c) Paso 3: Modificar el archivo struts.xml

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.

<?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 name="menu" value="/paginas/menu.jsp" /> <put-attribute name="pie" value="/paginas/pie.jsp" /> <put-attribute name="cabecera" value="/paginas/cabecera.jsp" /> <put-attribute 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> . . .

1

2

3

Page 80: 5to ciclo   desarrollo de aplicaciones web i

80

CARRERAS PROFESIONALES CIBERTEC

d) Paso 4: Modificar el archivo struts.xml

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.

. . . <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 </result> </action> <action name="a_bienvenida" > <result type="tiles"> d_bienvenida </result> </action> <action name="a_logueo" > <result > /logueo.jsp </result> </action> <action name="a_listado" > <result type="tiles"> d_listado </result> </action> <!-- 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> . . .

1

3

2

Page 81: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 8 1

CIBERTEC CARRERAS PROFESIONALES

e) Paso 5: Crear el archivo diseno01.jsp

Notas:

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

1

Page 82: 5to ciclo   desarrollo de aplicaciones web i

82

CARRERAS PROFESIONALES CIBERTEC

f) Paso 6: Modificar el archivo diseno01.jsp

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.

<%@ 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"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <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 name="cabecera" /></td> </tr> <tr> <td><tiles:insertAttribute name="menu" /></td> <td><tiles:insertAttribute name="body" /></td> </tr> <tr> <td colspan="2"><tiles:insertAttribute name="pie" /></td> </tr> </table> </body> . . .

1

2

Page 83: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 8 3

CIBERTEC CARRERAS PROFESIONALES

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

Notas: 1) Tal como se indicó en el archivo tiles.xml, las páginas JSP

deben estar dentro de una carpeta denominada páginas.

1

Page 84: 5to ciclo   desarrollo de aplicaciones web i

84

CARRERAS PROFESIONALES CIBERTEC

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

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.

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

1

Page 85: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 8 5

CIBERTEC CARRERAS PROFESIONALES

i) Paso 9: Ejecutar la aplicación web

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

Page 86: 5to ciclo   desarrollo de aplicaciones web i

86

CARRERAS PROFESIONALES CIBERTEC

Visualizará la pantalla de bienvenida de la aplicación

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

Page 87: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 8 7

CIBERTEC CARRERAS PROFESIONALES

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.

Page 88: 5to ciclo   desarrollo de aplicaciones web i

88

CARRERAS PROFESIONALES CIBERTEC

Page 89: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 8 9

CIBERTEC CARRERAS PROFESIONALES

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

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

UNIDAD DE APRENDIZAJE

2

Page 90: 5to ciclo   desarrollo de aplicaciones web i

90

CARRERAS PROFESIONALES CIBERTEC

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.

Page 91: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9 1

CIBERTEC CARRERAS PROFESIONALES

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

Notas: 1) Observe que debe contar con las librerías básicas de

IBATIS para integrar el framework a su aplicación web.

1

Page 92: 5to ciclo   desarrollo de aplicaciones web i

92

CARRERAS PROFESIONALES CIBERTEC

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

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.

1

2

Page 93: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9 3

CIBERTEC CARRERAS PROFESIONALES

c) Paso 3: Modificar el archivo SqlMapConfig.xml

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.

<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> <!-- 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> . . .

1

2

Page 94: 5to ciclo   desarrollo de aplicaciones web i

94

CARRERAS PROFESIONALES CIBERTEC

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 //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; } } . . .

1

2

Page 95: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9 5

CIBERTEC CARRERAS PROFESIONALES

e) Paso 5: Modificar el archivo Cliente.xml

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#

<?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 class="cli" id="clienteRes" > <result property="nombre" column="nombre" /> <result property="sueldo" column="sueldo" /> <result property="sexo" column="sexo" /> <result property="fecnac" column="fecnac" /> <result property="usuario" column="usuario" /> <result property="clave" column="clave" /> <result property="laFoto" column="foto" /> </resultMap> <!-- 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> . . .

1

2

3

Page 96: 5to ciclo   desarrollo de aplicaciones web i

96

CARRERAS PROFESIONALES CIBERTEC

f) Paso 6: Modificar el archivo MySqlClienteDAO

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.

public ClienteDTO buscaPorUsuario(String usuario) throws Exception{ //Metodo modificado para Ibatis ClienteDTO objClienteDTO=null; System.out.println("Validamos con ibatis"); SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance(); objClienteDTO=(ClienteDTO)sqlMap.queryForObject("ibatis_logueo", usuario); System.out.println("busca por usuario usando Ibatis"); return objClienteDTO; } . . .

1

2

Page 97: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9 7

CIBERTEC CARRERAS PROFESIONALES

g) Paso 7: Ejecutar la aplicación web

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

Page 98: 5to ciclo   desarrollo de aplicaciones web i

98

CARRERAS PROFESIONALES CIBERTEC

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.

Page 99: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 9 9

CIBERTEC CARRERAS PROFESIONALES

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 Métodos

<statement>

id parameterClass resultClass parameterMap resultMap cacheModel xmlResultName (Java only)

All dynamic elements

insert update delete All query methods

<insert> id parameterClass parameterMap

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

insert update delete

<update> id parameterClass parameterMap

All dynamic elements <generate> (.NET only)

insert update delete

<delete> id parameterClass parameterMap

All dynamic elements <generate> (.NET only)

insert update delete

<select>

id parameterClass resultClass parameterMap resultMap cacheModel

All dynamic elements <generate> (.NET only)

All query methods

<procedure>

id parameterClass resultClass parameterMap resultMap xmlResultName (Java only)

All dynamic elements

insert update 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.

Page 100: 5to ciclo   desarrollo de aplicaciones web i

100

CARRERAS PROFESIONALES CIBERTEC

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

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.

. . . <resultMap class="cli" id="clienteRes" > <result property="nombre" column="nombre" /> <result property="sueldo" column="sueldo" /> <result property="sexo" column="sexo" /> <result property="fecnac" column="fecnac" /> <result property="usuario" column="usuario" /> <result property="clave" column="clave" /> <result property="laFoto" column="foto" /> </resultMap> <parameterMap class="java.util.Map" id="clienteMap" > <parameter property="nombre" jdbcType="VARCHAR" /> <parameter property="sueldo" jdbcType="DOUBLE" /> <parameter property="sexo" jdbcType="CHAR" /> <parameter property="fecnac" jdbcType="DATETIME" /> <parameter property="usuario" jdbcType="VARCHAR" /> <parameter property="clave" jdbcType="VARCHAR" /> <parameter property="foto" jdbcType="BLOB" /> </parameterMap>

1

Page 101: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 0 1

CIBERTEC CARRERAS PROFESIONALES

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

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.

<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> . . .

1

Page 102: 5to ciclo   desarrollo de aplicaciones web i

102

CARRERAS PROFESIONALES CIBERTEC

b) Paso 2: Modificar la clase MySqlClienteDAO

Se prepara la invocación a las operaciones IBATIS definidas en el archivo Cliente.xml.

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.

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); map.put("foto", losbytes); cliente.insert("ibatis_insertaCliente",map); System.out.println("registro exitoso con IBATIS :) "); return resultado; } . . .

1

2

Page 103: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 0 3

CIBERTEC CARRERAS PROFESIONALES

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:

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_clienteLista", "%"+vnombre+"%"); System.out.println("listado por nombre usando Ibatis"); return clientes; } . . .

1

Page 104: 5to ciclo   desarrollo de aplicaciones web i

104

CARRERAS PROFESIONALES CIBERTEC

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.

Page 105: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 0 5

CIBERTEC CARRERAS PROFESIONALES

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

Page 106: 5to ciclo   desarrollo de aplicaciones web i

106

CARRERAS PROFESIONALES CIBERTEC

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

d) Paso 4: ¡Bien!, ha culminado la funcionalidad “Mantenimiento

IBATIS” exitosamente.

Page 107: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 0 7

CIBERTEC CARRERAS PROFESIONALES

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 continuación, ejercicios con procedimientos almacenados IBATIS.

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 el archivo

FuncionalidadIbatisProcedure_Inicial.war

1

Page 108: 5to ciclo   desarrollo de aplicaciones web i

108

CARRERAS PROFESIONALES CIBERTEC

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

1

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 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 $$ . . .

Page 109: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 0 9

CIBERTEC CARRERAS PROFESIONALES

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

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.

2

Page 110: 5to ciclo   desarrollo de aplicaciones web i

110

CARRERAS PROFESIONALES CIBERTEC

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

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.

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 insertar: " + map.get("resultado")); cliente.insert("ibatis_spInsertaCliente", map); System.out.println("resultado despues de insertar: " + map.get("resultado")); System.out.println("invocacion exitosa a SP IBATIS :) "); return resultado; . . .

1

2

3

Page 111: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1 1

CIBERTEC CARRERAS PROFESIONALES

d) Paso 4: Modifique el archivo Cliente.xml

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.

<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_spInsertaCliente" parameterMap="clienteMap" > call sp_nuevoCliente(?,?,?,?,?,?,?,?) </procedure>

1

2

3

4

Page 112: 5to ciclo   desarrollo de aplicaciones web i

112

CARRERAS PROFESIONALES CIBERTEC

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:

Page 113: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1 3

CIBERTEC CARRERAS PROFESIONALES

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

f) Paso 6: ¡Muy Bien!, ha culminado exitosamente la

funcionalidad “Registro de Clientes con Stored Procedures e

IBATIS”.

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\FuncionalidadIBatisProcedure_Final\upload__2a3c5961_12db5077826__8000_00000006.tmp 23/01/2011 05:38:41 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger warn

Page 114: 5to ciclo   desarrollo de aplicaciones web i

114

CARRERAS PROFESIONALES CIBERTEC

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.

Notas:

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

1

Page 115: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1 5

CIBERTEC CARRERAS PROFESIONALES

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

1

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; update tbcliente set nombre=vnombre, sueldo=vsueldo, sexo=vsexo, fecnac=vfecnac, clave=vclave where usuario=vusuario; else set resultado = 666; end if; END $$ . . .

Page 116: 5to ciclo   desarrollo de aplicaciones web i

116

CARRERAS PROFESIONALES CIBERTEC

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 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 $$ . . .

2

Page 117: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1 7

CIBERTEC CARRERAS PROFESIONALES

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

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.

3

Page 118: 5to ciclo   desarrollo de aplicaciones web i

118

CARRERAS PROFESIONALES CIBERTEC

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

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)

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"));

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 :) "); } . . .

1

2

3

Page 119: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 1 9

CIBERTEC CARRERAS PROFESIONALES

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

Notas: 1) Se ha creado un nuevo parameterMap: clienteMapBasico,

que será utilizado para actualizar la información del cliente sin modificar su fotografía.

<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" /> </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> <procedure id="ibatis_spModificaCliente" parameterMap="clienteMapBasico" > call sp_modificaCliente(?,?,?,?,?,?,?) </procedure>

1

2

3

Page 120: 5to ciclo   desarrollo de aplicaciones web i

120

CARRERAS PROFESIONALES CIBERTEC

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:

Page 121: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 2 1

CIBERTEC CARRERAS PROFESIONALES

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”.

1

Page 122: 5to ciclo   desarrollo de aplicaciones web i

122

CARRERAS PROFESIONALES CIBERTEC

f) Paso 6: ¡Muy Bien!, ha culminado exitosamente la

funcionalidad “Actualización de Clientes con Stored

Procedures e IBATIS”.

Page 123: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 2 3

CIBERTEC CARRERAS PROFESIONALES

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= "Report" id= "ReportResult"> <result column= "id" property= "id" /> <result column= "name" property= "name" /> <result column= "description" property= "description" /> <result column= "data" property= "data" jdbcType= "BLOB" /> </ resultMap>

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.

Page 124: 5to ciclo   desarrollo de aplicaciones web i

124

CARRERAS PROFESIONALES CIBERTEC

Page 125: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 2 5

CIBERTEC CARRERAS PROFESIONALES

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

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

UNIDAD DE APRENDIZAJE

3

Page 126: 5to ciclo   desarrollo de aplicaciones web i

126

CARRERAS PROFESIONALES CIBERTEC

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:

100% escrito en JAVA y, además, de uso libre y gratuito Maneja el 99% de las etiquetas de JasperReports Permite diseñar con sus propias herramientas: rectángulos, líneas,

elipses, campos de los textfields, cartas, subreports (subreportes) Soporta internacionalización nativamente Recopila y exporta integrados Soporta JDBC Soporta JavaBeans como orígenes de datos 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.

Page 127: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 2 7

CIBERTEC CARRERAS PROFESIONALES

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) Paso 1: Importar el archivo FuncionalidadIbatisReportes_Inicial.war

Page 128: 5to ciclo   desarrollo de aplicaciones web i

128

CARRERAS PROFESIONALES CIBERTEC

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

1

2

Page 129: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 2 9

CIBERTEC CARRERAS PROFESIONALES

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

1

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`)

Page 130: 5to ciclo   desarrollo de aplicaciones web i

130

CARRERAS PROFESIONALES CIBERTEC

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:

• Formato del archivo a generar: PDF

• Ubicación de archivos compilado .jasper a

ejecutar: /reportes/reporte01.jasper

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

. . . <result-types> <result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult"/> </result-types> <!-- creamos los actions del menu --> <action name="a_reporte" > <result type="tiles" >d_reporte</result> </action> . . . <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>

1

2

3

Page 131: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3 1

CIBERTEC CARRERAS PROFESIONALES

d) Paso 4: Modificar el archivo tiles.xml

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

e) Paso 5: Cree el archivo reportes.jsp

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

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

1

<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 --> . . .

1

Page 132: 5to ciclo   desarrollo de aplicaciones web i

132

CARRERAS PROFESIONALES CIBERTEC

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).

public class ReporteAction { private String nombre; private List<ReporteDTO> listaClientes; 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; } } . . .

1

2

Page 133: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3 3

CIBERTEC CARRERAS PROFESIONALES

g) Paso 7: Modifica la clase ClienteService

Notas: 1) Debe crear el método listaClientesReporte para que la clase

ReporteAction pueda invocarlo y generar el reporte.

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); . . .

1

Page 134: 5to ciclo   desarrollo de aplicaciones web i

134

CARRERAS PROFESIONALES CIBERTEC

h) Paso 8: Modificar el archivo MySqlClienteDAO

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

public List<ReporteDTO> listaPorNombreReporte(String nombre) throws Exception { ArrayList<ReporteDTO> clientes= new ArrayList<ReporteDTO>(); 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; } . . .

1

Page 135: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3 5

CIBERTEC CARRERAS PROFESIONALES

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

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

1

Page 136: 5to ciclo   desarrollo de aplicaciones web i

136

CARRERAS PROFESIONALES CIBERTEC

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:

Page 137: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3 7

CIBERTEC CARRERAS PROFESIONALES

j) Paso 11: ¡Muy Bien!, ha culminado la funcionalidad

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

Page 138: 5to ciclo   desarrollo de aplicaciones web i

138

CARRERAS PROFESIONALES CIBERTEC

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.

Page 139: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 3 9

CIBERTEC CARRERAS PROFESIONALES

ANEXO 1: SOFTWARE REQUERIDO Este curso requiere las siguientes herramientas de software:

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

ANEXOS

Page 140: 5to ciclo   desarrollo de aplicaciones web i

140

CARRERAS PROFESIONALES CIBERTEC

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.

Page 141: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 4 1

CIBERTEC CARRERAS PROFESIONALES

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

Page 142: 5to ciclo   desarrollo de aplicaciones web i

142

CARRERAS PROFESIONALES CIBERTEC

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

Page 143: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 4 3

CIBERTEC CARRERAS PROFESIONALES

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/

Page 144: 5to ciclo   desarrollo de aplicaciones web i

144

CARRERAS PROFESIONALES CIBERTEC

Page 145: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 4 5

CIBERTEC CARRERAS PROFESIONALES

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:

Page 146: 5to ciclo   desarrollo de aplicaciones web i

146

CARRERAS PROFESIONALES CIBERTEC

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.

Page 147: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 4 7

CIBERTEC CARRERAS PROFESIONALES

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.

Page 148: 5to ciclo   desarrollo de aplicaciones web i

148

CARRERAS PROFESIONALES CIBERTEC

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/

Page 149: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 4 9

CIBERTEC CARRERAS PROFESIONALES

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

Page 150: 5to ciclo   desarrollo de aplicaciones web i

150

CARRERAS PROFESIONALES CIBERTEC

Page 151: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5 1

CIBERTEC CARRERAS PROFESIONALES

ANEXO 2: MANEJO DE MYIBATIS

Ejemplo de una aplicación con MyIbatis

ANEXOS

Page 152: 5to ciclo   desarrollo de aplicaciones web i

152

CARRERAS PROFESIONALES CIBERTEC

La Clase entidad

Page 153: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5 3

CIBERTEC CARRERAS PROFESIONALES

El Data Access Object para Vendedor

Page 154: 5to ciclo   desarrollo de aplicaciones web i

154

CARRERAS PROFESIONALES CIBERTEC

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

Page 155: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5 5

CIBERTEC CARRERAS PROFESIONALES

El Archivo de Configuración de MyIbatis • Se configura

los datos de la cadena de conexión • Se configura

los tipos de datos de los mappers • Se configura

la ubicación de los mappers

Page 156: 5to ciclo   desarrollo de aplicaciones web i

156

CARRERAS PROFESIONALES CIBERTEC

Page 157: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5 7

CIBERTEC CARRERAS PROFESIONALES

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>

ANEXOS

Page 158: 5to ciclo   desarrollo de aplicaciones web i

158

CARRERAS PROFESIONALES CIBERTEC

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>

Page 159: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 5 9

CIBERTEC CARRERAS PROFESIONALES

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

ANEXOS

Page 160: 5to ciclo   desarrollo de aplicaciones web i

160

CARRERAS PROFESIONALES CIBERTEC

<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>

Page 161: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 6 1

CIBERTEC CARRERAS PROFESIONALES

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>

Page 162: 5to ciclo   desarrollo de aplicaciones web i

162

CARRERAS PROFESIONALES CIBERTEC

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"

Page 163: 5to ciclo   desarrollo de aplicaciones web i

D E S A R R O L L O D E A P L I C A C I O N E S W E B I 1 6 3

CIBERTEC CARRERAS PROFESIONALES

Ibatis 2.0:

jdbcType="NUMBER"

MyIbatis 3.0:

jdbcType="NUMERIC"

Stored procedures

• 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"/>

Page 164: 5to ciclo   desarrollo de aplicaciones web i

164

CARRERAS PROFESIONALES CIBERTEC

Dynamic SQL

Ibatis 2.0:

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

MyIbatis 3.0:

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