Académique Documents
Professionnel Documents
Culture Documents
CARRERAS PROFESIONALES
CIBERTEC
NDICE
Presentacin Red de contenidos Unidad de aprendizaje 1: Modelo Vista Controlador Patrn MVC
1.1 Tema 1
Pgina
5 6
: Fundamentos de Struts 2
9 9 13 29 51 63
1.1.1. : Arquitectura y Configuracin de aplicaciones 1.1.2. : La clase Action 1.1.3. : Libreras de etiquetas de Struts 2 1.1.4. : Internacionalizacin I18N 1.2 Tema 2
63
de datos
1.2.2. : Librera de Etiquetas de Struts 2 Principales
72
componentes
1.2.3. : Patrn Composite View Struts 2 Tiles
87
: Introduccin a IBATIS
2.1.1. : IBATIS Introduccin 2.1.2. : Operaciones bsicas de acceso a base de datos con
IBATIS
2.2 Tema 4
2.2.1. : Otras operaciones y caractersticas de IBATIS 2.2.2. : Tpicos avanzados de IBATIS e Integracin con
Struts 2
139
CIBERTEC
CARRERAS PROFESIONALES
141
herramienta Ireport
3.2 Tema 6
: Struts 2 y JasperReport
CARRERAS PROFESIONALES
CIBERTEC
PRESENTACIN
Desarrollo de Aplicaciones Web I pertenece a la lnea de Programacin y Desarrollo de Aplicaciones. Es un curso de especialidad slo en la carrera de Computacin e Informtica. Permite al estudiante concretizar proyectos informticos web, aplicando conocimientos previos aprendidos en diferentes cursos y poniendo en prctica la teora adquirida. De esta manera, consolida conocimientos de diversos cursos de especialidad. Es prctico y desarrollado en laboratorio. Se implementarn soluciones web que utilizarn los Frameworks Struts 2 e IBATIS en forma combinada.
El manual para el curso ha sido diseado 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 sesin, que le permitirn reforzar lo aprendido en la clase.
El curso es eminentemente prctico y se desarrolla ntegramente en laboratorio. En primer lugar, se inicia con el reconocimiento de los principales patrones de arquitectura de software, destacndose el patrn Model View Controller (MVC). Luego, contina con la presentacin del Framework MVC Struts 2. Se profundiza en sus principales caractersticas y componentes. Despus, se desarrollan conceptos de persistencia de datos utilizando para ello el Framework IBATIS. Por ltimo, se concluye con la elaboracin de reportes empresariales, utilizando la herramienta IReport, el lenguaje jasperReport e integrndolos a aplicaciones web creadas con Struts 2.
CIBERTEC
CARRERAS PROFESIONALES
RED DE CONTENIDOS
Introduccin a IBATIS
Tema 5 JasperReport
CARRERAS PROFESIONALES
CIBERTEC
UNIDAD DE APRENDIZAJE
TEMARIO 1.1 Tema 1 : Fundamentos de Struts 2 1.1.1. : Arquitectura y Configuracin de aplicaciones 1.1.2. : La clase Action 1.1.3. : Libreras de etiquetas de Struts 2 1.1.4. : Internacionalizacin I18N
1.2 Tema 2 : Acceso optimizado a base de datos y otras caractersticas de Struts 2 1.2.1. : Uso de un Pool de conexiones para acceso a la fuente de datos 1.2.2. : Librera de Etiquetas de Struts 2 Principales componentes. 1.2.3. : Patrn Composite View Struts 2 Tiles
ACTIVIDADES PROPUESTAS
Los alumnos implementan una aplicacin web bsica, utilizando las principales caractersticas del framework MVC Struts 2.
CIBERTEC
CARRERAS PROFESIONALES
Figura 1.1
Una caracterstica tpica de la capa View de Struts 2 es el uso de unos componentes especiales denominados Results. stos normalmente son representados por una pgina JSP; sin embargo, puede constituir, tambin, flujos de bytes, objetos del framework Tiles, etc.
CARRERAS PROFESIONALES
CIBERTEC
encuentra registrado en el archivo de configuracin XML de Struts 2. ste tiene por defecto el nombre struts.xml. El componente invocado, normalmente un Action de Struts 2, instanciar y/o utilizar diversos objetos de negocio para concretar la tarea solicitada. Segn el resultado que retorne el componente Action, la capa Controller derivar la respuesta generada a un objeto Result (normalmente una pgina JSP).
1.1.1.1. Ejercicio 1: Aplicacin web bsica de Struts 2 Se probar una aplicacin web con los componentes mnimos 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 aplicacin web de prueba, que cuenta con las caractersticas mnimas para que pueda ser ejecutada. Esta aplicacin 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 continuacin:
Notas:
CIBERTEC
CARRERAS PROFESIONALES
10
1) El principal archivo de configuracin del Framework es el archivo struts.xml. En l, se registrarn sus principales componentes. Se inicia esta sesin con el registro de la clase Action. 2) Puede observar las libreras mnimas con las que todo proyecto basado en Struts 2 debera contar. Dentro de ellas, destaca el archivo struts2-core-2.1.8.1.jar.
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
Notas: 1) Note el registro del filtro controlador del framework Struts 2. Este componente atrapar todas las solicitudes (request) generadas desde un cliente, dado que tiene como alias /*.
CARRERAS PROFESIONALES
CIBERTEC
11
CIBERTEC
CARRERAS PROFESIONALES
12
Se detalla, a continuacin, un ejercicio, en el cual se apreciarn los principales componentes de la arquitectura MVC utilizando Struts 2.
1.1.2.1. Ejercicio 1: Funcionalidad de Logueo Versin 1 Se simular la funcionalidad de logueo con los componentes bsicos del framework Struts 2 y sin acceso a base de datos.
a) Paso 1: Copiar las principales libreras y archivos configuracin al proyecto web funcionalidadLogueov1_Inicial
de
CARRERAS PROFESIONALES
CIBERTEC
13
Notas: 1) Observe que solo se puede copiar el archivo struts.xml dentro de la carpeta src, utilizando la vista Navigator. 2) Distinga las principales libreras y archivos de configuracin en las ubicaciones correctas: libreras en la carpeta lib y archivo de configuracin struts.xml en la carpeta src junto a los archivos fuente.
Notas: 1) Agregue el paquete aprendamos.java.action y, dentro de l, genere la clase LogueoAction. La clase LogueoAction debe contar con la siguiente lgica:
CIBERTEC
CARRERAS PROFESIONALES
14
package aprendamos.java.action; public class LogueoAction { private String usuario; private String clave;
public String getUsuario() { return usuario; } public void setUsuario(String usuario) { this.usuario = usuario; } public String getClave() { return clave; } public void setClave(String clave) { this.clave = clave; } public String execute(){ String vista="exito"; return vista; } }
<action name="logueo" class="aprendamos.java.action.LogueoAction" > <result name="error" <result name="exito" </action> </package> >/logueo.jsp </result> >/bienvenida.jsp </result>
Notas: 1) El alias de la clase action es logueo; por lo tanto, debe modificar el archivo logueo.jsp. Ya no invocar a la clase LogueoServlet sino a LogueoAction.
CARRERAS PROFESIONALES
CIBERTEC
15
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
versin 1
1.1.2.2. Ejercicio 2: Funcionalidad de Logueo Versin 2 Se efecta la funcionalidad de logueo con los componentes bsicos del framework e implementando los patrones de diseo DAO (Data Access Object), Service y Business Delegate.
a) Paso 1: Modificar la clase MySqlClienteDAO y verificar su correcta relacin con las clases que implementan el patrn de diseo DAO.
CIBERTEC
CARRERAS PROFESIONALES
16
Dentro de la clase MySqlClienteDAO, debe modificar el mtodo buscaPorUsuario. Complete el cdigo con la lgica mostrada a continuacin:
//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();
El patrn de diseo DAO (Data Access Object) permite que un componente pueda acceder a diferentes orgenes 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 podran contar con DAOs para acceder a otros orgenes 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:
public interface ClienteDAO {
public int registraCliente(ClienteDTO objCliente) throws Exception; public ClienteDTO buscaPorUsuario(String usuario) throws Exception; . . . }
CARRERAS PROFESIONALES
CIBERTEC
17
Una interface permite exponer al mundo las operaciones de la clase que la implementa. Verifique si MySqlClienteDAO es retornado por la fbrica de DAOs para MySql:
public class MySqlDAOFactory extends DAOFactory { // Esta es una fabrica que crea DAOs especificos para Mysql
@Override public ClienteDAO getClienteDAO() { // TODO Auto-generated method stub return new MySqlClienteDAO(); }
public abstract class DAOFactory { public public public public public static static static static static final final final final final int int int int int MYSQL = 1; ORACLE = 2; DB2 = 3; SQLSERVER = 4; XML = 5;
1
// Existir un mtodo por cada DAO que pueda ser creado. // Ejemplo: //public abstract ArticuloDAO getArticuloDAO(); // registramos nuestros daos public abstract ClienteDAO getClienteDAO(); //public abstract ProductoDAO getProductoDAO();
public static DAOFactory getDAOFactory(int whichFactory){ switch(whichFactory){ case MYSQL: return new MySqlDAOFactory(); case XML: return new XmlDAOFactory(); case ORACLE: return new OracleDAOFactory();
CIBERTEC
CARRERAS PROFESIONALES
18
Notas: 1) El registro de la clase MySqlClienteDAO es la creacin de un mtodo abstracto en la clase DAOFactory que retorna a la interface que implementa MySqlClienteDAO.
2
public class LogueoService implements LogueoService_I { // Referenciamos a la fabrica de daos para mysql DAOFactory fabrica = DAOFactory.getDAOFactory(DAOFactory.MYSQL); // Referenciamos al dao de la entidad cliente ClienteDAO objClienteDAO = fabrica.getClienteDAO();
public ClienteDTO validaUsuario(ClienteDTO cliente) throws Exception { // aqui podriamos tener mas logica return objClienteDAO.buscaPorUsuario(cliente.getUsuario()); } }
CARRERAS PROFESIONALES
CIBERTEC
19
Notas: 1) Agregue el paquete aprendamos.java.action y dentro de l genere la clase LogueoAction. 2) Un servicio es un componente, que pertenece a la capa Model del patrn de diseo MVC. Representa, en la programacin, el inicio de la lgica de negocio. Por cada caso de uso de sistema identificado en la aplicacin, se debe implementar un servicio. ste puede invocar a uno o ms DAOs.
Debe exponer las operaciones de la clase LogueoService; por lo tanto, debe crear la interface LogueoService_I
public interface LogueoService_I { public abstract ClienteDTO validaUsuario(ClienteDTO cliente) throws Exception; }
CIBERTEC
CARRERAS PROFESIONALES
20
2
public class PaqueteBusinessDelegate { private PaqueteBusinessDelegate() { // TODO Auto-generated constructor stub } public static LogueoService_I getLogueoService(){ return new LogueoService(); } // agregar aqui mas llamadas a otros servicios
Notas: 1) Dentro del paquete aprendamos.java.service, genere la clase PaqueteBusinessDelegate. 2) Por cada paquete de un modelo de anlisis, 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 lgica de negocio, desde la clase LogueoService, y crear la sesin web.
Genere, dentro de la clase LogueoAction, el atributo mensaje para poder visualizar posibles mensajes de error en la capa de presentacin. No debe olvidar crear los mtodos setter y getter para el nuevo atributo.
public String getMensaje() { return mensaje; } public void setMensaje(String mensaje) { this.mensaje = mensaje; }
CARRERAS PROFESIONALES
CIBERTEC
21
Agregue la lgica que permitir validar los datos ingresados y almacenarlos en la sesin 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 objUsuario=null; try { objUsuario = logueoservice.validaUsuario(usuarioCandidato); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if(objUsuario!=null){ if(objUsuario.getClave().equals(this.getClave())){ // creamos la sesion web al estilo struts 2 Map<String,Object> lasesion= ActionContext.getContext().getSession(); lasesion.put("b_usuario", objUsuario);
}else{ vista="error"; this.setMensaje( "Lo sentimos, la clave es incorrecta"); } }else{ vista="error"; this.setMensaje("Es una pena, el usuario no existe!"); } return vista; }
CIBERTEC
CARRERAS PROFESIONALES
22
Recuerde que debe utilizar Expression Language (EL) en el JSP logueo.jsp para visualizar el mensaje de error definido en la clase LogueoAction.
<tr> <td class="error general"> <!-- podemos visualizar el mensaje de error usando EL --> ${requestScope.mensaje} </td> </tr>
Recuerde que debe utilizar Expression Language (EL) en el JSP bienvenida.jsp para visualizar los datos del cliente cargados en la sesin web.
<tr> <td class="error general"> <!-- podemos visualizar el mensaje de error usando EL --> ${requestScope.mensaje} </td> </tr>
CARRERAS PROFESIONALES
CIBERTEC
23
CIBERTEC
CARRERAS PROFESIONALES
24
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 travs de la key struts.custom.i18n.resources, se define la ubicacin 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.
CARRERAS PROFESIONALES
CIBERTEC
25
# Definiremos keys y sus respectivos valores # Una key es un identificador asociado a alguna descripcion #keys para el logueo : completar Pagina de Inicio - Que facil es JEE :):) logueo.titulo = logueo.mensaje.error.usuario=Lo sentimos, el usuario ingresado no existe :( logueo.mensaje.error.clave=Es una pena, la clave ingresada no
c) Paso 3: Referenciar las keys dentro de la clase LogueoAction Para poder referenciar las keys, la clase LogueoAction debe heredar de la clase ActionSupport. Esto permitir incluir funcionalidad adicional dentro de la misma.
package aprendamos.java.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.LogueoService_I; import aprendamos.java.service.PaqueteBusinessDelegate; public class LogueoAction extends ActionSupport {
CIBERTEC
CARRERAS PROFESIONALES
26
<s:form action="logueo"
method="post"
>
<table > <tr class="etiqueta" > <td colspan="2" > <img alt="El loguito" src="imagenes/logo_tiny.png" </td> </tr> <tr class="etiqueta" > <td> <fmt:message key="logueo.usuario" /> </td> <td> <s:textfield name="cliente.usuario" /> </td> </tr> <tr class="etiqueta" > <td > <fmt:message key="kclave" /> </td> <td> <s:password name="cliente.clave" /> </td> </tr> <tr> <td colspan="2" align="right" > <s:submit name="boton01" value="Ingresar" type="submit" /> </td> </tr> <tr> <td class="error general"> ${requestScope.mensaje} </td> </tr> <tr> <td > <fmt:message key="logueo.imagen" /> </td> </tr>
>
</table> </s:form>
CARRERAS PROFESIONALES CIBERTEC
27
Note que se han modificado los nombres de los campos usuario y clave por cliente.usuario y cliente.clave. e) Paso 5: Referenciar a los campos cliente.usuario y cliente.clave dentro de la clase LogueoAction Agregue el atributo cliente en la clase LogueoAction.
public class LogueoAction extends ActionSupport {
private ClienteDTO cliente=null; public ClienteDTO getCliente() { return cliente; } public void setCliente(ClienteDTO cliente) { this.cliente = cliente; }
ClienteDTO objUsuario=null; try { objUsuario = logueoservice.validaUsuario(usuarioCandidato); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); Notas: } if(objUsuario!=null){
if(objUsuario.getClave().equals(this.getCliente().getClave())){
CIBERTEC CARRERAS PROFESIONALES
28
1) Los datos son obtenidos a partir del nuevo atributo cliente. 2) Se obtienen nuevamente los datos a partir del atributo cliente. Esta vez invocando al mtodo getCliente().
f)
CARRERAS PROFESIONALES
CIBERTEC
29
CIBERTEC
CARRERAS PROFESIONALES
30
1.1.3.2. Ejercicio 2: Funcionalidad Registro de cliente Se implementa la funcionalidad indicada, haciendo uso de de las utilidades incluidas en el framework para procesar archivos (en el ejemplo la imagen del cliente) a travs de un formulario HTML y gestionarlos dentro de la aplicacin web implementada. a) Paso 1: Importar el proyecto FuncionalidadRegistraImagen_Inicial.war web
Notas: 1) Note que, dentro del proyecto, cuenta con el script de base de datos FacilitoBaseDatos.sql. En l, se debe verificar que la tabla tbcliente cuenta con un tipo de dato adecuado para almacenar un archivo de cualquier modelo.
CARRERAS PROFESIONALES
CIBERTEC
31
b) Paso 2: Verificar que la tabla tbcliente cuente con un campo de tipo longblog
CREATE DATABASE IF NOT EXISTS facilito; USE facilito; --- Definition of table `tbcliente` -DROP TABLE IF EXISTS `tbcliente`; CREATE TABLE `tbcliente` ( `nombre` varchar(100) DEFAULT NULL, `sueldo` double DEFAULT NULL, `sexo` char(1) DEFAULT NULL, `fecnac` datetime DEFAULT NULL, `usuario` varchar(15) NOT NULL DEFAULT '', `clave` varchar(15) NOT NULL DEFAULT '', `foto` longblob DEFAULT NULL, PRIMARY KEY (`usuario`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
Notas: 1) Observe que, en el campo foto, se almacenar la imagen asociada al cliente que registrar en su aplicacin web.
CIBERTEC
CARRERAS PROFESIONALES
32
Dentro de la pgina nuevoCliente.jsp, se debe modificar el formulario HTML. Complete el cdigo con la lgica mostrada a continuacin:
<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> Fotografa: </td> <td> <s:file name="cliente.foto" </tr> <tr class="control" > <td align="right" > <input type="submit" name="boton01" value="Registrar" > </td> </tr> </table> </s:form>
/>
</td>
Notas: 1) Debe utilizar el atributo enctype del formulario con el valor multipart/form-data. De esta manera,se habilita el formulario para soportar campos tipo File. 2) Agregue la etiqueta file de Struts 2., cuyo nombre es cliente.foto, es decir, har referencia a un objeto de nombre cliente que cuente con un atributo llamado foto.
CARRERAS PROFESIONALES
CIBERTEC
33
Notas: 1) El alias ingresaCliente fue definido en el formulario de la pgina nuevoCliente.jsp. Note que al invocar este alias se ejecutar dentro de la clase ClienteAction el mtodo registrar.
package aprendamos.java.action; import java.util.List; import aprendamos.java.bean.ClienteDTO; import aprendamos.java.service.ClienteService_I; import aprendamos.java.service.PaqueteBusinessDelegate; public class ClienteAction { // creamos un atributo de tipo Lista de Clientes ClienteDTO cliente; List<ClienteDTO> clientes;
...
CIBERTEC
CARRERAS PROFESIONALES
34
...
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; }
3 4
Notas: 1) Se ha definido la variable cliente de tipo ClienteDTO. De manera automtica, el Framework instancia el objeto y almacena en l los datos que llegan desde la pgina nuevoCliente.jsp. Note que en la pgina 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 lgica de negocio y expone las operaciones que puede realizar la clase ClienteAction. 3) Note que el mtodo registraCliente recibe como parmetro el objeto cliente. Dentro de l, deben existir los campos necesarios para poder gestionar la imagen del cliente seleccionada en la pgina nuevoCliente.jsp 4) Una vez registrado el nuevo cliente se blanquea el atributo nombre del objeto cliente y se invoca la funcionalidad de listado antes de retornar a la vista respectiva.
CARRERAS PROFESIONALES
CIBERTEC
35
f)
private static final long serialVersionUID = 1L; private private private private private private String nombre; Date fecnac; String sexo; double sueldo; String usuario; String clave;
1 2
private File foto; private String fotoContentType; private String fotoFileName; private InputStream isFoto; public String getFotoContentType() { return fotoContentType; } public void setFotoContentType(String fotoContentType) { this.fotoContentType = fotoContentType; }
. . .
Notas: 1) Dado que en la pgina 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, tambin, por requerimiento del Framework, definir los campos fotoContentType y fotoFileName. Ambos se cargarn de manera automtica y proporcionarn importante informacin relacionada con la variable foto. Adicionalmente, se define la variable isFoto de tipo InputStream, debido a que sta ser utilizada por el componente MySqlClienteDAO en el registro de la imagen en la tabla tbcliente.
CIBERTEC
CARRERAS PROFESIONALES
36
g) Paso 7: Modificar la clase ClienteService La clase ClienteService debe contar con la siguiente lgica en el mtodo registraElCliente:
public int registraElCliente(ClienteDTO objCliente) throws Exception { // aqui agremos un poco de logica // como sabemos que el atributo isFoto esta llegando nulo // lo generamos a partir del atributo foto (de tipo File) if(objCliente.getFoto()!=null){ InputStream tempo = new FileInputStream(objCliente.getFoto()); objCliente.setIsFoto(tempo); } return objClienteDAO.registraCliente(objCliente); }
Notas:
1) Si el cliente seleccion en la pgina 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 mtodo registraElCliente debe ser expuesto registrndolo en la interface ClienteService_I. La clase ClienteService implementa la interface ClienteService_I.
CARRERAS PROFESIONALES
CIBERTEC
37
h) Paso 8: Modificar la clase MySqlClienteDAO La clase MySqlClienteDAO debe implementar la siguiente lgica en el mtodo registraCliente:
public int registraCliente(ClienteDTO objCliente) throws Exception{ int resultado =0; Connection cn = MySqlDBConn.obtenerConexion(); String sql = "insert into tbcliente(nombre,sueldo,sexo,fecnac," + "usuario,clave,foto) values (?,?,?,?,?,?,?)"; PreparedStatement pst = cn.prepareStatement(sql); // 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()); }
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.
CIBERTEC
CARRERAS PROFESIONALES
38
pst.setBinaryStream(7, null,0); Sin embargo, si el valor del atributo es diferente de null, registra la imagen, tomando como base al atributo de tipo InputStream isFoto: pst.setBinaryStream(7, objCliente.getIsFoto(), objCliente.getIsFoto().available());
El mtodo available() de un objeto de tipo InputStream retorna la cantidad de bytes (el tamao), en este caso, de la imagen a insertar en la tabla. De esta manera, se enva como tercer parmetro del mtodo setBinaryStream().
CARRERAS PROFESIONALES
CIBERTEC
39
i)
CIBERTEC
CARRERAS PROFESIONALES
40
CARRERAS PROFESIONALES
CIBERTEC
41
Al hacer clic sobre el botn Registrar, se grabar un nuevo registro en la base de datos y se visualizar nuevamente el listado de Clientes.
CIBERTEC
CARRERAS PROFESIONALES
42
Se puede verificar el correcto registro de la imagen, utilizando la herramienta MySql Query Browser:
Notas: 1) Al hacer clic sobre la lupa, visualizar en una nueva ventana la imagen registrada en la tabla tbcliente.
j)
CARRERAS PROFESIONALES
CIBERTEC
43
Cuando se internacionaliza una aplicacin, 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, imgenes y botones estn en el lenguaje correcto, pero los nmeros y fechas no son formateados correctamente, sta ser una experiencia desagradable para el usuario. Asegurar que una aplicacin puede soportar mltiples lenguajes y regiones solo es el primer paso. Se deben crear versiones localizadas de la aplicacin para cada lenguaje especfico y regin que debe soportar. Afortunadamente, aqu es donde los beneficios de I18N en la plataforma java se ejecutan. Para aplicaciones que estn siendo apropiadamente internacionalizadas, todo el trabajo para soportar nuevos lenguajes o naciones, son externas al cdigo fuente. Una clase locale es una regin (usualmente geogrfica, pero no necesariamente) que comparte personalizaciones, cultura y lenguaje. Aplicaciones que son escritas para una sola localizacin son comnmente referenciadas como miopes. Localizacin (L10N) es el proceso de adaptar su aplicacin, la cual ha sido internacionalizada apropiadamente con la especfica. Para aplicaciones donde el soporte I18N no ha sido planeado o incorporado, esto usualmente significa cambios de texto, imgenes y mensajes que son incluidos dentro
CIBERTEC
CARRERAS PROFESIONALES
44
del cdigo fuente. Despus de los cambios aplicados, ste debe de ser recopilado. Imagine hacer eso cada vez para una nueva localizacin soportada. De acuerdo con Richard Gillam, miembro del Grupo de Tecnologa Unicote (autor del diseo de muchas de las libreras Java para soporte I18N), los usuarios esperarn que los productos que utilizan trabajen para ellos en su lenguaje nativo. Se pueden obtener experiencias negativas si los usuarios no estn 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 imgenes implementado. La aplicacin web soportar el uso de tres idiomas distintos.
web
Notas: 1) Note que, dentro del proyecto, cuenta con el paquete aprendamos.java.recursos y dentro de l cuenta con tres archivos de recursos (archivos .properties) que soportan los
CARRERAS PROFESIONALES
CIBERTEC
45
idiomas italiano (it), portugus (pt) y espaol. 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 cdigos ISO 639-1.
b) Paso 2: Editar los archivos .properties. Se crearn, como ejemplos, las keys que sern utilizadas en la pgina bienvenida.jsp.
#keys para la pagina de bienvenida key.usuario = Usurio: key.nombre = Nome: key.fecnac = data de nascimento: key.sexo = sexo: key.saludo = Bem-vindo Caro usurio, seus dados so:
#keys para el menu menu.bienvenida = Ir pgina inicial menu.logueo = V para a entrada menu.listado = Ir para a lista
CIBERTEC
CARRERAS PROFESIONALES
46
#keys para la pagina de bienvenida key.usuario = Utente: key.nombre = Nome: key.fecnac = Data di Nascito: key.sexo = sesso: key.saludo = Benvenuto Caro utente, i dati sono:
#keys para el menu menu.bienvenida = Vai alla pagina di benvenuto menu.logueo = Ir al logueini menu.listado = Ir al listadini
Defina las keys para el idioma espaol en el archivo MisRecursos.properties (archivo de recursos por defecto).
#keys para la pagina de bienvenida key.usuario = Usuario: key.nombre = Nombre: key.fecnac = Fecha de Nacimiento: key.sexo = Sexo: key.saludo= Bienvenido estimado usuario, sus datos son:
#keys para el menu menu.bienvenida = Ir a la pgina de Bienvenida menu.logueo = Ir al logueo menu.listado = Ir al listado
CARRERAS PROFESIONALES
CIBERTEC
47
Notas: 1) El archivo de recursos por defecto es aquel que no tiene cdigo ISO asociado a un idioma en particular. Cuando se seleccione en la aplicacin web un idioma que no haya sido configurado en ningn archivo de recursos, automticamente, struts 2 recupera las keys del archivo de recursos por defecto.
<body class="titulo" > <img alt="" src="imagenes/logo.png" border="0" > <table> <tr><td> <a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=it"> <img src="imagenes/banderaItalia.png" alt="Italiana" border="0"> </a> </td> <td><a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=pt"> <img src="imagenes/BanderaBrasil.png" alt="Portugues" border="0"> </a> 2 </td> <td><a href="${pageContext.request.contextPath}/a_bienvenida?request_loc ale=es"> <img src="imagenes/banderaPeru.png" alt="Espaol" border="0"> </a> </td> </tr> </table> </body>
Notas: 1) Struts 2 soporta cuenta con un parmetro especial llamado request_locale. Cuando se utiliza ste, de manera automtica, se configura sul valor como el idioma actual de la aplicacin web. 2) Es recomendable utilizar variables al referenciar cualquier recurso dentro de una aplicacin web. En el ejemplo, en
CIBERTEC
CARRERAS PROFESIONALES
48
lugar de colocar el nombre de la aplicacin web, se realiza lo siguiente: FuncionalidadRegistraImagenI18N_Inicial Se coloca un expression language equivalente:
${pageContext.request.contextPath}
<action name="a_bienvenida" > <result > /bienvenida.jsp </result> </action> <action name="a_logueo" > <result > /logueo.jsp </action> . . .
Notas: 1 </result>
1) Note que el action a_bienvenida es solo un action de atajo que invoca automticamente a la pgina bienvenida.jsp. Se puede crear dentro de la aplicacin mltiples actions de atajo para invocar a travs de links a las pginas JSP.
e) Paso 5: Recuperar las keys del men y de la pgina de bienvenida, utilizando la etiqueta <s:text> de struts 2.
CARRERAS PROFESIONALES
CIBERTEC
49
>
1
<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> . . .
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 librera, utilizando la siguiente directiva: <%@ taglib prefix="s" uri="/struts-tags" %>
CIBERTEC
CARRERAS PROFESIONALES
50
. . .
<table class="control" > <tr> <td colspan="2" > <s:text name="key.saludo" /> </td> </tr> <!-recuperamos los atributos del usuario logueado utilizando EL (Expression Language) --> 1 <tr> <td><s:text name="key.usuario" /> </td> <td>${sessionScope.b_usuario.usuario}</td> </tr> <tr> <td> <s:text name="key.nombre" /> </td> <td>${sessionScope.b_usuario.nombre}</td> </tr> <tr> <td> <s:text name="key.fecnac" /> </td> <td>${sessionScope.b_usuario.fecnac}</td> </tr> <tr> <td> <s:text name="key.sexo" /> </td> <td>${sessionScope.b_usuario.sexo}</td> </tr> </table> . . .
CARRERAS PROFESIONALES
CIBERTEC
51
f)
Se debe visualizar la pantalla de bienvenida y los enlaces a los idiomas definidos en la pgina cabecera.jsp. Seleccione la bandera italiana.
CIBERTEC
CARRERAS PROFESIONALES
52
Visualizar la siguiente pantalla con el men y la bienvenida en idioma italiano. Seleccione la bandera de Brasil.
Se visualizar la siguiente pantalla con el men y la bienvenida en idioma portugus. Finalmente, seleccione la bandera del Per.
CARRERAS PROFESIONALES
CIBERTEC
53
CIBERTEC
CARRERAS PROFESIONALES
54
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.
web
CARRERAS PROFESIONALES
CIBERTEC
55
Notas: 1) Observe que, dentro del proyecto, cuenta en la carpeta META-INF con el archivo context.xml. En l, se debe crear la configuracin del pool de conexiones que utilizar para acceder a una base de datos.
CIBERTEC
CARRERAS PROFESIONALES
56
<?xml version="1.0" encoding="UTF-8"?> <!-- Este es un comentario --> <!-- la etiqueta Context representa una zona de memoria que se crea cuando levantamos la aplicacion web. Esta zona de memoria estara "viva" mientras no reiniciemos la aplicacion web -->
<Context path="/jee-web"
>
<!-- registramos un recurso en esta zona de memoria. En este caso un pool de conexiones --> <Resource name="jdbc/sisepuede" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="root" password="" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/facilito"/>
1 2
</Context>
Notas: 1) jdbc/sisepuede es el nombre del pool de conexiones que utilizar para referenciar a la base de datos. 2) El nmero mximo de conexiones activas es 100 en el ejemplo. Este valor debe ser calculado para cada aplicacin web sobre la base de la experiencia y el trfico que normalmente se soporte. En algunos casos, se tendr la necesidad de incrementar o redecir este valor por defecto. 3) El mximo tiempo de espera, 10000, est expresado en milisegundos. En este ejemplo, se esperar, como mximo, 10 segundos para obtener una conexin disponible (de las 100 existentes). De no conseguirla, se producira un error.
CARRERAS PROFESIONALES
CIBERTEC
57
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
Notas: 3) Debe importar el paquete javax.naming.*, ya que en l se encuentran las clases para utilizar JNDI y acceder al pool de conexiones. 4) Debe importar el pauete javax.sql.* debido a que dentro de l se encuentra la clase DataSource. sta representa un pool de conexiones en java.
CIBERTEC
CARRERAS PROFESIONALES
58
. . .
public static Connection obtenerConexion(){ // 1. Para referenciar al pool creamos un contexto JNDI // Java Naming and Directory Interface Connection cn=null; try { // creamos el contexto JNDI Inicial, JDNI valida los nombres , utiliza la infor de META INF para hacer un pool de conexiones., JNDI maneja nombres y objetos Context ctx = new InitialContext(); // ahora vamos a ubicar un nombre dentro // de este contexto, para ello usamos el // famoso metodo lookup. //Base standar JND String raizContexto ="java:comp/env/"; // 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; }
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 raz. Por lo tanto, para referenciar al pool, se pasar primero por el nombre raz. 2) A travs del mtodo lookup y utilizando el nombre raz del contexto, se referencia al pool de conexiones: jdbc/sisepuede.
CARRERAS PROFESIONALES
CIBERTEC
59
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 aplicacin web, quien solicita al servidor de base de datos las conexiones (en el ejemplo cien), que sern almacenadas en la memoria del servidor y que juntas constituyen el pool de conexiones.
CIBERTEC
CARRERAS PROFESIONALES
60
CARRERAS PROFESIONALES
CIBERTEC
61
Debe visualizar la pantalla de bienvenida con los datos del usuario logueado.
Tambin, se visualizar en la consola de Eclipse los mensajes del Logueo y el que se coloc en la clase MySqlDbConn: misin cumplida, se ha obtenido la conexin del pool.
CIBERTEC
CARRERAS PROFESIONALES
62
f)
CARRERAS PROFESIONALES
CIBERTEC
63
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 travs de un formulario HTML y el uso de un Action de Struts 2 que utiliza un nuevo tipo de Result: stream.
CIBERTEC
CARRERAS PROFESIONALES
64
Notas: 1) Debe modificar la pgina 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 pgina listado.jsp, debe crear un nuevo enlace para visualizar los datos del cliente seleccionado. Complete el cdigo con la lgica mostrada a continuacin:
. . .
<td align="center" > <s:url id="carga" action="cargaModificaCliente" > <s:param name="usuario" > ${elcli.usuario} </s:param> </s:url> <a </td> href="${carga}" > M </a>
. . .
CARRERAS PROFESIONALES
CIBERTEC
65
Notas: 1) Utilizando la etiqueta <s:url > defina un enlace que permitir invocar al alias cargaModificaCliente. Adicionalmente, determine el parmetro usuario utilizando la etiqueta <s:param>. Su valor es asignado usando el siguiente expression language (EL): ${elcli.usuario}
2) Culminado el cambio en listado.jsp, visualizar el enlace, tal como se muestra en la pantalla previa.
CIBERTEC
CARRERAS PROFESIONALES
66
<action name="cargaModificaCliente" class="aprendamos.java.action.ClienteAction" method="cargaModifica" > <result name="exito" >/modificaCliente.jsp </result> </action>
Notas: 1) El alias cargaModificaCliente fue referenciado en el enlace definido para modificar (M) de la pgina listado.jsp. Note que al invocar este alias se ejecutar dentro de la clase ClienteAction el mtodo cargaModifica.
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;
...
CARRERAS PROFESIONALES
CIBERTEC
67
...
public String cargaModifica(){ String vista="exito"; try { cliente= servicioCliente.buscaClientePorUsuario( this.getUsuario());
return vista; }
...
Notas: 1) Se ha definido la variable usuario de tipo String. Se definen tambin los mtodos setUsuario() y getUsuario(), respectivamente. De manera automtica, el Framework instancia el objeto y almacena en ste el parmetro usuario, que llega desde la pgina listado.jsp. . 2) Note que el mtodo buscaClientePorUsuario recibe como parmetro 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 pgina modificaCliente.jsp
CIBERTEC
CARRERAS PROFESIONALES
68
e) Paso 5: Verificar la clase MySqlClienteDAO La clase MySqlClienteDAO debe implementar la siguiente lgica en el mtodo buscaPorUsuario:
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; }
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 mtodo getBinaryStream del objeto ResultSet rs: rs.getBinaryStream(7)
CARRERAS PROFESIONALES
CIBERTEC
69
f)
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.
CIBERTEC
CARRERAS PROFESIONALES
70
En la pantalla mostrada, se visualizarn los datos asociados al cliente seleccionado. Sin embargo, no reconoce an la fotografa.
CARRERAS PROFESIONALES
CIBERTEC
71
Dentro de la pgina modificaCliente.jsp debe utilizar la etiqueta HTML <img> para visualizar la fotografa asociada al cliente mostrado:
. . .
<tr class="control" > <td> Fotografa: </td> <td> <s:file name="cliente.foto" /> <td> <img alt="Fotografia del Cliente:) " </td>
. . .
Notas: 1) Note cmo en el atributo src de la etiqueta <img> se hace referencia al alias cargaImagenCliente. Se enva adicionalmente el parmetro usuario con el valor ${cliente.usuario}.
CIBERTEC
CARRERAS PROFESIONALES
72
i)
<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>
Notas: 1) El alias cargaImagenCliente fue referenciado en la etiqueta <img> de la pgina modificaCliente.jsp. Note que al invocarlo se ejecutar dentro de la clase ImagenAction el mtodo recuperaImagenCliente. 2) Se utiliza un nuevo tipo de result: stream. A travs de l, la etiqueta <img> de la pgina modificaCliente.jsp visualizar la imagen a partir de un campo de tipo InputStream.
3) El campo imagenClienteRecuperada es el valor asociado al parmetro del result: inputName. ste debe ser de tipo InputStream y estar definido en el action ImagenAction.
CARRERAS PROFESIONALES
CIBERTEC
73
j)
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;
...
...
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; }
...
CIBERTEC
CARRERAS PROFESIONALES
74
Notas: 1) Se ha definido la variable imagenClienteRecuperada de tipo InputStream. sta es referenciada en el archivo struts.xml, en el registro del action ImagenAction. 2) El mtodo buscaClientePorUsuario retorna un objeto de tipo ClienteDTO que es asignado a la variable cli. 3) Se invoca el mtodo getIsFoto() de la variable cli para obtener la imagen recuperada de base de datos y asignarla a la imagenClienteRecuperada.
k) Paso 11: Ejecutar la aplicacin 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.
CARRERAS PROFESIONALES
CIBERTEC
75
En la pantalla mostrada, se visualizarn los datos asociados al cliente seleccionado. En esta oportunidad, s visualizar la fotografa asociada al cliente.
l)
Paso 12: Muy Bien!, ha culminado exitosamente la funcionalidad completa carga imagen.
CIBERTEC
CARRERAS PROFESIONALES
76
1.2.3.1. Ejercicio 1: Mantenimiento Completo con Tiles Sobre un mantenimiento completo e implementado con Struts 2, se harn las modificaciones necesarias para implementar el patrn Composite View. Para ello, se utilizar el framework Tiles y se integrar a la aplicacin web construida sobre Struts 2.
CARRERAS PROFESIONALES
CIBERTEC
77
Notas: 1) En general, las pginas JSP de la aplicacin se encontrarn dentro de carpetas especficas. En este ejemplo, se cuenta con dos tipos: Pginas. Para todas aquellas de la aplicacin web.
CIBERTEC
CARRERAS PROFESIONALES
78
Plantillas. Para las diferentes plantillas tiles sobre las cuales se distribuirn las pginas de la aplicacin web.
2) Para utilizar Tiles e integrarlo a struts 2, es necesario contar con las libreras de Tiles y el plug in de Struts 2 para sta. 3) El archivo de configuracin de tiles es tiles.xml y debe copiarse por defecto en la carpeta WEB-INF de la aplicacin web. 4) No todos los archivos JSP deben, necesariamente, estar dentro de una carpeta. En el ejemplo, la pgina logueo.jsp mantiene su ubicacin original: dentro de la carpeta WebContent.
b) Paso 2: Modificar el archivo web.xml Se deben agregar en el archivo web.xml las siguientes etiquetas:
<!-- registramos e l listener de strtus 2 titles --> <listener> <listener-class> org.apache.struts2.tiles.StrutsTilesListener </listener-class> </listener> ...
CARRERAS PROFESIONALES
CIBERTEC
79
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd"> <tiles-definitions> <definition name="d_bienvenida" template="/plantillas/diseno01.jsp"> <put-attribute <put-attribute <put-attribute <put-attribute
1 name="menu" value="/paginas/menu.jsp" /> name="pie" value="/paginas/pie.jsp" /> name="cabecera" value="/paginas/cabecera.jsp" /> name="body" value="/paginas/bienvenida.jsp" />
</definition> <definition name="d_listado" extends="d_bienvenida"> <put-attribute name="body" value="/paginas/listado.jsp" /> </definition> <definition name="d_nuevoCliente" extends="d_bienvenida"> <put-attribute name="body" value="/paginas/nuevoCliente.jsp" /> </definition> ...
3 2
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 estn referenciando a pginas JSP dentro de la carpeta pginas. sta debe existir y ah deben encontrarse las pginas referenciadas.
CIBERTEC
CARRERAS PROFESIONALES
80
... <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="false" /> <package name="default" namespace="/" extends="tiles-default"> <!-- creamos un action de atajo --> <action name="a_nuevoCliente" > <result type="tiles"> d_nuevoCliente </action> <action name="a_bienvenida" > <result type="tiles"> d_bienvenida </action> <action name="a_logueo" > <result > /logueo.jsp </action>
1
</result>
2
</result>
3
</result>
</result>
<!-- registramos nuestro primer action --> <action name="logueo" class="aprendamos.java.action.LogueoAction" > <result name="error" >/logueo.jsp </result> <result name="exito" type="tiles"> d_bienvenida </action> ...
</result>
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 pgina JSP, sino, ms bien, a un definition de tiles. 3) Para que un <result> pueda invocar a un definition de tiles es necesario indicar en su atributo type el valor tiles.
CARRERAS PROFESIONALES
CIBERTEC
81
Notas: 1) El archivo debe ser creado tal como se referenci en el archivo tiles.xml, es decir, dentro de una carpeta llada plantillas.
CIBERTEC
CARRERAS PROFESIONALES
82
f)
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 1 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-88591"> <title>Insert title here</title> </head> <body> <!-- en esta plantilla definimos el orden de distribucion de los puts del definition --> <table> <tr> <td colspan="2"><tiles:insertAttribute 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> ...
Notas: 1) Para poder utilizar las etiquetas de tiles dentro de la pgina JSP, es necesario referenciar a la librera de etiquetas tags-tiles. 2) Note cmo se ha creado una tabla con filas y columnas, dentro de las cuales, haciendo uso de la etiqueta <tiles:insertAttribute>, se insertan los diferentes puts definidos en el archivo tiles.xml.
CARRERAS PROFESIONALES
CIBERTEC
83
Notas: 1) Tal como se indic en el archivo tiles.xml, las pginas JSP deben estar dentro de una carpeta denominada pginas.
CIBERTEC
CARRERAS PROFESIONALES
84
<table> <tr> <td colspan="2" align="center" > <!-- aqui va la cabecera --> <jsp:include page="cabecera.jsp" </td> </tr> <tr> />
1
<td > <!-- aqui va el menu --> <jsp:include page="menu.jsp" </td> <!-- aqui va el cuerpo --> <td > ... />
Notas: 1) Dado que ahora se trabajar con Tiles, ya no es necesario tener directivas include dentro de los JSPs. Importante: De dejarlas, se duplicara la implementacin del patrn de diseo Composite View.
CARRERAS PROFESIONALES
CIBERTEC
85
i)
CIBERTEC
CARRERAS PROFESIONALES
86
j)
la
funcionalidad
CARRERAS PROFESIONALES
CIBERTEC
87
Resumen
Las etiquetas de struts 2 se encuentran agrupadas dentro de una sola librera: <%@ taglib prefix="s" uri="/struts-tags" %>
Las etiquetas de struts 2 son parte de la capa de presentacin dentro de una arquitectura MVC. Con Tiles, se puede, fcilmente, cambiar de una estructura de aplicacin a otra. A travs de ste, nicamente de plantillas, permite tener mayor flexibilidad al momento de una posible migracin.
Si desea saber ms acerca de estos temas, puede consultar las siguientes pginas: http://struts.apache.org/2.x/index.html Aqu encontrar importante documentacin oficial y ejemplos de uso del framework Struts 2 http://struts.apache.org/1.x/struts-tiles/ Aqu encontrar documentacin oficial sobre el uso de plantillas Tiles dentro de una aplicacin implementada con el framework Struts. Tambin, encontrar referencias para utilizar Tiles independientemente de Struts: Tiles 2.
CIBERTEC
CARRERAS PROFESIONALES
88
CARRERAS PROFESIONALES
CIBERTEC
89
UNIDAD DE APRENDIZAJE
TEMARIO 2.1 Tema 3 : Introduccin a IBATIS 2.1.1. 2.1.2. : IBATIS Introduccin : Operaciones bsicas de acceso a base de datos con IBATIS
2.2 Tema 4 : Otras operaciones con IBATIS 2.2.1. 2.2.2. : Otras operaciones y caractersticas de IBATIS : Tpicos avanzados de IBATIS e Integracin con Struts 2
ACTIVIDADES PROPUESTAS
Los alumnos implementan una aplicacin web bsica, utilizando las principales caractersticas del framework MVC Struts 2 y el framework IBATIS.
CIBERTEC
CARRERAS PROFESIONALES
90
B. Toda implementacin de Ibatis incluye los siguientes componentes: Data Mapper proporciona una forma sencilla de interaccin de datos entre los objetos Java y .NET y bases de datos relacionales. Data Access Object es una abstraccin que oculta la persistencia de objetos en la aplicacin y proporciona un API de acceso a datos al resto.
El marco de trabajo SQL Maps es muy tolerante, tanto con las malas implementaciones de los modelos de datos como con los modelos de objetos.
CARRERAS PROFESIONALES
CIBERTEC
91
A pesar de ello, es muy recomendable que se usen las mejores prcticas, tanto cuando se disee la base de datos (normalizacin apropiada, etc.) como el modelo de objetos. Al hacer esto, se garantizar un mejor rendimiento y un diseo ms claro.
2.1.1.1. Ejercicio 1: Funcionalidad IBATIS - Introduccin Se implementar una aplicacin web con los componentes bsicos para el correcto funcionamiento del framework IBATIS. a) Paso 1: Importar el archivo FuncionalidadIbatisIntro_Inicial.war
Notas: 1) Observe que debe contar con las libreras bsicas de IBATIS para integrar el framework a su aplicacin web.
CIBERTEC
CARRERAS PROFESIONALES
92
Notas: 1) SqlMapConfig.xml es el archivo de configuracin por excelencia de IBATIS. En l, se define, por ejemplo, el pool de conexiones a utilizar y otros archivos XML (llamados SqlMaps), que sern referenciados en la aplicacin 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 representacin en java como objeto del archivo SqlMapConfig.xml.
CARRERAS PROFESIONALES
CIBERTEC
93
<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> ...
2
Notas: 1) A travs 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 travs de la etiqueta <sqlMap>, se referencia a los archivos XML, que contienen las sentencias SQL para operar sobre las entidades que referencian. En el ejemplo, se referencian los archivos XML Cliente y Producto.
CIBERTEC
CARRERAS PROFESIONALES
94
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; } } ...
CARRERAS PROFESIONALES
CIBERTEC
95
<?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"
2
>
property="nombre" column="nombre" /> property="sueldo" column="sueldo" /> property="sexo" column="sexo" /> property="fecnac" column="fecnac" /> property="usuario" column="usuario" /> property="clave" column="clave" /> property="laFoto" column="foto" />
<!-- Definimos un operacion , el dao llamara a las operaciones por su ID --> <select id="ibatis_logueo" parameterClass="java.lang.String" resultMap="clienteRes"> select usuario,clave,nombre,sueldo,sexo,fecnac,foto from tbcliente where usuario = #value#; </select> ...
Notas: 1) A travs 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 travs de la etiqueta <select>, se puede utilizar SQL estndar para realizar consultas. Los parmetros simples que llegan a la consulta son referenciados, utilizando la sintaxis #value#
CIBERTEC
CARRERAS PROFESIONALES
96
public ClienteDTO buscaPorUsuario(String usuario) throws Exception{ //Metodo modificado para Ibatis ClienteDTO objClienteDTO=null; System.out.println("Validamos con ibatis"); SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance();
Notas: 1) A travs de la clase UtilSqlConfig, se crea una instancia de la clase SqlMapClient. En el ejemplo, el objeto sqlMap es la representacin en java del archivo SqlMapConfig. 2) Se invoca al mtodo queryForObject del objeto sqlMap. Se enva como parmetros lo siguiente: El nombre de la operacin que se desea ejecutar (definida en el archivo Cliente.xml) El cdigo de usuario a travs del cual se validar el logueo.
CARRERAS PROFESIONALES
CIBERTEC
97
CIBERTEC
CARRERAS PROFESIONALES
98
h)
Paso 8:
CARRERAS PROFESIONALES
CIBERTEC
99
Elementos Hijos
Mtodos
<insert>
All dynamic elements insert <selectKey> update <generate> (.NET delete only) All dynamic elements insert <generate> (.NET update only) delete All dynamic elements insert <generate> (.NET update only) delete
<update>
<delete>
<select>
Se desarrollan, a continuacin, diversos ejercicios en los que se utilizarn y describirn las principales etiquetas del Framework.
CIBERTEC
CARRERAS PROFESIONALES
100
Se implementar una aplicacin que permita ejecutar las operaciones bsicas de un mantenimiento, utilizando el framework IBATIS. a) Paso 1: Modificar el archivo Cliente.xml
. . . <resultMap
class="cli" id="clienteRes"
>
property="nombre" column="nombre" /> property="sueldo" column="sueldo" /> property="sexo" column="sexo" /> property="fecnac" column="fecnac" /> property="usuario" column="usuario" /> property="clave" column="clave" /> property="laFoto" column="foto" />
</resultMap>
1
<parameterMap class="java.util.Map" id="clienteMap" <parameter <parameter <parameter <parameter <parameter <parameter <parameter </parameterMap>
>
property="nombre" jdbcType="VARCHAR" /> property="sueldo" jdbcType="DOUBLE" /> property="sexo" jdbcType="CHAR" /> property="fecnac" jdbcType="DATETIME" /> property="usuario" jdbcType="VARCHAR" /> property="clave" jdbcType="VARCHAR" /> property="foto" jdbcType="BLOB" />
Notas: 1) Al utilizar la etiqueta <parameterMap>, se ha creado un prametro especial llamado clienteMap. ste ser enviado desde la clase DAO y estar representado por la clase java.util.Map. Note cmo se identifica cada campo de la clase Map con el tipo de dato al que se referir en la base de datos.
CARRERAS PROFESIONALES
CIBERTEC
101
<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
Notas: 1) Observe cmo la operacin ibatis_insertaCliente recibe como parmetro clienteMap definido en lneas previas. Los campos son automticamente asociados a las interrogantes de la sentencia SQL.
CIBERTEC
CARRERAS PROFESIONALES
102
b) Paso 2: Modificar la clase MySqlClienteDAO Se prepara la invocacin a las operaciones IBATIS definidas en el archivo Cliente.xml.
public int registraCliente(ClienteDTO objCliente) throws Exception{ System.out.println("Insertando con ibatis :) "); int resultado =0; SqlMapClient cliente = UtilSqlConfig.getSqlMapInstance(); // En vez de enviar objCliente, enviaremos una estructura // preparada para soportar un tipo LongBloB y registrar // el cliente con IBATIS HashMap<String, Object> map = new HashMap<String, Object>(); map.put("nombre", objCliente.getNombre()); map.put("sueldo", objCliente.getSueldo()); map.put("sexo", objCliente.getSexo()); map.put("fecnac", objCliente.getFecnac()); map.put("usuario", objCliente.getUsuario()); map.put("clave", objCliente.getClave()); // intento 01: asumimos que ibatis soporta como parametro // un arreglo de bytes // Asumimos que esta llegando la foto InputStream is = objCliente.getIsFoto(); byte[] losbytes = new byte[is.available()]; // a partir del inputStream cargamos el arreglo los bytes is.read(losbytes); map.put("foto", losbytes); cliente.insert("ibatis_insertaCliente",map); System.out.println("registro exitoso con IBATIS :) "); return resultado; } ...
Notas: 1) A partir del campo isFoto (de tipo InputStream), se prepara un arreglo de bytes, el cual se carga en el objeto map con el nombre foto. 2) Se invoca a la sentencia insert de IBATIS, pasndole como parmetros el nombre de la operacin a ejecutar y el objeto map. 2 1
CARRERAS PROFESIONALES
CIBERTEC
103
public List<ClienteDTO> listaPorNombre(String vnombre) throws Exception{ ArrayList<ClienteDTO> clientes= new ArrayList<ClienteDTO>(); /** Para manejar transacciones usar las clasese de Ibatis de sqlMapClient**/ System.out.println("Validamos con ibatis"); SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance(); clientes=(ArrayList<ClienteDTO>)sqlMap.queryForList("ibatis_cl ienteLista", "%"+vnombre+"%"); System.out.println("listado por nombre usando Ibatis");
Notas: 1) Se invoca al mtodo queryForList para ejecutar operaciones que retornen ms de un registro como resultado. Note que se enva la variable vnombre junto con los caracteres % a ser utilizados en la consulta definida en el archivo Cliente.xml (como parte del parmetro like).
CIBERTEC
CARRERAS PROFESIONALES
104
Ahora, seleccione el enlace Nuevo Cliente y registre uno nuevo con el botn Registrar.
CARRERAS PROFESIONALES
CIBERTEC
105
Se visualizar la siguiente ventana con el nuevo registro ingresado. En el ejemplo, se ha registrado al cliente Don Ramn.
CIBERTEC
CARRERAS PROFESIONALES
106
CARRERAS PROFESIONALES
CIBERTEC
107
<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>
continuacin,
ejercicios
con
procedimientos
2.2.1.1. Ejercicio 1: Registro de Clientes utilizando Stored Procedures Se implementar una aplicacin web que permita registrar los datos de un cliente (incluida su fotografa), utilizando IBATIS y Stored Procedures. a) Paso 1: Importar FuncionalidadIbatisProcedure_Inicial.war el archivo
CIBERTEC
CARRERAS PROFESIONALES
108
Notas: 1) Cuenta, en esta oportunidad, dentro de la carpeta bd con archivos adicionales dentro de los cuales destaca ps_nuevoCliente.sql. Este archivo contiene el stored procedure que deber crear en mysql. b) Paso 2: Ejecute el archivo sp_nuevoCliente.sql dentro de mysql
CREATE PROCEDURE `sp_nuevoCliente`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), in vfoto BLOB, inout resultado int ) BEGIN declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable = 0 then set resultado = 777; insert into tbcliente(nombre,sueldo,sexo,fecnac,usuario,clave,foto) values( vnombre, vsueldo, vsexo, vfecnac, vusuario, vclave, vfoto); else set resultado = 666; end if; END $$ ...
CARRERAS PROFESIONALES
CIBERTEC
109
Ejecute el stored procedure, utilizando la herramienta Mysql Query Browser (u otra equivalente)
Notas: 1) Se recibe como parmetro un campo de tipo BLOB. ste debe haber sido cargado previamente en la clase MySqlClienteDAO y reconocido por el archivo Cliente.xml. 2) Una vez ejecutado el script del stored procedure se debe visualizar su base de datos (en el ejemplo facilito) y el nombre del procedimiento creado.
CIBERTEC
CARRERAS PROFESIONALES
110
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; ...
2 1
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 operacin 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 operacin, retornar el valor 777, de lo contrario regresar a 666.
CARRERAS PROFESIONALES
CIBERTEC
111
<parameterMap class="java.util.Map" id="clienteMap" <parameter <parameter <parameter <parameter <parameter <parameter <parameter <parameter />
>
property="nombre" jdbcType="VARCHAR" mode="IN" /> property="sueldo" jdbcType="DOUBLE" mode="IN" /> property="sexo" jdbcType="CHAR" mode="IN" /> property="fecnac" jdbcType="DATETIME" mode="IN" /> property="usuario" jdbcType="VARCHAR" mode="IN" /> property="clave" jdbcType="VARCHAR" mode="IN" /> property="foto" jdbcType="BLOB" mode="IN" /> property="resultado" jdbcType="INT" mode="INOUT"
>
CIBERTEC
CARRERAS PROFESIONALES
112
e) Paso 5: Ejecute la aplicacin Seleccione la opcin Nuevo Cliente una vez realizado el listado de Clientes. Visualizar la siguiente pantalla:
CARRERAS PROFESIONALES
CIBERTEC
113
Insertando con ibatis :) resultado antes de insertar: 0 resultado despues de insertar: 777 invocacion exitosa a SP IBATIS :) dentro del listaCliente del Service Validamos con ibatis listado por nombre usando Ibatis 23/01/2011 05:38:41 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger INFO: Removing file cliente.foto C:\Users\plgarcia\workspace\.metadata\.plugins\org.eclipse.wst .server.core\tmp0\work\Catalina\localhost\FuncionalidadIBatisP rocedure_Final\upload__2a3c5961_12db5077826__8000_00000006.tmp 23/01/2011 05:38:41 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger warn
f) Paso 6: Muy Bien!, ha culminado exitosamente la
CIBERTEC
CARRERAS PROFESIONALES
114
a) Paso 1: Ubique los Stored Procedures relacionados con la actualizacin de datos de un cliente almacenados en la carpeta bd de su proyecto.
CARRERAS PROFESIONALES
CIBERTEC
115
b) Paso 2: Ejecute los archivos sp_modificaCliente.sql y sp_modificaClienteConFoto.sql dentro del entorno MySql
CREATE PROCEDURE `sp_modificaCliente`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), inout resultado int ) BEGIN declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable != 0 then set resultado = 777; update tbcliente set nombre=vnombre, sueldo=vsueldo, sexo=vsexo, fecnac=vfecnac, clave=vclave where usuario=vusuario; else set resultado = 666; end if; END $$ ...
1
CIBERTEC
CARRERAS PROFESIONALES
116
CREATE PROCEDURE `sp_modificaClienteConFoto`( in vnombre varchar(100), in vsueldo double, in vsexo varchar(1), in vfecnac date, in vusuario varchar(15), in vclave varchar(15), in vfoto BLOB, inout resultado int ) BEGIN declare variable int; select count(*) into variable from tbcliente where usuario = vusuario; if variable != 0 then set resultado = 777; update tbcliente set nombre=vnombre, sueldo=vsueldo, sexo=vsexo, fecnac=vfecnac, clave=vclave, foto=vfoto where usuario=vusuario; else set resultado = 666; end if;
END $$ ...
CARRERAS PROFESIONALES
CIBERTEC
117
En el ejemplo, se ha utilizado la herramienta MySql WorkBench para ejecutar los Stored Procedures.
Notas: 1) La sentencia update no considera en su ejecucin la actualizacin de la columna foto. Este procedure ser invocado cuando el usuario del sistema no desee actualizar la fotografa del cliente. 2) Este procedure s recibe como parmetro un campo denominado vfoto, de modo que se pueda actualizar la imagen del cliente. 3) Una vez ejecutados los procedures dentro de la herramienta grfica de Mysql stos se visualizan en la ventana de edicin. En el ejemplo, en la ventana Object Browser.
CIBERTEC
CARRERAS PROFESIONALES
118
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 :) "); } ...
Notas: 1) Solo se carga en el objeto map el atributo foto, si ste es diferente de null. En el ejemplo, se controla esta situacin a travs de la condicin: 3
if (objCliente.getFoto() != null)
CARRERAS PROFESIONALES
CIBERTEC
119
2) Se invocar a una nueva operacin: ibatis_spModificaClienteConFoto o ibatis_spModificaCliente. 3) Se recupera el resultado retornado por el stored procedure: En el ejemplo, en caso de ser exitosa la operacin, retornar el valor 777, de lo contrario regresar a 666. d) Paso 4: Modifique el archivo Cliente.xml
<parameterMap class="java.util.Map" id="clienteMapBasico" > <parameter property="nombre" jdbcType="VARCHAR" mode="IN" /> <parameter property="sueldo" jdbcType="DOUBLE" mode="IN" /> <parameter property="sexo" jdbcType="CHAR" mode="IN" /> <parameter property="fecnac" jdbcType="DATETIME" mode="IN" /> <parameter property="usuario" jdbcType="VARCHAR" mode="IN" /> <parameter property="clave" jdbcType="VARCHAR" mode="IN" /> <parameter property="resultado" jdbcType="INT" mode="INOUT" /> </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>
Notas: 1) Se ha creado un nuevo parameterMap: clienteMapBasico, que ser utilizado para actualizar la informacin del cliente sin modificar su fotografa.
CIBERTEC
CARRERAS PROFESIONALES
120
2) Se mantiene el parameterMap clienteMap para actualizar la informacin del cliente modificando su fotografa.
3) Se han creado dos nuevas operaciones en el archivo Cliente.xml que sern invocadas por la clase MySqlClienteDAO para modificar la informacin del cliente modificando o no su fotografa, respectivamente.
e) Paso 5: Ejecute la aplicacin 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 Ramn. Se visualizar la siguiente pantalla:
Luego de modificar los datos y seleccionar el botn Actualizar, se visualizar la siguiente pantalla:
CARRERAS PROFESIONALES
CIBERTEC
121
Nota: 1) Puede seleccionar nuevamente el enlace M para verificar los cambios realizados. Visualizar que se logr modificar exitosamente la fotografa de Don Ramn.
CIBERTEC
CARRERAS PROFESIONALES
122
f)
Paso
6:
Muy Bien!,
ha
culminado
exitosamente la
CARRERAS PROFESIONALES
CIBERTEC
123
Resumen
Para recoger un conjunto de elementos con la clase List, puede hacer lo siguiente:
List<Coche> coches = sqlMap.queryForList("getCoches", null)
Para recoger un conjunto de elementos con la clase Map, puede hacer lo siguiente:
Map hashCoche = (Map) sqlMap.queryForObject("getHashCoche", 3);
Para el manejo del campo BLOB, se tiene que realizar lo siguiente en el archivo de Ibatis:
"Report" id= "ReportResult"> column= "id" property= "id" /> column= "name" property= "name" /> column= "description" property= "description" /> column= "data" property= "data" jdbcType= "BLOB"
Si desea saber ms acerca de estos temas, puede consultar la siguiente pgina. 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 ms utilizados.
CIBERTEC
CARRERAS PROFESIONALES
124
CARRERAS PROFESIONALES
CIBERTEC
125
UNIDAD DE APRENDIZAJE
TEMARIO 3.1 Tema 5 3.1.1. : Reportes con JasperReport : Diseo e implementacin de reportes con la herramienta IReport : Struts 2 y JasperReport : Integracin de Struts 2 y JasperReport Reportes Estndar
ACTIVIDADES PROPUESTAS Los alumnos implementan una aplicacin web bsica utilizando las principales caractersticas del framework MVC Struts 2 y la librera jasperReport.
CIBERTEC
CARRERAS PROFESIONALES
126
3.1.1.1. Funcionamiento de JasperReport JasperReports trabaja en forma similar a un compilador y a un intrprete. El usuario disea el reporte codificndolo 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 dnde colocar texto, imgenes, lneas, rectngulos, cmo adquirir los datos, cmo realizar ciertos clculos para mostrar totales, etc. Este archivo fuente XML debe ser compilado para obtener un reporte real. La versin compilada del fuente es nombrada "archivo jasper" (este termina con .jasper). Un Archivo jasper es el compilado de un cdigo fuente. Cuando se tiene ste, se necesita de datos para visualizar el resultado. Para generar reportes en Java, se necesita considerar la aplicacin del archivo compilado (.jasper), que recibir los datos a visualizar de la aplicacin. El archivo generado por la herramienta iReport es de tipo jrxml, en el cual se encontrar el diseo y estilo del reporte, y podr ser modificado en la herramienta iReport.
CARRERAS PROFESIONALES
CIBERTEC
127
CIBERTEC
CARRERAS PROFESIONALES
128
Notas: 1) Existe un nuevo archivo en la carpeta bd denominado FacilitoBaseDatosv2.sql. En l, se encontrarn nuevas tablas, a partir de las cuales se generar el reporte. 2) Existen nuevas libreras en la carpeta lib que permitirn integrar Struts 2 y JasperReport.
CARRERAS PROFESIONALES
CIBERTEC
129
create table pais ( `cod_pais` varchar(2) not null, `nom_pais` varchar(90) not null, primary key (`cod_pais`) ) ENGINE=InnoDB default CHARSET=latin1;
1
create table cliente ( `usuario` varchar(15) not null, `password` varchar(15) not null, `nombres` varchar(90) null, `apellidos` varchar(90) null, `sexo` varchar(1) not null, `fecha_nacimiento` datetime null, `dni` varchar(8) null, `cod_pais` varchar(2) null, `fecha_ingreso` datetime null, `email` varchar(80) null, `vip` varchar(1) not null, `flag_admin` varchar(1) not null default 'N', primary key (`usuario`)
Notas: 1) Debe crear las tablas cliente y pas en MySql. Sobre la base de estas tablas, se generar el nuevo reporte. b) Paso 3: Modificar el archivo struts.xml
CIBERTEC
CARRERAS PROFESIONALES
130
<!-- 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>
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 pgina 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 parmetros del reporte como por ejemplo: Formato del archivo a generar: PDF Ubicacin de archivos compilado ejecutar: /reportes/reporte01.jasper Origen de datos para generar (dataSource): atributo listaClientes. .jasper a
el
listado
CARRERAS PROFESIONALES
CIBERTEC
131
<s:form method="post" action="reporteFacilito"> <table class="control" > <tr> <td> <s:text name="reporte.nombre" /> </td> <td> <s:textfield name="nombre" /> </td> <td align="right" > <input type="submit" name="boton01" value="Listar" > </td> </tr> </table> </s:form>su ID -->
...
Notas: 1) Debe invocar al action reporteFacilito, el cual ya ha sido registrado en el archivo struts.xm. Asimismo, debe generar el listado con jasperreport. f) Paso 6: Cree el action ReporteAction
CIBERTEC
CARRERAS PROFESIONALES
132
public List<ReporteDTO> getListaClientes() { return listaClientes; } public void setListaClientes(List<ReporteDTO> listaClientes) { this.listaClientes = listaClientes; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String listaClientesPorPais(){ String vista="exito"; //JasperReportConstants.FORMAT_HTML //JasperReportConstants.FORMAT_PDF //JasperReportConstants.FORMAT_XLS System.out.println("dentro de listaClientesPorPais :)"); try { this.setListaClientes( PaqueteBusinessDelegate.getClienteService(). listaClientesReporte(nombre)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("nombre del cliente"+this.getNombre()); System.out.println("redireccionamos a la vista exito!"); return vista; } } ...
Notas: 1) El atributo listaClientes es referenciado en el archivo struts.xml como origen de datos para el Reporte. Note que es una lista de objetos de tipo ReporteDTO. Esta clase tiene como atributos los campos que sern mostrados en el reporte. 2) Se define la lista de clientes a obtener, considerando la seleccin del usuario (el atributo nombre).
CARRERAS PROFESIONALES
CIBERTEC
133
public List<ReporteDTO> listaClientesReporte(String nombre) throws Exception{ System.out.println("dentro del listaCliente del Service"); // Aqui podemos colocar logica adicional antes de invocar al metodo // del DAO return objClienteDAO.listaPorNombreReporte(nombre); ...
Notas: 1) Debe crear el mtodo listaClientesReporte para que la clase ReporteAction pueda invocarlo y generar el reporte.
CIBERTEC
CARRERAS PROFESIONALES
134
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
Notas: 1) Note cmo, de manera clsica, se obtiene una conexin para hacer la consulta respectiva. Debe transformar este cdigo a su equivalente en ibatis. i) Paso 9: Modifique el archivo menu.jsp
CARRERAS PROFESIONALES
CIBERTEC
135
Notas: 1) Debe invocar al action a_reporte para cargar la pgina JSP a partir de la cual se generar el reporte.
i)
CIBERTEC
CARRERAS PROFESIONALES
136
Se visualizar la siguiente pantalla. Luego, ingrese un criterio de bsqueda. Finalmente, seleccione el botn Listar.
Visualizar una pantalla a travs de la que se le consultar si desea abrir o guardar el archivo. Seleccione abrir el archivo.
CARRERAS PROFESIONALES
CIBERTEC
137
j)
Paso 11:
CIBERTEC
CARRERAS PROFESIONALES
138
Resumen
Se pueden construir reportes visualmente en Java, utilizando la herramienta iReport. sta usa como estructura base jasperReport, un lenguaje basado en etiquetas xml y especialmente creado para generar reportes. IReport genera archivos fuente con extensin .jrxml. Los archivos compilados tienen extensin .jasper y pueden ser ejecutados desde una aplicacin java web.
Si desea saber ms acerca de estos temas, puede consultar la siguiente pgina. http://jasperforge.org/website/ireportwebsite/IR%20Website/iReport_documentati on.html?group_id=243&header=project&leftnav=yes&target=ireport
CARRERAS PROFESIONALES
CIBERTEC
139
ANEXOS
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
CIBERTEC
CARRERAS PROFESIONALES
140
Para entornos de programacin, se requiere el JDK, pero para los de produccin basta con el JRE. Por ltimo, ejecute el instalador y siga los pasos indicados en el wizard.
CARRERAS PROFESIONALES
CIBERTEC
141
Eclipse IDE:
Primero, descargue Eclipse Helios desde la pgina de la fundacin Eclipse ( http://www.eclipse.org ). Luego, busque la zona de descarga. Por ltimo, seleccione la versin Java EE:
Al terminar la descarga, el .ZIP generado se puede extraer en una carpeta cualquiera (normalmente en la raz de uno de los discos de la PC). Se puede crear un acceso directo desde el Escritorio apuntando al archivo eclipse.exe
CIBERTEC
CARRERAS PROFESIONALES
142
CARRERAS PROFESIONALES
CIBERTEC
143
CIBERTEC
CARRERAS PROFESIONALES
144
CARRERAS PROFESIONALES
CIBERTEC
145
Basta con descargar el .ZIP y extraerlo en cualquier carpeta. El servicio de base de datos se activa por lnea de comandos de la manera siguiente:
CIBERTEC
CARRERAS PROFESIONALES
146
Las herramientas de Query Browser y MySQL Administrator han sido reemplazadas por MySQL WorkBench:
De igual forma, seleccionar el .ZIP ( que sea del tipo No Install ) y extraerlo en alguna carpeta de la PC.
CARRERAS PROFESIONALES
CIBERTEC
147
Se debe escoger una de las opciones de los archivos .ZIP. Con la alternativa de Full Distribution, es ms que suficiente.
CIBERTEC
CARRERAS PROFESIONALES
148
CARRERAS PROFESIONALES
CIBERTEC
149
CIBERTEC
CARRERAS PROFESIONALES
150
CARRERAS PROFESIONALES
CIBERTEC
151
ANEXOS
CIBERTEC
CARRERAS PROFESIONALES
152
La Clase entidad
CARRERAS PROFESIONALES
CIBERTEC
153
CIBERTEC
CARRERAS PROFESIONALES
154
CARRERAS PROFESIONALES
CIBERTEC
155
El Archivo de Configuracin de MyIbatis los datos de la cadena de conexin los tipos de datos de los mappers la ubicacin de los mappers
CIBERTEC
CARRERAS PROFESIONALES
156
CARRERAS PROFESIONALES
CIBERTEC
157
ANEXOS
ANEXO 3: MYIBATIS
DynamicSQL
Una de las caractersticas ms potentes de MyBatis siempre ha sido su capacidad de SQL dinmico. MyBatis, sin duda, mejora la situacin en el lenguaje SQL, que se pueden utilizar dentro de cualquier mapa instruccinSQL. Los elementos de SQL dinmico debe ser familiar para cualquiera que haya usado JSTL o cualquier XML, similares a base procesadores de texto. En versiones anteriores de MyBatis, haba 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 mayora de los dems elementos.
CIBERTEC
CARRERAS PROFESIONALES
158
Foreach
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
CARRERAS PROFESIONALES
CIBERTEC
159
ANEXOS
Configuracin:
MyIbatis 3.0:
CIBERTEC
CARRERAS PROFESIONALES
160
<settings useStatementNamespaces="true"/>
<typeAlias>
<typeAlias>
<configuration> <settings> ... </settings> <typeAliases> <typeAlias ... /> </typeAliases> </configuration>
MyIbatis 3.0:
<environments default="env"> <environment id="env"> <transactionManager type="JDBC"> <property name="commitRequired" value="false"/> </transactionManager> <dataSource type="your.package.CustomDataSourceFactory" /> </environment> </environments>
<sqlMap>
CARRERAS PROFESIONALES
CIBERTEC
161
Ibatis 2.0:
MyIbatis 3.0:
Mapping
La raiz del elemento <sqlMap> es ahora <mapper> El atributo parameterClass debera ser cambiado por parameterType El atributo resultClass debera ser cambiado por resultType El atributo class debera ser cambiado por type El columnIndex atributo no existe algun resultado en la etiqueta <result> El groupBy atributo debera ser eliminado.
Ibatis 2.0:
<resultMap id="productRM" class="product" groupBy="id"> <result property="id" column="product_id"/> <result property="name" column="product_name"/> <result property="category" column="product_category"/> <result property="subProducts" resultMap="Products.subProductsRM"/> </resultMap>
MyIbatis 3.0:
<resultMap id="productRM" type="product" > <id property="id" column="product "/> <result property="name " column="product_name "/> <result property="category " column="product_category "/> <collection property="subProducts" resultMap="Products.subProductsRM"/> </resultMap>
CIBERTEC
CARRERAS PROFESIONALES
162
Nested resultMaps
debera especificarse mediante <association> tag.
Ibatis 2.0:
MyIbatis 3.0:
#value#
MyIbatis 3.0:
#{value}
jdbcType="ORACLECURSOR"
MyIbatis 3.0:
jdbcType="CURSOR"
CARRERAS PROFESIONALES
CIBERTEC
163
Ibatis 2.0:
jdbcType="NUMBER"
MyIbatis 3.0:
jdbcType="NUMERIC"
Stored procedures
Ibatis 2.0:
MyIbatis 3.0:
<cacheModel id="myCache" type="LRU"> <flushInterval hours="24"/> <property name="size" value="100" /> </cacheModel>
MyIbatis 3.0:
CIBERTEC
CARRERAS PROFESIONALES
164
<isNotNull.*?property=\"(.*?)\"> </isNotNull>
MyIbatis 3.0:
CARRERAS PROFESIONALES
CIBERTEC