Sei sulla pagina 1di 164

Desarrollo de

Sofware basado en
Frameworks
2

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 3

NDICE Pgina

Presentacin 5
Red de contenidos 6
Unidad de aprendizaje 1: Modelo Vista Controlador Patrn MVC
1.1 Tema 1 : Fundamentos de Struts 2 9
1.1.1. : Arquitectura y Configuracin de aplicaciones 9
1.1.2. : La clase Action 13
1.1.3. : Libreras de etiquetas de Struts 2 29
1.1.4. : Internacionalizacin I18N 51
1.2 Tema 2 : Acceso optimizado a base de datos y otras 63
caractersticas Struts 2
1.2.1. : Uso de un pool de conexiones para acceso a la fuente 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

Unidad de aprendizaje 2: Persistencia de datos Framework IBATIS


2.1 Tema 3 : Introduccin a IBATIS 101
2.1.1. : IBATIS Introduccin 101
2.1.2. : Operaciones bsicas de acceso a base de datos con 110
IBATIS

2.2 Tema 4 : Otras operaciones con IBATIS 119


2.2.1. : Otras operaciones y caractersticas de IBATIS 119
2.2.2. : Tpicos avanzados de IBATIS e Integracin con 128
Struts 2

Unidad de aprendizaje 3: Reportes en Sistemas empresariales


3.1 Tema 5 : Reportes con JasperReport 139

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
4

3.1.1. : Diseo e implementacin de reportes con la 141


herramienta Ireport
3.2 Tema 6 : Struts 2 y JasperReport 142
3.2.1. : Integracin de Struts 2 y JasperReport 142

Anexo 1 157
Anexo 2 167
Anexo 3 172

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 5

PRESENTACIN

Desarrollo de Sofware basado en Frameworks 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
6

RED DE CONTENIDOS

Desarrollo de Software Basado en Framework

Modelo Vista Persistencia de Reportes en


Controlador datos sistemas
Patrn MVC Framework empresariales
IBATIS

Fundame Otras Introduccin Otras Tema 5 Tema 6


ntos de Caractersticas a IBATIS operaciones JasperReport Struts 2 y
Struts 2 Struts 2 IBATIS Jasper

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 7

UNIDAD DE
APRENDIZAJE

MODELO VISTA CONTROLADOR PATRN MVC


LOGRO DE LA UNIDAD DE APRENDIZAJE

Al finalizar la unidad, el alumno, utilizando el framework MVC STRUTS 2,


implementa una aplicacin web que contenga, en su estructura, el componente
Action, las principales etiquetas del framework y acceso a base de datos a
travs 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 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.

1.1 Fundamentos de Struts 2

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


8

Struts 2 es un framework que implementa el patrn 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 aplicacin. Se muestra, a continuacin, el esquema
bsico de funcionamiento de esta arquitectura.

La capa Model en Struts 2 inicia con los componentes Action. Debajo de stos, se
tendrn diversos componentes:

Services (Lgica pura de negocio)


DAOs (objetos de persistencia de datos), entre otros.

Se muestra, a continuacin, el esquema bsico de la arquitectura MVC


implementado por el framework Struts 2.

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.

1.1.1. Arquitectura y configuracin de aplicaciones

La arquitectura MVC funciona en Struts 2 bsicamente de la siguiente


manera: a travs 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 configuracin XML de Struts 2. ste
tiene por defecto el nombre struts.xml.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 9

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:

1) El principal archivo de configuracin del Framework es el


archivo struts.xml. En l, se registrarn sus principales

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
10

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.

b) Paso 2: Revisar el archivo web.xml

<?xml version="1.0" encoding="UTF-8"?>


<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts Blank</display-name>

<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 1
</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

</web-app>

Notas:

1) Note el registro del filtro controlador del framework Struts 2.


Este componente atrapar todas las solicitudes (request)
generadas desde un cliente, dado que tiene como alias /*.

c) Paso 3: Ejecutar la aplicacin

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 11

d) Paso 4: Excelente!, ha culminado el proceso de probar


exitosamente la aplicacin web struts2-blank-2.1.8.1

1.1.2. La clase Action

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
12

Un action es, en Struts 2, el primer componente de la capa Model dentro


de la arquitectura MVC.

Un actions realiza bsicamente tres pasos dentro de una aplicacin web.


En primer lugar, recibe las solicitudes (request) enviadas por un cliente y
realiza el trabajo inicial para atenderla. Es el componente que interacta
con la capa controladora y la capa view. En segundo lugar, acta como
un transportador natural de datos entre el objeto request y los
componentes de la capa view, esto gracias a las caractersticas de
transferencia automtica 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 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 de


configuracin al proyecto web funcionalidadLogueov1_Inicial

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

b) Paso 2: Registrar el filtro controlador de Struts 2 dentro


del archivo web.xml

<!-- registramos el filtro controlador de struts 2 -->


<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

c) Paso 3: Crear el primer componente Struts 2 de la aplicacin,


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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
14

package aprendamos.java.action;

public class LogueoAction {

private String usuario;


private String clave;

public String getUsuario() {


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

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


struts.xml
1

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

<action name="logueo"
class="aprendamos.java.action.LogueoAction" >

<result name="error" >/logueo.jsp </result>


<result name="exito" >/bienvenida.jsp </result>
</action>
</package>

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 15

e) Paso 5: Ejecutar la aplicacin 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

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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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;
. . .
}

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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();
}

Verifique si la clase MySqlClienteDAO ha sido registrada en


la fbrica de fbricas DAOFactory:

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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.

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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;

c) Paso 3: Crear la clase PaqueteBusinessDelegate

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
20

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 class LogueoAction {

private String usuario;


private String clave;
private String mensaje;

public String getMensaje() {


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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 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;
}

DESARROLLO DE SOFWARE BASADO


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

e) Paso 5: Ejecutar la aplicacin

Primero, ingrese un usuario invlido.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 23

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

Por ltimo, ingrese los datos correctamente.

Excelente!, ha culminado la funcionalidad de logueo versin 2

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
24

1.1.3. Libreras de etiquetas de Struts 2

1.1.3.1. Ejercicio 1: Funcionalidad de Logueo Versin 3

Agregue una nueva funcionalidad al logueo implementado, a


travs del uso de archivos de recursos y nuevas caractersticas
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 travs de la key


struts.custom.i18n.resources, se define la ubicacin del archivo
de recursos.

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

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


MisRecursos.properties

Puede agregar las keys correspondientes a los mensajes de


error del logueo.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 25

# Definiremos keys y sus respectivos valores


# Una key es un identificador asociado a alguna descripcion

#keys para el logueo : completar


logueo.titulo = Pagina de Inicio - Que facil es JEE :):)

logueo.mensaje.error.usuario=Lo sentimos, el usuario ingresado


no existe :(
logueo.mensaje.error.clave=Es una pena, la clave ingresada no

c) Paso 3: Referenciar las keys dentro de la clase LogueoAction

Para poder referenciar las keys, la clase LogueoAction debe


heredar de la clase ActionSupport. Esto permitir incluir
funcionalidad adicional dentro de la misma.

package aprendamos.java.action;

import java.util.Map;

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

private String usuario;


private String clave;
private String mensaje;

Invoque el mtodo getText, heredado de la clase ActionSupport.

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

. . .

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
26

d) Paso 4: Modificar el JSP logueo.jsp

Debe referenciar a la librera de etiquetas de struts 2.

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

Transforme las etiquetas html en sus equivalentes de Struts 2.

<s:form action="logueo" method="post" >

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

<tr class="etiqueta" >


<td > <fmt:message key="kclave" /> </td>
<td> <s:password name="cliente.clave" /> </td>
</tr>
<tr>
<td colspan="2" align="right" >
<s:submit name="boton01"
value="Ingresar"
type="submit" />
</td>
</tr>

<tr>
<td class="error general">
${requestScope.mensaje}
</td>

</tr>
<tr>
<td >
<fmt:message key="logueo.imagen" />
</td>

</tr>

</table>

</s:form>

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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;
}

Modifique el mtodo execute.

public String execute(){


String vista="exito";
System.out.println("dentro de nuestro primer action"); 1
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 { 2
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())){

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
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) Paso 6: Ejecutar la aplicacin

Primero, ingrese un usuario invlido.

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

Por ltimo, ingrese los datos correctamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 29

g) Paso 7: Muy buen trabajo!

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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 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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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`; 1
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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
32

c) Paso 3: Modificar el archivo nuevoCliente.jsp

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" 1
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> 2 <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>

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 33

d) Paso 4: Registrar el alias ingresaCliente en el


archivo struts.xml

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

<result name="exito" >/listado.jsp</result>

</action>

Notas:

1) El alias ingresaCliente fue definido en el formulario de la


pgina nuevoCliente.jsp. Note que al invocar este alias se
ejecutar dentro de la clase ClienteAction el mtodo registrar.

e) Paso 5: Crear el mtodo registrar en la clase ClienteAction

La clase ClienteAction debe contar con la siguiente lgica:

package aprendamos.java.action;

import java.util.List;

import aprendamos.java.bean.ClienteDTO;

import aprendamos.java.service.ClienteService_I; 1 import


aprendamos.java.service.PaqueteBusinessDelegate;
public class ClienteAction {

// creamos un atributo de tipo Lista de


Clientes ClienteDTO cliente;
List<ClienteDTO> clientes;

...

DESARROLLO DE SOFWARE BASADO


EN FRAMEWORKS
34

...
ClienteService_I servicioCliente = 2
PaqueteBusinessDelegate.getClienteService();

// creamos el metodo registra


public String registra(){ 3
String vista="exito";
try { 4

servicioCliente.registraElCliente(cliente);

// lo retornado por el servicio lo asignamos al


atributo de tipo Lista de clientes
cliente.setNombre("");

clientes=
servicioCliente.
listaClientesPorNombre(cliente.getNombre());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return vista;
}

Notas:

1) Se ha definido la variable cliente de tipo ClienteDTO. De


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 35

f) Paso 6: Modificar la clase ClienteDTO

La clase ClienteDTO debe contar con la siguiente lgica:

public class ClienteDTO implements Serializable {

private static final long serialVersionUID = 1L;

private String nombre; 1


private Date fecnac;
private String sexo;
private double sueldo; 2
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;
}
. . .

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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
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){ 1
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


serexpuesto registrndolo en la interface
ClienteService_I. La clase ClienteService implementa
la interface ClienteService_I.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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); 1

// asignamos valores a las interrogantes


pst.setString(1, objCliente.getNombre());
pst.setDouble(2, objCliente.getSueldo());
2
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;

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:

DESARROLLO DE SOFWARE BASADO EN


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 39

i) Paso 9: Ejecutar la aplicacin web

Seleccione del listado de Clientes el enlace Nuevo Cliente:

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
40

En la pantalla mostrada, ingrese los campos solicitados.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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) Paso 10: Bien!, ha culminado la funcionalidad registra imagen


exitosamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 43

1.1.4. Internacionalizacin I18n

Tradicionalmente, los desarrolladores de software se centran en construir


aplicaciones que resuelvan en forma inmediata problemas de negocio.
Mientras hacen eso es fcil y a veces necesario realizar asunciones acerca
del lenguaje o lugar de residencia de los usuarios. En muchos casos, estas
asunciones son vlidas y no hay preguntas sobre quin ser la audiencia.
Sin embargo, es probable, alguna vez, que se deba reconstruir una
aplicacin, porque estas asunciones fueron incorrectas.

Internacionalizacin (I18N) es el proceso de disear su software con


soporte en tiempo real de mltiples lenguajes y regiones. Dada esta
caracterstica, no ser necesario redisear nuestras aplicaciones cada vez
que se necesite soporte para un nuevo lenguaje. Una aplicacin que dice
tener soporte para internacionalizacin debe contar con las siguientes
caractersticas:

Puede soportar lenguajes adicionales sin requerir cambios adicionales


de cdigo.
Los elementos de texto, mensajes e imgenes son almacenados
externamente al cdigo fuente.
Dependencia culturales de datos, tales como fecha y hora, y valores
decimales son correctamente formateados para el lenguaje del usuario
y localizacin geogrfica.
Caracteres no estndares son soportados.
La aplicacin puede ser fcilmente adaptada a nuevos lenguajes y
regiones.

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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.

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

Defina las keys para el idioma portugus en el archivo


MisRecursos_pt.properties

#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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
46

Defina las keys para el idioma italiano en el archivo


MisRecursos_it.properties

#keys para la pagina de bienvenida


key.usuario = Utente:
key.nombre = Nome:
key.fecnac = Data di Nascito:
key.sexo = sesso:
key.saludo = Benvenuto Caro utente, i dati sono:

#keys para el menu


menu.bienvenida = Vai alla pagina di
benvenuto menu.logueo = Ir al logueini
menu.listado = Ir al listadini

Defina las keys para el idioma espaol en el archivo


MisRecursos.properties (archivo de recursos por defecto). 1

#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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

c) Paso 3: Modificar el archivo cabecera.jsp

< body class="titulo" >


< img alt="" src="imagenes/logo.png" border="0" >
<table>
<tr><td>
<a
href="${pageContext.request.contextPath}/a_bienvenida?request_loc
ale=it">
<img
src="imagenes/banderaItalia.png" alt="Italiana" border="0">
</a> 1
</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

DESARROLLO DE SOFWARE BASADO EN


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

d) Paso 4: Registrar el action a_bienvenida en el archivo


struts.xml

. . .

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


default">
1
<action name="a_bienvenida" >
<result > /bienvenida.jsp </result>
</action>

<action name="a_logueo" > 1

<result > /logueo.jsp </result>


</action>
. . .

Notas:

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 49

Modifique el archivo menu.jsp

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

</s:a>
</td>
</tr>
<tr>
1 <s:a
<td class ="control" >
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" %>

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
50

Modifique el archivo bienvenida.jsp

. . .

<table class="control" >


<tr>
<td colspan="2" >
<s:text name="key.saludo" />
</td>
</tr>

<!-- recuperamos los atributos del usuario logueado


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 51

f) Paso 6: Ejecutar la aplicacin web

Ingrese a la intranet a travs de la pgina de logueo.

Se debe visualizar la pantalla de bienvenida y los enlaces a los


idiomas definidos en la pgina cabecera.jsp. Seleccione la
bandera italiana.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 53

Se visualizar la siguiente pantalla con el men y la bienvenida


en idioma castellano.

g) Paso 7: Bien!, ha culminado la funcionalidad registra


imagen con I18n exitosamente.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
54

1.2 Acceso optimizado a base de datos y otras caractersticas


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 sern "prestadas" a los threads (hilos) de ejecucin 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 anlisis es el mismo. El recurso es la conexin 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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
56

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


conexiones.

<?xml version="1.0" encoding="UTF-8"?>


<!-- Este es un comentario -->
<!-- la etiqueta Context representa una zona de memoria que se crea
cuando levantamos la aplicacion web. Esta zona de memoria estara
"viva"
mientras no reiniciemos la aplicacion web -->

<Context path="/jee-web" >


<!-- registramos un recurso en esta zona de memoria. En este
caso
un de conexiones
pool --> 1
<Resource

name="jdbc/sisepuede" 2 auth="Container"
type="javax.sql.DataSource"
maxActive="100" 3
maxIdle="30"
maxWait="10000"
username="root"
password=""
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/facilito"/>

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 57

c) Paso 3: Modificar el archivo MySqlDbConn.java

package aprendamos.java.util;

// Esta clase nos retornara una conexion a base de datos

import java.sql.*; 1
import javax.naming.*;
import javax.sql.*; 2
public class MySqlDBConn {
// Utilizaremos mas bien un pool de conexiones

// creamos el metodo que nos permite obtener una conexion


. . .

Notas:

3) Debe importar el paquete javax.naming.*, ya que en l se


encuentran las clases para utilizar JNDI y acceder al pool de
conexiones.

4) Debe importar el pauete javax.sql.* debido a que dentro de l


se encuentra la clase DataSource. sta representa un pool
de conexiones en java.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
58

. . .
public static Connection obtenerConexion(){

// 1. Para referenciar al pool creamos un contexto JNDI


// Java Naming and Directory Interface
Connection cn=null;

try {

// creamos el contexto JNDI Inicial, JDNI valida los nombres ,


utiliza la infor de META INF para hacer un pool de conexiones., JNDI
maneja nombres y objetos
Context ctx = new InitialContext();

// ahora vamos a ubicar un nombre dentro


// de este contexto, para ello usamos el
// famoso metodo lookup.
//Base standar JND
String raizContexto ="java:comp/env/"; 1

// obtenemos a traves de su nombre a nuestro


// pool de conexiones
DataSource ds=

(DataSource)ctx.lookup(raizContexto+"jdbc/sisepuede"); 2

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 59

Se obtiene un objeto de tipo DataSource que representa el pool


almacenado en memoria.

d) Paso 4: Copiar el conector de mysql dentro de la carpeta lib


del servidor de aplicaciones TomCat

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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
60

e) Paso 5: Ejecutar la aplicacin web

Ingrese a la intranet a travs de la pgina de logueo.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
62

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


imagen pool exitosamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 63

1.2.2. Libreras de etiquetas de Struts 2. Principales componentes

Dentro de la familia de nuevas etiquetas de Struts 2, es importante


destacar que, en esta versin, todas las etiquetas bsicas del framework
se encuentran en una sola librera, la cual es referenciada en un JSP de
la siguiente manera:

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

Se detalla, a continuacin, ejercicios de aplicacin 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 travs 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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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" > 1
<s:url id="carga" action="cargaModificaCliente" >
<s:param name="usuario" > ${elcli.usuario} </s:param>
</s:url>

<a href="${carga}" > M </a>


</td>

. . .

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
66

c) Paso 3: Registrar el alias cargaModificaCliente en el archivo


struts.xml

<action name="cargaModificaCliente" 1
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.

d) Paso 4: Crear el mtodo cargaModifica en la clase


ClienteAction

La clase ClienteAction debe contar con la siguiente lgica:

package aprendamos.java.action;

import java.util.List;

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

...

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 67

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

servicioCliente.buscaClientePorUsuario(
this.getUsuario());

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

return vista;
} 3
...

Notas:

1) Se ha definido la variable usuario de tipo String. Se definen


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

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
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;
1
Connection cn = MySqlDBConn.obtenerConexion();

//definimos la sentencia
String sql="select
usuario,clave,nombre,sueldo,sexo,fecnac,foto " + " "
+ "from tbcliente where usuario = ?";
//la preparamos
PreparedStatement pst=cn.prepareStatement(sql);
//asignamos valores a las interrogantes 2
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)

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 69

f) Paso 6: Ejecutar la aplicacin 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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
70

En la pantalla mostrada, se visualizarn los datos asociados al


cliente seleccionado. Sin embargo, no reconoce an la
fotografa.

g) Paso 7: Bien!, ha culminado la primera parte de la


funcionalidad carga imagen

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 71

h) Paso 8: Modificar la pgina modificaCliente.jsp

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>
<td>
<img alt="Fotografia del Cliente:) " 1
src="cargaImagenCliente?usuario=${cliente.usuario}" />
</td>
</tr>
. . .

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

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
72

i) Paso 9: Registrar el alias cargaImagenCliente en el


archivo struts.xml

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

</action>

Notas:

1) El alias cargaImagenCliente fue referenciado en la etiqueta


<img> de la 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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 73

j) Paso 10: Crear el mtodo recuperaImagenCliente en la


clase ImagenAction

La clase ImagenAction debe contar con la siguiente lgica:

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; 1
InputStream imagenClienteRecuperada;
...

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

servicioCliente.buscaClientePorUsuario(usuario); 2

// del objeto cli solo nos importa la foto como InputStream


// recuperamos ese atributo y lo asignamos al campo
// imagenClienteRecuperada
this.imagenClienteRecuperada = cli.getIsFoto(); 3
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return vista;
}
...

DESARROLLO DE SOFWARE BASADO EN


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
76

1.2.3. Patrn Composite View Struts 2 Tiles

Al momento de crear el diseo de un sitio web tpico, ste puede sufrir


muchos cambios durante su ciclo de vida. Utilizar diseos y gestores de
diseo puede ayudar a organizar las diferentes partes de un JSP de modo
que stos se puedan alterar con un mnimo impacto para el resto de la
aplicacin.

Surge, de esta manera, el patrn de diseo Composite View, el cual


permite, de manera eficiente y escalable, gestionar diversos diseos para
un sitio web. Desafortunadamente, la tecnologa JSP no proporciona
ningn soporte directo para diseos o gestores de diseo, es por ello que
surgen libreras en el mercado que pueden ser utilizadas para mejorar la
estructura de nuestras aplicaciones web.

Se muestra, a continuacin, a travs de un ejercicio, la configuracin y


uso de la librera Tiles. sta es de cdigo abierto e implementa el patrn
Composite View.

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 77

a) Paso 1: Importar el proyecto web


MantenimientoTiles_Inicial.war

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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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>
1 </listener-
org.apache.struts2.tiles.StrutsTilesListener
class>

</listener>

...

Notas:

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 79

c) Paso 3: Modificar el archivo struts.xml

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

<!DOCTYPE tiles-definitions PUBLIC


"-//Apache Software Foundation//DTD Tiles Configuration
2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="d_bienvenida"
template="/plantillas/diseno01.jsp">
<put-attribute name="menu" value="/paginas/menu.jsp" /> 1
<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" /> 2

</definition>
<definition name="d_nuevoCliente" extends="d_bienvenida">

<put-attribute name="body" value="/paginas/nuevoCliente.jsp" />

</definition>
... 3

Notas:

1) Debe crear definiciones de Tiles. sta determina qu


componentes (JSPs normalmente) se despliegan sobre
una plantilla en particular. En el ejemplo, el definition
d_bienvenida referencia a la plantilla diseno01.jsp,
2) Un definition puede ser heredado. De esta manera, solo
es necesario sobre escribir los puts que queramos
modificar. En el ejemplo, el definition d_listado hereda del
definition d_bienvenida.
3) Note que los puts dentro de los definitions estn
referenciando a pginas JSP dentro de la carpeta
pginas. sta debe existir y ah deben encontrarse las
pginas referenciadas.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
80

d) Paso 4: Modificar el archivo struts.xml

...
<struts>

<constant name="struts.enable.DynamicMethodInvocation"
value="false" />
<constant name="struts.devMode" value="false" />

1
<package name="default" namespace="/" extends="tiles-default">
<!-- creamos un action de atajo -->
<action name="a_nuevoCliente" >
<result type="tiles"> d_nuevoCliente </result>
</action>
2

<action name="a_bienvenida" > <result


type="tiles"> d_bienvenida </result>
</action>
3
<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>
...

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 81

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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
82

f) Paso 6: Modificar el archivo diseno01.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-


1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"> <html>
1
<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> 2
<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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 83

g) Paso 7: Copiar las pginas JSP dentro de la carpeta pginas

Notas:

1) Tal como se indic en el archivo tiles.xml, las pginas JSP


deben estar dentro de una carpeta denominada pginas.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
84

h) Paso 8: Eliminar las directivas <include> de todas las


pginas JSP.

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

<tr>

<td >
<!-- aqui va el menu -->

<jsp:include page="menu.jsp" />

</td>

<!-- aqui va el cuerpo -->


<td >
...

Notas:

1) Dado que ahora se trabajar con Tiles, ya no es necesario


tener directivas include dentro de los JSPs.

Importante: De dejarlas, se duplicara la implementacin del


patrn de diseo Composite View.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 85

i) Paso 9: Ejecutar la aplicacin web

Ingrese a la intranet a travs de la pgina de logueo.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
86

Visualizar la pantalla de bienvenida de la aplicacin

j) Paso 10: Bien!, ha culminado la funcionalidad


Mantenimiento con Tiles exitosamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
88

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 89

UNIDAD DE
APRENDIZAJE

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 : 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 : Otras operaciones con IBATIS


2.2.1. : Otras operaciones y caractersticas de IBATIS
2.2.2. : 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
90

2.1 Introduccin a IBATIS

2.1.1. IBATIS - Introduccin

Ibatis es un framework (marco de trabajo) de cdigo abierto basado en


capas desarrollado por Apache Software Foundation, que se ocupa de la
capa de Persistencia (se sita entre la lgica de Negocio y la capa de la
Base de Datos). Puede ser implementado en Java y .NET (tambin 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
utilizacin de bases de datos.

Dentro de sus principales caractersticas se destacan:

A. Es posible subdividir la capa de persistencia en tres subcapas:

La capa de abstraccin ser la interfaz con la de la lgica


de negocio, haciendo las veces de fachada (Patrn Facade)
entre la aplicacin y la persistencia. Se implementa de forma
general, mediante el patrn 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, ocupndose de la gestin 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 comunicacin con la


propia base de datos, utilizando uno especfico para la misma.

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
92

b) Paso 2: Copiar los archivos de configuracin y la clase


UtilSqlConfig

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 93

c) Paso 3: Modificar el archivo SqlMapConfig.xml

<sqlMapConfig>

<!-- referenciamos a nuestro pool de conexiones, archivo


de confiracion por excelncia de IBatis -->
<transactionManager type="JDBC"> 1
<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 -->
2
<sqlMap resource="aprendamos/java/ibatis/Cliente.xml" />
<sqlMap resource="aprendamos/java/ibatis/Producto.xml"/> <!--
podemos registrar muchos mas sqlmaps -->
</sqlMapConfig>

...

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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
94

d) Paso 4: Modificar la clase UtilSqlConfig

import java.io.Reader;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder; 1
// 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"; 2
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;
}
}
...

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 95

e) Paso 5: Modificar el archivo Cliente.xml

<?xml version="1.0" encoding="UTF-8" ?>


<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="Cliente">
<!-- Referencia al DTO -->
<typeAlias alias="cli" type="aprendamos.java.bean.ClienteDTO"
/> 1
<resultMap class="cli" 2
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#; 3
</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#

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
96

f) Paso 6: Modificar el archivo MySqlClienteDAO

public ClienteDTO buscaPorUsuario(String usuario) throws Exception{


//Metodo modificado para Ibatis
ClienteDTO objClienteDTO=null;
System.out.println("Validamos con ibatis");
1
SqlMapClient sqlMap=UtilSqlConfig.getSqlMapInstance();

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

System. out.println("busca por usuario usando


Ibatis"); return objClienteDTO;
}

...

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 97

g) Paso 7: Ejecutar la aplicacin web

Ingrese a la intranet a travs de la pgina de logueo.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
98

Se visualizar la pantalla de bienvenida de la aplicacin.

Se visualizar en consola el mensaje generado por la clase


MySqlClienteDAO

h) Paso 8: Bien!, ha culminado la funcionalidad


Introduccin IBATIS exitosamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 99

2.1.2. Operaciones bsicas de Acceso a base de datos con IBATIS

Para implementar las operaciones bsicas con IBATIS, es necesario


conocer las principales etiquetas del Framework. stas se muestran a
continuacin:

Sentencias Atributos Elementos Hijos Mtodos


id
parameterClass
insert
resultClass update
<statement> parameterMap All dynamic elements delete
resultMap
All query
cacheModel
xmlResultName (Java methods

only)

id All dynamic elements insert


<selectKey>
<insert> parameterClass update
<generate> (.NET
parameterMap delete
only)
id All dynamic elements insert
<update> parameterClass <generate> (.NET update
parameterMap only) delete
id All dynamic elements insert
<delete> parameterClass <generate> (.NET update
parameterMap only) delete
id
parameterClass
resultClass All dynamic elements All query
<select> <generate> (.NET
parameterMap methods
only)
resultMap
cacheModel
id
parameterClass insert
resultClass update
<procedure> parameterMap All dynamic elements delete
resultMap All query
xmlResultName (Java methods
only)

Se desarrollan, a continuacin, diversos ejercicios en los que se utilizarn


y describirn las principales etiquetas del Framework.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
100

2.1.2.1. Ejercicio 1: Funcionalidad IBATIS - Mantenimiento

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

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

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

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 101

Se crean las operaciones para insertar y listar clientes por


nombre.

<select id="ibatis_clienteLista"
parameterClass="java.lang.String"
resultClass="cli">
<!-- Para poner wildcards aqui en value
seria '%$value$%'-->
select usuario,clave,nombre,sueldo,sexo,fecnac
from tbcliente where nombre like #value#
</select>

<!-- cuando utilizamos parameterMap o resultMap


nuestras sentencias pueden utilizar las interrogantes
de un prepareStatement tipico -->
<insert id="ibatis_insertaCliente" parameterMap="clienteMap" >
insert into tbcliente(nombre,sueldo,sexo,fecnac, 1
usuario,clave,foto) values (?,?,?,?,?,?,?)
</insert>
...

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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
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);
1
map.put("foto", losbytes);

cliente.insert("ibatis_insertaCliente",map); 2

System. out.println("registro exitoso con IBATIS :)


"); return resultado;
}
...

Notas:
1) A partir del campo isFoto (de tipo InputStream), se
prepara un arreglo de bytes, el cual se carga en el objeto
map con el nombre foto.
2) Se invoca a la sentencia insert de IBATIS, pasndole
como parmetros el nombre de la operacin a ejecutar y
el objeto map.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 103

public List<ClienteDTO> listaPorNombre(String vnombre) throws


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

return clientes; 1
}
...

Notas:
1) Se invoca al 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).

c) Paso 3: Ejecutar la aplicacin

Ingrese a la intranet y ejecute la funcionalidad de Listado. Se


visualizar la siguiente pantalla:

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
104

En la consola, se visualizar el mensaje definido en la clase


MySqlClienteDAO.

Ahora, seleccione el enlace Nuevo Cliente y registre uno nuevo


con el botn Registrar.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 105

Se visualizar la siguiente ventana con el nuevo registro


ingresado. En el ejemplo, se ha registrado al cliente Don
Ramn.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
106

Tambin, se visualizar, en consola, el mensaje definido en la


clase MySqlClienteDAO.

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


IBATIS exitosamente.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 107

2.2 Otras operaciones con IBATIS

2.2.1. Otras operaciones y caractersticas de IBATIS

Los procedimientos almacenados se crean con la declaracin


<procedure>. El siguiente ejemplo muestra un procedimiento
almacenado con parmetros 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 continuacin, ejercicios con procedimientos


almacenados IBATIS.

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


FuncionalidadIbatisProcedure_Inicial.war

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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, 1
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 $$
...

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
110

c) Paso 3: Modifique el mtodo registraCliente dentro de la clase


MySqlClienteDAO

byte[] losbytes = new byte[is.available()];

// a partir del inputStream cargamos el arreglo los


bytes is.read(losbytes);
map.put("foto", losbytes);

map.put("resultado", 0); 1

System.out.println("resultado antes de insertar: "


+ map.get("resultado"));

cliente.insert("ibatis_spInsertaCliente", map); 2

System.out.println("resultado despues de insertar: "


+ map.get("resultado")); 3

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

return resultado;

...

Notas:
1) Se carga en el objeto map un atributo adicional: el campo
resultado. ste permitir recuperar el resultado retornado
por el stored procedure.
2) Se debe invocar a una nueva 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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 111

d) Paso 4: Modifique el archivo Cliente.xml

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


1
<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" />
2
<parameter property="clave" jdbcType="VARCHAR" mode="IN" />
<parameter property="foto" jdbcType="BLOB" mode="IN" />
<parameter property="resultado" jdbcType="INT" mode="INOUT"
/>

</parameterMap> 3

...

<procedure id="ibatis_spInsertaCliente"
parameterMap="clienteMap" > 4

call sp_nuevoCliente(?,?,?,?,?,?,?,?)

</procedure>

Notas:
1) Se debe modificar cada una de las etiquetas <parameter>
para indicar, a travs del atributo mode, si el parmetro
es de entrada o entrada/salida.

2) Note cmo 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 travs de ella, se retornar al MySqlClienteDAO el
resultado de la ejecucin del stored procedure.

4) Debe invocar al stored procedure creado en base de


datos a travs de la sentencia call. Note que usa la
etiqueta IBATIS <prodecure> para definir la operacin
ibatis_spInsertaCliente.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
112

e) Paso 5: Ejecute la aplicacin

Seleccione la opcin Nuevo Cliente una vez realizado el listado


de Clientes. Visualizar la siguiente pantalla:

Luego de ingresar datos y seleccionar el botn Registrar,


se visualizar la siguiente pantalla:

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 113

Se visualizar tambin, en la consola de Eclipse, los


siguientes mensajes:

Insertando con ibatis :) resultado


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

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


funcionalidad Registro de Clientes con Stored Procedures e
IBATIS.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
114

2.1.2. Tpicos Avanzandos de IBATIS e integracin Struts 2

Es cada vez ms comn utilizar estructuras de base de datos capaces de


almacenar grandes cantidades de informacin. IBATIS es capaz de
gestionar objetos grandes (LOB), tales como los campos BLOB (Binary) o
CLOB (de caracteres). A partir de la versin de IBATIS 2.0.9, este
framework cuenta, por defecto, los campos BLOB y CLOB.

Se implementa, a continuacin, un ejemplo con Stored Procedures que


utiliza este tipo de estructuras.

2.1.2.1. Ejercicio 1: Actualizacin de Clientes utilizando Stored Procedures

a) Paso 1: Ubique los Stored Procedures relacionados con la


actualizacin 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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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 1
set nombre=vnombre,
sueldo=vsueldo,
sexo=vsexo,
fecnac=vfecnac,
clave=vclave
where usuario=vusuario;

else

set resultado = 666;


end if;
END $$
...

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
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, 2
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 $$
...

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
118

c) Paso 3: Modifique el mtodo registraCliente dentro de la clase


MySqlClienteDAO

HashMap<String, Object> map = new HashMap<String, Object>();

map.put("nombre", objCliente.getNombre());
map.put("sueldo", objCliente.getSueldo());
map.put("sexo", objCliente.getSexo());
map.put("fecnac", objCliente.getFecnac());
map.put("usuario", objCliente.getUsuario());
map.put("clave", objCliente.getClave());
if (objCliente.getFoto() != null) {

InputStream is = objCliente.getIsFoto();

byte[] losbytes = new byte[is.available()];

// a partir del inputStream cargamos el arreglo los bytes


is.read(losbytes);
map.put("foto", losbytes); 1
}
map.put("resultado", 0);
System.out.println("resultado antes de actualizar: "
+ map.get("resultado"));

SqlMapClient cliente = UtilSqlConfig.getSqlMapInstance();


if (objCliente.getFoto() != null) {
2
cliente.update("ibatis_spModificaClienteConFoto", map);
}else{
cliente.update("ibatis_spModificaCliente", map);
}

System.out.println("resultado despues de actualizar: 3


" + 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:
if (objCliente.getFoto() != null)

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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" > 1


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


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

Notas:

1) Se ha creado un nuevo parameterMap: clienteMapBasico,


que ser utilizado para actualizar la informacin del cliente
sin modificar su fotografa.

DESARROLLO DE SOFWARE BASADO EN


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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
122

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


funcionalidad Actualizacin de Clientes con Stored
Procedures e IBATIS.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 123

Resumen

Para recoger un conjunto de elementos con la clase List, puede hacer lo


siguiente:

List<Coche> coches = sqlMap.queryForList("getCoches", null)

Para recoger un conjunto de elementos con la clase Map, puede hacer lo


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

Para el manejo del campo BLOB, se tiene que realizar lo siguiente en el


archivo de Ibatis:

<resultMap class= "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 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.

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
124

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 125

UNIDAD DE
APRENDIZAJE

REPORTES EN SISTEMAS EMPRESARIALES


LOGRO DE LA UNIDAD DE APRENDIZAJE

Al finalizar la unidad, los alumnos, utilizando el framework STRUTS 2, la


librera JasperReport y la herramienta IReport, implementan una aplicacin
web que genera reportes con criterios de bsqueda dinmicos y acceso a base
de datos.

TEMARIO

3.1 Tema 5 : Reportes con JasperReport


3.1.1. : Diseo e implementacin de reportes con la herramienta IReport

3.2 Tema 6 : Struts 2 y JasperReport


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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
126

3.1 Reportes con JasperReport

3.1.1. Diseo e implementacin de Reportes con la herramienta


IReport
La herramienta iReport es un constructor y/o diseador de reportes visual,
fcil de usar para JasperReport, un lenguaje para generacin de reportes
escrito en Java.

Esta herramienta permite que los usuarios corrijan visualmente reportes


complejos con cartas, imgenes, subreportes, etc. iReport est, adems,
integrado con la biblioteca grfica JFreeChart, una de las ms grficas
OpenSource y difundida para Java. Los datos para imprimir pueden ser
recuperados por varios tipos de archivos, incluso mltiples uniones JDBC,
TableModels, JavaBeans, archivos XML, etc.

A continuacin, se enumeran las principales caractersticas de esta


herramienta:

100% escrito en JAVA y, adems, de uso libre y gratuito


Maneja el 99% de las etiquetas de JasperReports
Permite disear con sus propias herramientas: rectngulos, lneas,
elipses, campos de los textfields, cartas, subreports (subreportes)
Soporta internacionalizacin nativamente
Recopila y exporta integrados
Soporta JDBC
Soporta JavaBeans como orgenes de datos
Incluye asistentes para crear automticamente informes.

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.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 127

3.2 Struts 2 y JasperReport

3.2.1. Integracin de Struts 2 y JasperReport Reportes Estndar

Struts 2 permite implementar una integracin natural con JasperReport a


travs del uso de una librera (plug in):

struts2-jasperreports-plugin-2.1.8.1.jar

Esta librera viene por defecto con la versin estndar de Struts 2 y


permite crear en el archivo struts.xml un nuevo tipo de <result>: jasper

Se implementar, a continuacin, un ejercicio de aplicacin, 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 aplicacin web que permita listar los


clientes por Pas, haciendo uso de la librera JasperReport e
integrndola a Struts 2.

a) Paso 1: Importar el archivo


FuncionalidadIbatisReportes_Inicial.war

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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.

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


mysql

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 129

create table pais (


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

create table cliente ( 1


`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

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
130

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

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


ejecutar: /reportes/reporte01.jasper

Origen de datos para generar el listado


(dataSource): atributo listaClientes.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 131

d) Paso 4: Modificar el archivo tiles.xml

<definition name="d_reporte" extends="d_bienvenida">


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

Notas:

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

e) Paso 5: Cree el archivo reportes.jsp

<s:form method="post" action="reporteFacilito"> 1


<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

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
132

public class ReporteAction {


private String nombre;
private List<ReporteDTO> listaClientes; 1
public List<ReporteDTO> getListaClientes() {
return listaClientes;
}
public void setListaClientes(List<ReporteDTO> listaClientes)
{ this.listaClientes = listaClientes;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre)
{ this.nombre = nombre;
}
public String listaClientesPorPais(){
String vista="exito";
//JasperReportConstants.FORMAT_HTML
//JasperReportConstants.FORMAT_PDF
//JasperReportConstants.FORMAT_XLS
System.out.println("dentro de listaClientesPorPais :)");
try {
this.setListaClientes(
PaqueteBusinessDelegate.getClienteService().
2
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).

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 133

g) Paso 7: Modifica la clase ClienteService

public List<ReporteDTO> listaClientesReporte(String nombre) throws


Exception{
System.out.println("dentro del listaCliente del Service");
// Aqui podemos colocar logica adicional antes de invocar al metodo
1
// del DAO
return objClienteDAO.listaPorNombreReporte(nombre);

...

Notas:

1) Debe crear el mtodo listaClientesReporte para que la clase


ReporteAction pueda invocarlo y generar el reporte.

DESARROLLO DE SOFWARE BASADO EN


FRAMEWORKS
134

h) Paso 8: Modificar el archivo MySqlClienteDAO

public List<ReporteDTO> listaPorNombreReporte(String nombre) throws


Exception {
ArrayList<ReporteDTO> clientes= new ArrayList<ReporteDTO>();
1
Connection cn = MySqlDBConn.obtenerConexion();
//definimos la sentencia
String sql="SELECT
usuario,password,nombres,apellidos,sexo,fecha_nacimiento,dni,
c.cod_pais,p.nom_pais" +
" FROM cliente c,pais p WHERE c.nombres like ?
and c.cod_pais = p.cod_pais order by c.cod_pais";

//la preparamos
PreparedStatement pst=cn.prepareStatement(sql);
//asignamos valores a las interrogantes
pst.setString(1,"%"+nombre+"%"); //ejecutamos

ResultSet rs=pst.executeQuery();

while(rs.next()){
//hay dayos, recuperamos un ergsitro
ReporteDTO cliente = new ReporteDTO();
cliente.setUsuario(rs.getString(1));
cliente.setPassword(rs.getString(2));
cliente.setNombres(rs.getString(3));
cliente.setApellidos(rs.getString(4));
cliente.setSexo(rs.getString(5));
cliente.setFecha_nacimiento(rs.getString(6));
cliente.setDni(rs.getString(7));
cliente.setCod_pais(rs.getString(8));
cliente.setNom_pais(rs.getString(9));

clientes.add(cliente);
}
cn.close();
return clientes;
}
...

Notas:
1) Note 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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 135

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

<s:text name="menu.reporte" />


</s:a>

</td>
</tr>
...

Notas:

1) Debe invocar al action a_reporte para cargar la pgina JSP a


partir de la cual se generar el reporte.

i) Paso 10: Ejecutar la aplicacin web

Ingrese a la intranet a travs de la pgina de logueo. Se


visualizar la siguiente pantalla:

Seleccione la opcin reporte utilizando JasperReport

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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.

Visualizar el reporte en una pantalla similar a la siguiente:

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 137

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


con JasperReport y Struts 2 de manera exitosa!

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
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

Aqu, encontrar tutoriales que le permitirn crear reportes utilizando IReport.

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 139

ANEXOS

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
140

HERRAMIENTA #1: Java Development Kit


Desde la pgina de Oracle, descargue la ltima versin del JDK (Java Development
Kit). Se debe considerar que los updates de las versiones son peridicos.

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 141

HERRAMIENTA #2: Entorno Integrado de Desarrollo


En un entorno de desarrollo Java, el IDE ( Integrated Development Environment ) es la
herramienta de software que permite obtener mayor productividad al programar las
aplicaciones. En el mercado, existen varias opciones disponibles, pero las ms
utilizadas y conocidas son las siguientes:

Eclipse IDE : Sitio web http://www.eclipse.org


NetBeans : Sitio web http://www.netbeans.org
JDeveloper : Informacin disponible en http://www.oracle.com
Rational Application Developer: Informacin disponible en http://www.ibm.com

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
142

Rational Application Developer IDE :

Descargue el software IBM Rational Application Developer for WebSphere Software


desde la pgina web de IBM:
http://www.ibm.com/developerworks/downloads/r/rad/?S_CMP=TRIALS

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 143

HERRAMIENTA #3: Servidor de aplicaciones

Apache Tomcat

Desde la pgina de la Fundacin Apache ( http://tomcat.apache.org ), se debe obtener


el servidor de aplicaciones Tomcat.

La ltima versin probada en otros tutoriales ha sido la 6.0.20. Actualmente se


encuentra disponible la versin 7 en beta.

Slo es necesario el Core. Descargar el .ZIP y extraerlo en una carpeta.

WebSphere Application Server

Desde la pgina web de IBM, se puede descargar el software del servidor de


aplicaciones: http://www-01.ibm.com/software/webservers/appserv/was/

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
144

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 145

HERRAMIENTA #4: Motor de Base de Datos


Se necesita un motor de base de datos: En http://www.mysql.com, se puede decargar
la Base de Datos MySQL (versin Community Server )

Es preferible descargar la versin 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 lnea de comandos de la manera siguiente:

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
146

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 147

HERRAMIENTA #5: Libreras de Struts 2


Del sitio web de la Fundacin Apache, se obtienen las libreras del framework Struts 2
La ltima versin liberada es la 2.2.1

Se debe escoger una de las opciones de los archivos .ZIP. Con la alternativa de Full
Distribution, es ms que suficiente.

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
148

HERRAMIENTA #6: MyIbatis


La pgina principal se encuentra en http://www.mybatis.org/

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 149

HERRAMIENTA #7: MyIbatis Generator


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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
150

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 151

ANEXOS

ANEXO 2: MANEJO DE MYIBATIS

Ejemplo de una aplicacin con MyIbatis

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
152

La Clase entidad

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 153

El Data Access Object para Vendedor

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
154

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 155

El Archivo de Configuracin de MyIbatis


Se configura
los datos de la cadena de conexin
Se configura
los tipos de datos de los mappers
Se configura
la ubicacin de los mappers

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
156

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 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.

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>

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
158

choose, when, otherwise


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

trim, where, set

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

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

Foreach

<select id="selectPostIn" resultType="domain.blog.Post">


SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 159

ANEXOS

ANEXO 3: DE IBATIS 2.X HACIA MYIBATIS

En el sqlMapConfig.xml DTD:

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config


3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

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

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

Configuracin:

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
160

<settings useStatementNamespaces="true"/>

<typeAlias>

<typeAlias> deberia ser movido fuera de <sqlMap> hacia


<configuration>

<typeAliases></typeAliases>

</configuration>

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

<transactionManager> <dataSource>

Ibatis 2.0:

<transactionManager type="JDBC" commitRequired="false">


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

MyIbatis 3.0:

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

<sqlMap>

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 161

Ibatis 2.0:

<sqlMap resource=... />


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

MyIbatis 3.0:

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

Mapping

La raiz del elemento <sqlMap> es ahora <mapper>


El atributo parameterClass 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>

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
162

Nested resultMaps

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

DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS


DESARROLLO DE SOFWARE BASADO EN FRAMEWORKS 163

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

DESARROLLO DE SOFWARE
BASADO EN FRAMEWORKS
164

Dynamic SQL

Ibatis 2.0:

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

MyIbatis 3.0:

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


</if>

Potrebbero piacerti anche