desarrollo con java - media.readthedocs.org · ejecución del ejemplo teniendo instalado el jdk de...

137
Desarrollo con Java Versión Armando Arce 27 de abril de 2017

Upload: phamkien

Post on 29-Sep-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

Desarrollo con JavaVersión

Armando Arce

27 de abril de 2017

Índice general

1. Contenidos 3

I

II

Desarrollo con Java, Versión

El objetivo de este sitio es presentar un conjunto de tutoriales bá-sicos sobre el desarrollo de aplicaciones empresariales utilizando elambiente Java.

Los tutoriales disponibles hasta el momento son los siguientes:

Índice general 1

Desarrollo con Java, Versión

2 Índice general

CAPÍTULO 1

Contenidos

Uso de JSP

Una de las tecnologías más ampliamente utilizadas para el desarro-llo de aplicaciones Web bajo ambiente Java es JSP (Java Server Pa-ges). Esta herramienta permite crear una serie de plantillas HTML queincluyen código incrustado (llamados sniplets) mediante marcadoresespeciales.

El uso de JSP simplifica la programación de servlets pues no es ne-cesario compilar código ya que esto se realiza de forma automática.Además, debido a que la plantilla se escribe directamente en HTMLes factible utilizar editores y diseñadores de páginas Web para progra-mar la aplicación.

3

Desarrollo con Java, Versión

Creación de la base de datos

Para este ejemplo se creará una base de datos de prueba, llamadauniversidad.db, utilizando SQLite. Es posible utilizar diferentes he-rramientas para crear bases de datos en este formato, entre ellas seencuentra el plugin para Firefox llamado SQLite Manager, o bien, laherramienta SQLiteBrowser.

Por el momento solo se utilizará una tabla con información de profe-sores de una universidad. El código SQL para crear dicha tabla seríael siguiente:

CREATE TABLE "profesor" (id INTEGER PRIMARY KEY ASC,cedula VARCHAR,nombre VARCHAR,titulo VARCHAR,area VARCHAR,telefono VARCHAR

);

Luego de crear la base de datos se agregaron algunos datos de ejemploa esta tabla. Las siguientes instrucciones SQL permiten poblar la tablaalguna información:

INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (1,'101110111','Carlos Perez Rojas',

→˓'Licenciado','Administracion','3456-7890');

INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (2,'202220222','Luis Torres','Master',

'Economia','6677-3456');INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (3,'303330333','Juan Castro','Licenciado',

'Matematica','67455-7788');

4 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Página de listado de profesores

La primer página consistirá del listado de todos los profesores que seencuentran en la base de datos. El código que se muestra a continua-ción (llamado listaProfesores.jsp) establece la conexión con la basede datos (utilizado JDBC), ejecuta la instrucción de consulta, recupe-ra los datos y crea una tabla HTML con la información obtenida.

<%@ page import="java.sql.*" %><%

String driver="org.sqlite.JDBC";String url="jdbc:sqlite:database/universidad.db

→˓";Class.forName(driver);Connection conn=null;try {

conn = DriverManager.getConnection(url);String sql="select * from profesor";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);

%><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2><table><thead><tr><th>Cedula</th><th>Nombre</th><th>Titulo</th><th>Acciones</th></tr></thead><tbody><% while (rs.next()) {

String id = rs.getString(1);String cedula = rs.getString(2);String nombre = rs.getString(3);String titulo = rs.getString(4);

%>

1.1. Uso de JSP 5

Desarrollo con Java, Versión

<tr><td><%= cedula %></td><td><%= nombre %></td><td><%= titulo %></td><td><a href='/detalleProfesor.jsp?id=<%=

→˓id %>'><input type="submit" value="Detalle"/

→˓></a><a href='/eliminarProfesor.jsp?id=<%=

→˓id %>'><input type="submit" value="Eliminar

→˓"/></a></td></tr><% } %>

</tbody><tfoot><tr><td><a href='/agregarProfesor.jsp'>

<input type="submit" name="action" value=→˓"Agregar"/></a>

</td><td></td><td></td><td></td></tr></tfoot></table>

</html><%

rs.close();rs=null;stmt.close();stmt=null;if (conn!=null)

conn.close();} catch (Exception e) {

e.printStackTrace();}

%>

Es importante observar en este código que existen enlaces que accede-rán a otras páginas para realizar acciones con los datos. Por ejemplo,el enlace de “Detalle” ejecutará la página detalleProfesor.jsp con elparámetro ID; y el enlace de “Eliminar” ejecutará la página eliminar-Profesor.jsp con el mismo parámetro ID. También está presente otroenlace “Agregar” que invocará a la página agregarProfesor.jsp perosin parámetros.

6 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Detalle del profesor

La página detalleProfesor.jsp recibe como parámetro el ID de un pro-fesor, recupera sus datos desde la base y datos, y los muestra en unformulario HTML. La estructura general de la consulta a la base dedatos es muy similar a la anterior con la diferencia que se recuperasolo un registro particular.

<%@ page import="java.sql.*" %><%

String id = request.getParameter("id");String driver="org.sqlite.JDBC";String url="jdbc:sqlite:database/universidad.db

→˓";Class.forName(driver);Connection conn=null;try {

conn = DriverManager.getConnection(url);String sql="select * from profesor where id='

→˓"+id+"'";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);

%><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><form name="ActualizarProfesor" action=

→˓"actualizarProfesor" method="get"><table style="width:400px;"><thead><tr><th></th><th></th></tr></thead><tbody><% rs.next();

String cedula = rs.getString(2);String nombre = rs.getString(3);

1.1. Uso de JSP 7

Desarrollo con Java, Versión

String titulo = rs.getString(4);String area = rs.getString(5);String telefono = rs.getString(6);

%><input type="hidden" name="id" value="<%= id %>

→˓"/><tr><td>Nombre:</td><td>

<input type="text" name="nombre" value="<%=→˓nombre %>"/></td></tr>

<tr><td>Cedula:</td><td><input type="text" name="cedula" value="<%=

→˓cedula %>"/></td></tr><tr><td>Titulo:</td><td>

<input type="text" name="titulo" value="<%=→˓titulo %>"/></td></tr>

<tr><td>Area:</td><td><input type="text" name="area" value="<%=

→˓area %>"/></td></tr><tr><td>Telefono:</td><td>

<input type="text" name="telefono" value="<→˓%= telefono %>"/></td></tr>

</tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr></tfoot>

</tbody></table></form>

</html><%

rs.close();rs=null;stmt.close();stmt=null;if (conn!=null)

conn.close();} catch (Exception e) {

e.printStackTrace();}

%>

8 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Este código también cuenta con un enlace adicional “Actualizar” quepermite tomar la información del formulario y realizar la actualiza-ción de datos en la base de datos, mediante la página actualizarPro-fesor.jsp

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;

1.1. Uso de JSP 9

Desarrollo con Java, Versión

color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

Ambiente de ejecución

Para ejecutar este ejemplo es necesario contar con un servidor de ser-vlets que permita también la ejecución de plantillas JSP. La herra-mienta más utilizada para esto es el Apache Tomcat, el cuál es muypotente y cuenta con gran cantidad de parámetros de configuración.Sin embargo, para propósito de desarrollo y depuración de programasbasta con un ambiente más liviano tal como Winstone.

Winstone consiste de un único archivo de menos de 350 KB, llama-do winstone-0.9.10.jar, el cual puede ser ejecutado directamente me-diante Java. Sin embargo, poder utilizar plantillas JSP se requiere dela herramienta Jasper que consiste de múltiples librerías adicionales.

Para acceder a la base de datos SQLite, mediante JDBC, es necesariocontar con una librería que incluya el driver adecuado. Aún cuandoexisten diferentes librerías que hacen esto, ninguna es pequeña.

Estructura de directorios

La ubicación de los diferentes archivos de código, y librerías se mues-tra en el siguiente esquema de directorios:

tutorial1run.batwinstone-0.9.10.jar

10 Capítulo 1. Contenidos

Desarrollo con Java, Versión

databaseuniversidad.db

rootstyle.csslistaProfesores.jspdetalleProfesor.jsp

libel-api-6.0.18.jarjasper-6.0.18.jarjasper-el-6.0.18.jarjsp-api-6.0.18.jarjuli-6.0.18.jarservlet-api-2.5.jarsqlite-jdbc-3.5.9.jar

Ejecución del ejemplo

Teniendo instalado el JDK de Java (no el JRE) basta con ejecutar elarchivo run.bat para iniciar el servidor. El archivo run.bat cuenta conlas siguientes instrucciones:

set PATH=C:\Java\jdk1.7.0\bin;%PATH%java -jar winstone-0.9.10.jar --httpPort=8089 ^

--commonLibFolder=lib --useJasper=true --→˓webroot=root

Luego se debe apuntar el visualizador (browser) de Web a la direcciónhttp://localhost:8089/listaProfesores.jsp

Nota: Es posible que el JDK de Java se encuentre instalado en otrodirectorio en su máquina.

Rutinas de Transacción

A continuación se presenta un ejemplo sencillo de la aplicación Webdel Sistema Universitario, lo que servirá para mostrar el uso de dife-

1.2. Rutinas de Transacción 11

Desarrollo con Java, Versión

rentes capas y de cómo se debe estructurar una aplicación para obtenerel mayor provecho de las aplicaciones empresariales.

En este ejemplo se combinarán tres patrones descritos por Fowler:rutinas de transacción para la lógica del dominio, pasarela a fila dedatos para la capa de acceso a los datos, y controlador frontal para lacapa de presentación. Más específicamente, las rutinas de transacciónse estructurarán utilizando el patrón comando.

Capa de acceso a datos

La capa de acceso a datos utilizará una pasarela a filas de datos quese conectará a una base de datos SQLite. Este tipo de técnica tambiénrequiere crear una clase que se encargue de crear la pasarela, llamadaun “finder”.

Base de datos

Se utilizará una base de datos SQLite para administrar los datos. Di-cha base de datos debe llevar por nombre universidad.db y debe estarubicada en el directorio /tutorial2/database/. El código SQL utilizadopara generar la tabla de profesores sería el siguiente:

CREATE TABLE profesor (id INTEGER PRIMARY KEY,→˓cedula VARCHAR,nombre VARCHAR, titulo VARCHAR, area VARCHAR,

→˓telefono VARCHAR);INSERT INTO profesor VALUES(1,'101110111','Carlos→˓Perez','Licenciado','Administracion','3456-7890');

INSERT INTO profesor VALUES(2,'202220222','Luis→˓Torres','Master','Economia','6677-3456');

INSERT INTO profesor VALUES(3,'303330333','Juan→˓Castro','Licenciado','Matematica','6755-7788');

12 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Para administrar una base de datos SQLite se puede utilizar alguno delos excelentes productos creados para ello, tal como SQLiteman ó elplugin para Firefox llamado SQLite Manager

Pasarela a fila de datos

Para implementar la capa de acceso de datos se utiliza una pasare-la a filas de datos. Para ello es necesario crear una clase que per-mita acceder a la información de la base de datos cuyo nombre esProfesorRowGateway.java. Dicha clase residirá en el directorio /tuto-rial2/src/data/

package data;

import java.util.*;import java.sql.*;import javax.sql.*;import org.springframework.jdbc.core.JdbcTemplate;

public class ProfesorRowGateway {

private int id;private String cedula;private String nombre;private String titulo;private String area;private String telefono;private JdbcTemplate jdbcTemplate;private DataSource dataSource;

ProfesorRowGateway() {};

ProfesorRowGateway(int id, String ced, String→˓nomb,

String tit, String→˓area, String tel) {

this.id=id; this.cedula=ced; this.→˓nombre=nomb;

this.titulo=tit;this.area=area;this.→˓telefono=tel;

1.2. Rutinas de Transacción 13

Desarrollo con Java, Versión

}

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

public void setCedula(String ced) {this.→˓cedula=ced;}public String getCedula() {return cedula;}

public void setNombre(String nomb) {this.→˓nombre=nomb;}public String getNombre() {return nombre;}

public void setTitulo(String tit) {this.→˓titulo=tit;}public String getTitulo() {return titulo;}

public void setArea(String area) {this.area=area;→˓}public String getArea() {return area;}

public void setTelefono(String tel) {this.→˓telefono=tel;}public String getTelefono() {return telefono;}

public void setDataSource(DataSource dataSource)→˓{

this.dataSource = dataSource;}

private void createJdbcTemplate() {jdbcTemplate = new

→˓JdbcTemplate(dataSource);}

private static final String insertStatement ="INSERT INTO profesor "+"VALUES (?,?,?,?,?,?)";

public int insert() {

14 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Random generator = new Random();int id = generator.nextInt();if (jdbcTemplate==null)

→˓createJdbcTemplate();jdbcTemplate.update(insertStatement,

id,cedula,nombre,titulo,area,→˓telefono);

return id;}

private static final String updateStatement ="UPDATE profesor "+"SET cedula = ?, nombre = ?, titulo = ?, "+"area = ?, telefono = ? WHERE id = ?";

public void update() {if (jdbcTemplate==null)

→˓createJdbcTemplate();jdbcTemplate.update(updateStatement,

cedula,nombre,titulo,area,→˓telefono,id);}

private static final String deleteStatement ="DELETE FROM profesor "+"WHERE id = ?";

public void delete() {if (jdbcTemplate==null)

→˓createJdbcTemplate();jdbcTemplate.update(deleteStatement,id);

}

public static ProfesorRowGateway load(DataSource→˓ds, Map map) {

ProfesorRowGateway prof=null;if (map==null)prof = new ProfesorRowGateway();

else {int id = ((Integer)map.get("id")).

→˓intValue();

1.2. Rutinas de Transacción 15

Desarrollo con Java, Versión

String cedula = (String)map.get("cedula→˓");

String nombre = (String)map.get("nombre→˓");

String titulo = (String)map.get("titulo→˓");

String area = (String)map.get("area");String telefono = (String)map.get(

→˓"telefono");prof = new ProfesorRowGateway(id,cedula,

→˓nombre,titulo,area,telefono);}prof.setDataSource(ds);return prof;

}}

Generación de objetos de pasarelas

Para manejar este tipo de técnica es necesario contar con otra cla-se encargada de crear las pasarelas. Esta nueva clase se define enel archivo ProfesorFinder.java y reside en el mismo directorio /tu-torial2/src/data/

package data;

import java.util.*;import java.sql.*;import javax.sql.*;import org.springframework.jdbc.core.JdbcTemplate;

public class ProfesorFinder {

private JdbcTemplate jdbcTemplate;private DataSource dataSource;

public void setDataSource(DataSource dataSource)→˓{

16 Capítulo 1. Contenidos

Desarrollo con Java, Versión

this.dataSource = dataSource;this.jdbcTemplate = new

→˓JdbcTemplate(dataSource);}

public ProfesorRowGateway create() {return ProfesorRowGateway.load(dataSource,

→˓null);}

private final static String findStatement ="SELECT * "+"FROM profesor "+"WHERE id = ?";

public ProfesorRowGateway find(String id) {List profs =jdbcTemplate.queryForList(findStatement,

→˓id);ProfesorRowGateway prof =ProfesorRowGateway.load(dataSource,

→˓(Map)profs.get(0));return prof;

}

private final static String findAllStatement ="SELECT * "+"FROM profesor ";

public List<ProfesorRowGateway> findAll() {List result = new ArrayList();List profs = jdbcTemplate.

→˓queryForList(findAllStatement);for (int i=0; i<profs.size();i++)result.add(ProfesorRowGateway.

→˓load(dataSource,(Map)profs.get(i)));return result;

}}

1.2. Rutinas de Transacción 17

Desarrollo con Java, Versión

Compilando la capa de datos

Se puede realizar la compilación de estas dos clases en forma sepa-rada del resto del código. Para ello es necesario contar con el fra-mework Spring 3 el cual se debe descargar y copiar todas las libre-rías .jar del directorio lib de dicho framework hacia el directorio/tutorial2/root/WEB-INF/lib/. También es necesario contar en dichodirectorio con el driver jdbc para SQLite y las librerías commons paramanejo de conexiones a base de datos.

Específicamente las librerías que deben residir en el directorio/tutorial2/root/WEB-INF/lib/ son las siguientes:

commons-dbcp-1.4.jar

commons-logging-1.1.1.jar

commons-pool-1.6.jar

servlet-api.jar

spring-asm-3.2.0.M1.jar

spring-beans-3.2.0.M1.jar

spring-context-3.2.0.M1.jar

spring-core-3.2.0.M1.jar

spring-expression-3.2.0.M1.jar

spring-jdbc-3.2.0.M1.jar

spring-tx.3.2.0.M1.jar

spring-web-3.2.0.M1.jar

sqlite-jdbc-3.5.9.jar

La siguiente instrucción para ejecutar la compilación puede estar de-finida en un archivo compileDataLayer.bat residente en el directorio/tutorial2 (todo en una sola línea):

18 Capítulo 1. Contenidos

Desarrollo con Java, Versión

javac -cp "root/WEB-INF/lib/*" -d root/WEB-INF/→˓classes

src/data/ProfesorRowGateway.java src/data/→˓ProfesorFinder.java

Nota: La versión del JDK debe ser superior a 6.0

Capa de presentación

El servicio de la universidad ha sido implementado como un contro-lador frontal, en donde cada rutina de transacción será implementadacomo un comando. El archivo del servicio se llamará FrontContro-ller.java y debe residir en el directorio /tutorial2/src/display/

package display;

import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

import org.springframework.web.context.*;import org.springframework.web.context.support.*;

public class FrontController extends HttpServlet {

private WebApplicationContext context;

public void init(ServletConfig config) throws→˓ServletException {

super.init(config);context =WebApplicationContextUtils.

→˓getWebApplicationContext(getServletContext());}

public void doGet(HttpServletRequest request,

→˓HttpServletResponse response)

1.2. Rutinas de Transacción 19

Desarrollo con Java, Versión

throws ServletException,IOException {FrontCommand command =

getCommand((String)request.getAttribute(→˓"command"));

command.init(context,request,response);command.process();

}

private FrontCommand getCommand(String→˓commandName) {

try {return (FrontCommand)

→˓getCommandClass(commandName).newInstance();} catch (Exception e) {e.printStackTrace();

}return null;

}

private Class getCommandClass(String→˓commandName) {

Class result;try {result = Class.forName(commandName);

} catch (ClassNotFoundException e) {result = UnknownCommand.class;

}return result;

}}

La clase para los comandos

Como se indicó antes, cada transacción se implementa como un co-mando independiente de todos los demás. Existe una clase abstractaFrontCommand.java que permite definir los métodos comunes a cual-quier comando. Este archivo también se ubica en el directorio /tuto-rial2/src/display/

20 Capítulo 1. Contenidos

Desarrollo con Java, Versión

package display;import java.util.*;

import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

public abstract class FrontCommand {

public WebApplicationContext context;public HttpServletRequest request;public HttpServletResponse response;

public void init(WebApplicationContext ctx,

→˓HttpServletRequest req,

→˓HttpServletResponse resp) {this.context = ctx;this.request = req;this.response = resp;

}

protected void forward(String target)throws ServletException, IOException {RequestDispatcher dispatcher =context.getServletContext().

→˓getRequestDispatcher(target);dispatcher.forward(request,response);

}

public abstract void process()throws ServletException, IOException;

}

1.2. Rutinas de Transacción 21

Desarrollo con Java, Versión

Comandos desconocidos

Cuando se pretende ejecutar un comando desconocido es necesariointerceptar dicha solicitud e imprimir un mensaje de advertencia. Laclase UnknownCommand.java se encarga de esta tarea y reside en elmismo directorio /tutorial2/src/display/

package display;import java.io.*;import javax.servlet.*;

public class UnknownCommand extends FrontCommand {

public void process()throws ServletException, IOException {forward("/unknown.jsp");

}}

También es necesario contar con una pequeña plantilla JSP que per-mite generar el mensaje que se presentará en pantalla. El código deesta plantilla se ubica en el archivo unknown.jsp que reside en el di-rectorio /tutorial2/root/

<html><head>

<title>Sistema Universitario</title></head><h1>Operación inválida</h1>

</html>

Compilando la capa de presentación

También, se puede realizar la compilación de estas clases de presenta-ción en forma separada del resto del código de la aplicación. Para elloes necesario contar con las librerías del framework Spring 3 (como seindicó antes) y con la librería servlet-api.jar ubicadas en el directorio/tutorial2/root/WEB-INF/lib/. La siguiente instrucción para ejecutar

22 Capítulo 1. Contenidos

Desarrollo con Java, Versión

la compilación puede estar definida en un archivo compileDisplayLa-yer.bat residente en el directorio /tutorial2/ (todo en una sola línea):

javac -cp "root/WEB-INF/lib/*" -d root/WEB-INF/→˓classes

src/display/FrontController.java src/display/→˓FrontCommand.java

src/display/UnknownCommand.java

La capa de lógica del dominio

Para implementar la capa de lógica del dominio se utilizará la técnicade rutinas de transacción. En dicho caso cada rutina es responsablede recuperar los parámetros de la consulta, acceder a la tabla de datos,procesar los datos, e invocar a la rutina de presentación.

La rutina de listado

Para presentar el listado de profesores se crea la clase ListaProfeso-res.java en el directorio /tutorial2/src/domain/

package domain;

import display.FrontCommand;import data.ProfesorRowGateway;import data.ProfesorFinder;

import java.util.Map;import java.util.HashMap;import java.util.List;import java.util.ArrayList;import java.io.IOException;import java.sql.SQLException;import javax.servlet.ServletException;

public class ListaProfesores extends FrontCommand {

1.2. Rutinas de Transacción 23

Desarrollo con Java, Versión

public void process()throws ServletException, IOException {ProfesorFinder profs =(ProfesorFinder) context.getBean(

→˓"profesorFinder");List<ProfesorRowGateway> data = profs.

→˓findAll();List param = new ArrayList();for (int i=0;i<data.size();i++) {ProfesorRowGateway prof = data.get(i);Map item = new HashMap();item.put("id",prof.getId()+"");item.put("cedula",prof.getCedula());item.put("nombre",prof.getNombre());item.put("titulo",prof.getTitulo());item.put("area",prof.getArea());item.put("telefono",prof.getTelefono());param.add(item);

}request.setAttribute("profesores",param);forward("/listaProfesores.jsp");

}}

Plantilla JSP

Adicionalmente se utilizará una plantilla JSP para realizar el formateode página en código HTML. El archivo listaProfesores.jsp se encargade esta tarea y residirá en el directorio /tutorial2/root/

<%@ page import="java.util.*" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2>

24 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<% List profs = (List)request.getAttribute(→˓"profesores"); %><table>

<thead><tr><th>Nombre</th><th>Título</th>

<th>Area</th><th>Acciones</th></tr></thead><tbody><% for(int i = 0, n = profs.size(); i < n;

→˓i++) {Map prof = (Map) profs.get(i); %><tr><td><%= prof.get("nombre") %></

→˓td><td><%= prof.get("titulo") %></td><td><%= prof.get("area") %></td><td>

<a href='/domain.DetalleProfesor?id=<%=→˓prof.get("id") %>'>

<input type="submit" value="Detalle"/>→˓</a>

<a href='/domain.EliminarProfesor?id=<%=→˓prof.get("id") %>'>

<input type="submit" value="Eliminar"/>→˓</a></td></tr>

<% } %></tbody><tfoot><tr><td><a href='/domain.AgregarProfesor

→˓'><input type="submit" name="action"

→˓value="Agregar"/></a></td><td></td><td></td><td></td></tr>

</tfoot></table>

</html>

Nótese que la tabla generada cuenta con enlaces que invocarán la ru-tina que presenta el detalle del profesor (que se describe a continua-ción).

1.2. Rutinas de Transacción 25

Desarrollo con Java, Versión

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

26 Capítulo 1. Contenidos

Desarrollo con Java, Versión

}input[type="text"] {

width: 250px;}

La rutina de detalle

La rutina de detalle de profesor presentará otra tabla HTML con la in-formación detallada del profesor. Este archivo es llamado DetallePro-fesor.java y se ubica en el mismo directorio /tutorial2/src/domain/. Esimportante observar la utilización del id del profesor para realizar laconsulta a la pasarela de datos.

package domain;

import display.FrontCommand;import data.ProfesorFinder;import data.ProfesorRowGateway;

import java.util.Map;import java.util.HashMap;import java.io.IOException;import javax.servlet.ServletException;

public class DetalleProfesor extends FrontCommand {

public void process()throws ServletException, IOException {ProfesorFinder profs =

(ProfesorFinder) context.getBean(→˓"profesorFinder");

String id = request.getParameter("id");ProfesorRowGateway prof = profs.find(id);Map params = new HashMap();params.put("id",prof.getId()+"");params.put("cedula",prof.getCedula());params.put("nombre",prof.getNombre());params.put("titulo",prof.getTitulo());

1.2. Rutinas de Transacción 27

Desarrollo con Java, Versión

params.put("area",prof.getArea());params.put("telefono",prof.getTelefono());request.setAttribute("profesor",params);forward("/detalleProfesor.jsp");

}}

Plantilla JSP

La plantilla JSP que genera el código HTML se presenta a continua-ción. El código de la plantilla se define en un archivo llamado deta-lleProfesor.jsp que reside también en el directorio /tutorial2/root/.

<%@ page import="java.util.Map" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><% Map prof = (Map)request.getAttribute("profesor

→˓"); %><form name="ActualizarProfesor"

action="/domain.ActualizarProfesor" method=→˓"get"><input type="hidden" name="id" value="<%= prof.

→˓get("id") %>"/><table style="width:400px;"><thead>

<tr><th></th><th></th></tr></thead><tbody>

<tr><td>Nombre:</td><td><input type="text"→˓name="nombre"

value="<%= prof.get("nombre") %>"/>→˓</td></tr>

<tr><td>Cédula:</td><td><input type="text"→˓name="cedula"

28 Capítulo 1. Contenidos

Desarrollo con Java, Versión

value="<%= prof.get("cedula") %>"/>→˓</td></tr>

<tr><td>Título:</td><td><input type="text"→˓name="titulo"

value="<%= prof.get("titulo") %>"/>→˓</td></tr>

<tr><td>Area:</td><td><input type="text"→˓name="area"

value="<%= prof.get("area") %>"/></→˓td></tr>

<tr><td>Teléfono:</td><td><input type="text→˓" name="telefono"

value="<%= prof.get("telefono") %>→˓"/></td></tr>

</tbody><tfoot>

<tr><td><input type="submit" value=→˓"Actualizar" /></td><td></td></tr>

</tfoot></tbody></table></form>

</html>

Actualizar información

Se presenta también la rutina de transacción que permite actualizar losdatos de un profesor. La lógica de esta rutina se ubica en el archivo Ac-tualizarProfesor.java y reside en el directorio /tutorial2/src/domain/.

package domain;

import display.FrontCommand;import data.ProfesorFinder;import data.ProfesorRowGateway;

import java.util.Map;import java.util.HashMap;

1.2. Rutinas de Transacción 29

Desarrollo con Java, Versión

import java.io.IOException;import javax.servlet.ServletException;

public class ActualizarProfesor extends→˓FrontCommand {

public void process()throws ServletException, IOException {ProfesorFinder profs =

(ProfesorFinder) context.getBean(→˓"profesorFinder");

String id = request.getParameter("id");ProfesorRowGateway prof = profs.find(id);if (prof!=null) {String cedula = request.getParameter(

→˓"cedula");if (cedula!=null) prof.setCedula(cedula);String nombre = request.getParameter(

→˓"nombre");if (nombre!=null) prof.setNombre(nombre);String titulo = request.getParameter(

→˓"titulo");if (titulo!=null) prof.setTitulo(titulo);String area = request.getParameter("area

→˓");if (area!=null) prof.setArea(area);String telefono = request.getParameter(

→˓"telefono");if (telefono!=null) prof.

→˓setTelefono(telefono);prof.update();

}response.sendRedirect("domain.

→˓ListaProfesores");}

}

30 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Compilando la capa de dominio

Se puede realizar la compilación de estas clases de dominio en for-ma separada del resto del código de la aplicación. Para ello es ne-cesario contar con las librerías del framework Spring 3 (como se in-dicó antes) y con la librería servlet-api.jar ubicadas en el directorio/tutorial2/root/WEB-INF/lib/. La siguiente instrucción para ejecutarla compilación puede estar definida en un archivo compileDomainLa-yer.bat residente en el directorio /tutorial2 (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"

-d root/WEB-INF/classes src/domain/→˓ListaProfesores.java

src/domain/DetalleProfesor.java src/domain/→˓ActualizarProfesor.java

Configuración del contexto

El framework Spring permite crear archivos xml que definen la con-figuración del contexto de ejecución de la aplicación. El archivo deconfiguración llamado context.xml se deberá ubicar en el directorio/tutorial2/root/WEB-INF/ y contendrá la siguiente información.

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"

xmlns:xsi="http://www.w3.org/2001/→˓XMLSchema-instance"

xmlns:context="http://www.springframework.→˓org/schema/context"

xsi:schemaLocation="http://www.springframework.org/

→˓schema/beanshttp://www.springframework.org/

→˓schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/

→˓schema/context

1.2. Rutinas de Transacción 31

Desarrollo con Java, Versión

http://www.springframework.org/→˓schema/context/spring-context-3.0.xsd">

<bean id="profesorFinder" class="data.→˓ProfesorFinder">

<property name="dataSource" ref=→˓"dataSource"/>

</bean><bean id="dataSource" class="org.apache.

→˓commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName"

→˓value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.

→˓url}"/><property name="username" value="$

→˓{jdbc.username}"/><property name="password" value="$

→˓{jdbc.password}"/></bean><context:property-placeholder location=

→˓"WEB-INF/jdbc.properties"/></beans>

Los aspectos importantes que se pueden observar en este archivo sonla declaración de una instancia (singleton) al constructor de pasarelasy la declaración de la fuente de datos JDBC.

Precisamente para configurar la fuente de datos se utilizará un archivode propiedades llamado jdbc.properties y que residirá en el directorio/tutorial2/root/WEB-INF. Su contenido es simplemente el siguiente:

jdbc.driverClassName=org.sqlite.JDBCjdbc.url=jdbc:sqlite:database/universidad.dbjdbc.username=sajdbc.password=root

Sin embargo, note que una base de datos SQLite no requiere indicarel usuario y su clave.

32 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Configuración del servidor

El servidor de servlets requiere del archivo de configuración de laaplicación para conocer en donde se ubica la clase a ejecutar. Ade-más este archivo permite indicar la ubicación y nombre del archivode contexto. Estos archivos de configuración del servlet siempre sellaman web.xml y deben residir en el directorio /tutorial2/root/WEB-INF/. Para este caso su contenido sería el siguiente:

<?xml version="1.0" encoding="ISO-8859-1"?><web-app 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→˓"

version="2.4"><display-name>Sistema Universitario</display-name><description>Ejemplo de Rutinas de Transaccion</→˓description><context-param>

<param-name>contextConfigLocation</param-→˓name>

<param-value>/WEB-INF/context.xml</param-→˓value></context-param><listener>

<listener-class>org.springframework.web.context.

→˓ContextLoaderListener</listener-class>

</listener><filter>

<filter-name>UrlRewriteFilter</filter-name><filter-class>org.tuckey.web.filters.

→˓urlrewrite.UrlRewriteFilter</filter-class></filter><filter-mapping>

<filter-name>UrlRewriteFilter</filter-name>

1.2. Rutinas de Transacción 33

Desarrollo con Java, Versión

<url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>FrontController</servlet-name><servlet-class>display.FrontController</servlet-

→˓class></servlet><servlet-mapping><servlet-name>FrontController</servlet-name><url-pattern>/frontController</url-pattern>

</servlet-mapping></web-app>

Como se puede observar en este archivo, se utilizará una librería espe-cial que permite redireccionar las solicitudes que se hacen al serviciocon base en su URL. Para esto es necesario contar con un archivo url-rewrite.xml que se muestra a continuación y que residirá en el mismodirectorio /tutorial2/root/WEB-INF/

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD→˓UrlRewrite 2.6//EN"

"http://tuckey.org/res/dtds/urlrewrite2.6.→˓dtd"><urlrewrite>

<rule><from>/*.css</from><to>.css</to>

</rule><rule><from>/(.*)$</from><to>/frontController</to><set name="command">$1</set>

</rule></urlrewrite>

34 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Ejecución del tutorial

Este ejemplo se puede ejecutar bajo cualquier contenedor de Servlet.Por ejemplo, para realizar la ejecución de pruebas se puede utilizarun producto como el Winstone Servlet Container que permite ejecu-tar servlets de forma muy sencilla. Se debe descargar el programawinstone-0.9.10.jar y copiarlo en el directorio /tutorial2/. Sin em-bargo, para lograr que Winstone ejecute plantillas JSP es necesariodescargar algunas librerías adicionales que deben ser copiadas en eldirectorio /tutorial2/lib:

el-api-6.0.18.jar

jasper-6.0.18.jar

jasper-el-6.0.18.jar

jasper-jdt-6.0.18.jar

jsp-api-6.0.18.jar

jstl-api-1.2.jar

jstl-impl-1.2.jar

jtds-1.2.4.jar

juli-6.0.18.jar

servlet-api-2.5.jar

servlet-api.jar

urlrewrite-3.2.0.jar

Para ejecutar el servidor de servlets se puede crear un archivo de ins-trucciones, llamado run.bat, similar al siguiente en el directorio /tuto-rial2/ (todo en una sola línea):

java -jar winstone-0.9.10.jar --httpPort=8089 --→˓commonLibFolder=lib

--useJasper=true --webroot=root

1.2. Rutinas de Transacción 35

Desarrollo con Java, Versión

Luego se puede acceder a la aplicación desde cualquier visualiza-dor web y apuntando a la dirección http://localhost:8089/domain.ListaProfesores

Módulo de Tabla

A continuación se presenta el mismo ejemplo del tutorial anterior deuna aplicación Web de un Sistema Universitario. En este ejemplo secombinarán otros tres patrones descritos por Fowler: módulo de tablapara la lógica del dominio, pasarela a tabla de datos para la capa deacceso a los datos, y controlador de página para la capa de presenta-ción.

Capa de acceso a datos

La capa de acceso a datos utilizará una pasarela a tabla de datos quese conectará a una base de datos SQLite.

Base de datos

Se utilizará la misma base de datos SQLite del tutorial anterior paraadministrar los datos. Dicha base de datos debe llevar por nombre uni-versidad.db y debe estar ubicada en el directorio /tutorial3/database/.El código SQL utilizado para generar la tabla de profesores sería elsiguiente:

CREATE TABLE profesor (id INTEGER PRIMARY KEY,→˓cedula VARCHAR,nombre VARCHAR, titulo VARCHAR, area VARCHAR,

→˓telefono VARCHAR);INSERT INTO profesor VALUES(1,'101110111','Carlos→˓Perez','Licenciado','Administracion','3456-7890');

INSERT INTO profesor VALUES(2,'202220222','Luis→˓Torres',

36 Capítulo 1. Contenidos

Desarrollo con Java, Versión

'Master','Economia','6677-3456');INSERT INTO profesor VALUES(3,'303330333','Juan→˓Castro','Licenciado','Matematica','6755-7788');

Para administrar una base de datos SQLite se puede utilizar alguno delos excelentes productos creados para ello, tal como SQLiteman ó elplugin para Firefox llamado SQLite Manager

Pasarela a tabla de datos

Para implementar la capa de acceso de datos se utiliza una pasare-la a tabla de datos. Para ello es necesario crear una clase abstractaque se encargue de almacenar la conexión jdbc. Esta clase se llamaráTableGateway.java y residirá en el directorio /tutorial3/src/data/.

package data;

import java.util.*;import javax.sql.*;import org.springframework.jdbc.core.JdbcTemplate;

public abstract class TableGateway {

protected JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource)→˓{

this.jdbcTemplate = new→˓JdbcTemplate(dataSource);}

}

La otra clase necesaria es la que implementa la tabla de datos para losprofesores. Este archivo se llama ProfesorGateway.java y reside en elmismo directorio /tutorial3/src/data/.

1.3. Módulo de Tabla 37

Desarrollo con Java, Versión

package data;

import java.util.*;import javax.sql.*;import org.springframework.jdbc.core.JdbcTemplate;

public class ProfesorGateway extends TableGateway {

private final static String findStatement ="SELECT * "+"FROM profesor "+"WHERE id = ?";

public Map<String, Object> find(String id) {List profs = jdbcTemplate.

→˓queryForList(findStatement,id);return (Map<String, Object>)profs.get(0);

}

private final static String findAllStatement ="SELECT * "+"FROM profesor ";

public List<Map<String, Object>> findAll() {return jdbcTemplate.

→˓queryForList(findAllStatement);}

private static final String insertStatement ="INSERT INTO profesor "+

"VALUES (?,?,?,?,?,?)";

public int insert(String cedula,String nombre,→˓String titulo,

String area, String telefono) {Random generator = new Random();int id = generator.nextInt();

jdbcTemplate.update(insertStatement,id,cedula,nombre,titulo,area,telefono);

return id;

38 Capítulo 1. Contenidos

Desarrollo con Java, Versión

}

private static final String updateStatement ="UPDATE profesor "+"SET cedula = ?, nombre = ?, titulo = ?, "+"area = ?, telefono = ? WHERE id = ?";

public void update(int id,String cedula,String→˓nombre,

String titulo, String area, String telefono) {jdbcTemplate.update(updateStatement,

cedula,nombre,titulo,area,telefono,id);}

private static final String deleteStatement ="DELETE FROM profesor "+"WHERE id = ?";

public void delete(int id) {jdbcTemplate.update(deleteStatement,id);

}}

Compilando la capa de datos

Se puede realizar la compilación de estas dos clases en forma sepa-rada del resto del código. Para ello es necesario contar con el fra-mework Spring 3 el cual se debe descargar y copiar todas las libre-rías .jar del directorio lib de dicho framework hacia el directorio/tutorial3/root/WEB-INF/lib/. También es necesario contar en dichodirectorio con el driver jdbc para SQLite y las librerías commons paramanejo de conexiones a base de datos.

Específicamente las librerías que deben residir en el directorio/tutorial3/root/WEB-INF/lib/ son las siguientes:

commons-dbcp-1.4.jar

commons-logging-1.1.1.jar

1.3. Módulo de Tabla 39

Desarrollo con Java, Versión

commons-pool-1.6.jar

servlet-api.jar

spring-asm-3.2.0.M1.jar

spring-beans-3.2.0.M1.jar

spring-context-3.2.0.M1.jar

spring-core-3.2.0.M1.jar

spring-expression-3.2.0.M1.jar

spring-jdbc-3.2.0.M1.jar

spring-tx.3.2.0.M1.jar

spring-web-3.2.0.M1.jar

sqlite-jdbc-3.5.9.jar

La siguiente instrucción para ejecutar la compilación puede estar de-finida en un archivo compileData.bat residente en el directorio /tuto-rial3 (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/data/TableGateway.

→˓javasrc/data/ProfesorGateway.java

Nota: La versión del JDK debe ser superior a 6.0

La capa de lógica del dominio

Para implementar la capa de lógica del dominio se utilizará la técnicade módulo de tabla. En este caso el módulo agrupa toda la lógica deldominio, pero no se encarga del acceso a datos. Para acceder a losdatos se utiliza la pasarela a tabla de datos mostrada anteriormente.

La única clase necesaria sería la llamada ProfesorModule.java y resi-dirá en el directorio /tutorial3/src/domain/.

40 Capítulo 1. Contenidos

Desarrollo con Java, Versión

package domain;

import data.TableGateway;import data.ProfesorGateway;

import java.util.Map;import java.util.List;import java.io.IOException;import javax.servlet.ServletException;

public class ProfesorModule {

private ProfesorGateway gateway;

public void setGateway(TableGateway gateway) {this.gateway = (ProfesorGateway)gateway;

}

public void actualizar(int id, String cedula,→˓String nombre,

String titulo, String area, String telefono)→˓throws Exception {

if (id <= 0)throw new Exception("Identificador de

→˓profesor incorrecto");if (titulo.toLowerCase().equals("bachiller") ||

titulo.toLowerCase().equals("licenciado")→˓||

titulo.toLowerCase().equals("master") ||titulo.toLowerCase().equals("doctor"))

gateway.update(id,cedula,nombre,titulo,area,→˓telefono);

elsethrow new Exception("Error en título de

→˓profesor");}

public Map<String,Object> buscar(int id) throws→˓Exception {

if (id <= 0)

1.3. Módulo de Tabla 41

Desarrollo con Java, Versión

throw new Exception("Identificador de→˓profesor incorrecto");

Map<String,Object> prof = gateway.find(id+"");return prof;

}

public List<Map<String,Object>> listado() throws→˓Exception {

List<Map<String,Object>> profs = gateway.→˓findAll();

return profs;}

}

Compilando la capa de dominio

Para compilar la clase del dominio es necesario contar con las libreríasdel framework Spring 3 (como se indicó antes). La siguiente instruc-ción para ejecutar la compilación puede estar definida en un archivocompileDomain.bat residente en el directorio /tutorial3/ (todo en unasola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/domain/

→˓ProfesorModule.java

Capa de presentación

El servicio de la root ha sido implementado mediante controlado-res de página, en donde cada página se implementa como un con-trolador individual. La clase general para definir los controladoresse llama PageController.java y debe residir en el directorio /tuto-rial3/src/display/.

42 Capítulo 1. Contenidos

Desarrollo con Java, Versión

package display;

import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

import org.springframework.web.context.*;import org.springframework.web.context.support.*;

public class PageController extends HttpServlet {

protected WebApplicationContext context;

public void init(ServletConfig config) throws→˓ServletException {

super.init(config);context =

WebApplicationContextUtils.→˓getWebApplicationContext(getServletContext());}

protected void forward(String target,→˓HttpServletRequest request,

HttpServletResponse response)throws ServletException, IOException {RequestDispatcher dispatcher =

context.getServletContext().→˓getRequestDispatcher(target);

dispatcher.forward(request,response);}

}

El controlador de listado de profesores

El primer controlador de página es el que permite mostrar el listadode profesores. Este archivo se llama ListaProfesores.java y reside enel mismo directorio /tutorial3/src/display/.

1.3. Módulo de Tabla 43

Desarrollo con Java, Versión

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorModule;

public class ListaProfesores extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorModule module =

(ProfesorModule) context.getBean(→˓"profesorModule");

try {List data = module.listado();request.setAttribute("profesores",data);forward("/listaProfesores.jsp",request,

→˓response);} catch (Exception e) {

request.setAttribute("mensaje",e.→˓getMessage());

forward("/paginaError.jsp",request,response);}

}}

La plantilla JSP

Adicionalmente se utilizará, con en el tutorial anterior, una plantillaJSP para realizar el formateo de página en código HTML. El archivolistaProfesores.jsp se encarga de esta tarea y residirá en el directorio/tutorial3/root/.

44 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<%@ page import="java.util.*" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css"><meta http-equiv="Content-Type" content="text/

→˓html;charset=UTF-8" />

</head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2><% List profs = (List)request.getAttribute(

→˓"profesores"); %><table><thead><tr><th>Nombre</th><th>T&iacute;tulo</th><th>

→˓Area</th><th>Acciones</th></tr>

</thead><tbody><% for(int i = 0, n = profs.size(); i < n;

→˓i++) {Map prof = (Map) profs.get(i); %><tr><td><%= prof.get("nombre") %></td><td><%= prof.get("titulo") %></td><td><%= prof.get("area") %></td><td><a href='/detalleProfesor?id=<%= prof.

→˓get("id") %>'><input type="submit" value="Detalle"/

→˓></a><a href='/eliminarProfesor?id=<%= prof.

→˓get("id") %>'><input type="submit" value="Eliminar

→˓"/></a></td></tr><% } %>

</tbody><tfoot>

<tr><td><a href='/agregarProfesor'><input type="submit" name="action" value=

→˓"Agregar"/></a>

1.3. Módulo de Tabla 45

Desarrollo con Java, Versión

</td><td></td><td></td><td></td></tr></tfoot>

</table></html>

Nótese que la tabla generada cuenta con enlaces que invocarán la ru-tina que presenta el detalle del profesor (que se describe a continua-ción).

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código y y reside en el directorio /tutorial3/root/.:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

46 Capítulo 1. Contenidos

Desarrollo con Java, Versión

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

El controlador de detalle de profesor

El controlador de detalle de profesor presentará otra tabla HTMLcon la información detallada del profesor. Este controlador es lla-mado DetalleProfesor.java y se ubica en el mismo directorio /tuto-rial3/src/display/. Es importante observar la utilización del id del pro-fesor para realizar la consulta al módula de tabla.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorModule;

public class DetalleProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

1.3. Módulo de Tabla 47

Desarrollo con Java, Versión

throws ServletException, IOException {ProfesorModule module =

(ProfesorModule) context.getBean(→˓"profesorModule");

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);Map prof = module.buscar(idProf);request.setAttribute("profesor",prof);forward("/detalleProfesor.jsp",request,

→˓response);} catch (Exception e) {

request.setAttribute("mensaje",e.→˓getMessage());

forward("/paginaError.jsp",request,response);}

}}

Plantilla JSP

La plantilla JSP que genera el código HTML del detalle del profesor,se presenta a continuación. El código de la plantilla se define en un ar-chivo llamado detalleProfesor.jsp que reside también en el directorio/tutorial3/root/.

<html><head><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8"/><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><% Map prof = (Map)request.getAttribute("profesor

→˓"); %><form name="ActualizarProfesor" action="/

→˓actualizarProfesor" method="get">

48 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<input type="hidden" name="id" value="<%= prof.→˓get("id") %>"/><table style="width:400px;"><thead>

<tr><th></th><th></th></tr></thead><tbody><tr><td>Nombre:</td><td><input type="text"

→˓name="nombre"value="<%= prof.get("nombre") %>"/></td></

→˓tr><tr><td>C&eacute;dula:</td><td><input type=

→˓"text" name="cedula"value="<%= prof.get("cedula") %>"/></td></

→˓tr><tr><td>T&iacute;tulo:</td><td><input type=

→˓"text" name="titulo"value="<%= prof.get("titulo") %>"/></td></

→˓tr><tr><td>Area:</td><td><input type="text" name=

→˓"area"value="<%= prof.get("area") %>"/></td></tr>

<tr><td>Tel&eacute;fono:</td><td><input type=→˓"text" name="telefono"

value="<%= prof.get("telefono") %>"/></td>→˓</tr>

</tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr>

</tfoot></table></form>

</html>

1.3. Módulo de Tabla 49

Desarrollo con Java, Versión

El controlador para actualizar información

Se presenta también el controlador de página que permite actuali-zar los datos de un profesor. La lógica de este controlador se ubicaen el archivo ActualizarProfesor.java y reside en el directorio /tuto-rial3/src/display/.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorModule;

public class ActualizarProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorModule module =

(ProfesorModule) context.getBean(→˓"profesorModule");

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);String cedula = request.getParameter("cedula

→˓");String nombre = request.getParameter("nombre

→˓");String titulo = request.getParameter("titulo

→˓");String area = request.getParameter("area");String telefono = request.getParameter(

→˓"telefono");module.actualizar(idProf,cedula,nombre,

→˓titulo,area,telefono);response.sendRedirect("listaProfesores");

50 Capítulo 1. Contenidos

Desarrollo con Java, Versión

} catch (Exception e) {request.setAttribute("mensaje",e.

→˓getMessage());forward("/paginaError.jsp",request,response);

}}

}

Compilando la capa de presentación

Para compilar la capa de presentación es necesario contar con las li-brerías del framework Spring 3 (como se indicó antes) y con la libreríaservlet-api.jar ubicadas en el directorio /tutorial3/root/WEB-INF/lib/.La siguiente instrucción para ejecutar la compilación puede estar de-finida en un archivo compileDisplay.bat residente en el directorio /tu-torial3/ (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/display/

→˓PageController.javasrc/display/ListaProfesores.java src/display/

→˓ActualizarProfesor.javasrc/display/DetalleProfesor.java

Configuración del contexto

El framework Spring permite crear archivos xml que definen la con-figuración del contexto de ejecución de la aplicación. El archivo deconfiguración llamado context.xml se deberá ubicar en el directorio/tutorial3/root/WEB-INF/ y contendrá la siguiente información.

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-→˓instance"

1.3. Módulo de Tabla 51

Desarrollo con Java, Versión

xmlns:context="http://www.springframework.org/→˓schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/

→˓beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/

→˓contexthttp://www.springframework.org/schema/

→˓context/spring-context-3.0.xsd"><bean id="profesorGateway" class="data.

→˓ProfesorGateway"><property name="dataSource" ref="dataSource

→˓"/></bean><bean id="profesorModule" class="domain.

→˓ProfesorModule"><property name="gateway" ref=

→˓"profesorGateway"/></bean><bean id="dataSource" class="org.apache.

→˓commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="$

→˓{jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.

→˓username}"/><property name="password" value="${jdbc.

→˓password}"/></bean><context:property-placeholder location="WEB-

→˓INF/jdbc.properties"/></beans>

Los aspectos importantes que se pueden observar en este archivo sonla declaración de una instancia (singleton) al constructor de pasarelasy la declaración de la fuente de datos JDBC.

Precisamente para configurar la fuente de datos se utilizará un archivo

52 Capítulo 1. Contenidos

Desarrollo con Java, Versión

de propiedades llamado jdbc.properties y que residirá en el directorio/tutorial3/root/WEB-INF. Su contenido es simplemente el siguiente:

jdbc.driverClassName=org.sqlite.JDBCjdbc.url=jdbc:sqlite:database/universidad.dbjdbc.username=sajdbc.password=root

Sin embargo, note que una base de datos SQLite no requiere indicarel usuario y su clave.

Configuración del servidor

El servidor de servlets requiere del archivo de configuración de laaplicación para conocer en donde se ubica la clase a ejecutar. Ade-más este archivo permite indicar la ubicación y nombre del archivode contexto. Estos archivos de configuración del servlet siempre sellaman web.xml y deben residir en el directorio /tutorial3/root/WEB-INF/. Para este caso su contenido sería el siguiente:

<?xml version="1.0" encoding="ISO-8859-1"?><web-app 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"

version="2.4"><display-name>Sistema Universitario</display-name><description>Ejemplo de Módulo de Tabla</→˓description><context-param>

<param-name>contextConfigLocation</param-name><param-value>/WEB-INF/context.xml</param-value>

</context-param><listener>

<listener-class>org.springframework.web.context.

→˓ContextLoaderListener

1.3. Módulo de Tabla 53

Desarrollo con Java, Versión

</listener-class></listener><servlet><servlet-name>ActualizarProfesor</servlet-name><servlet-class>display.ActualizarProfesor</

→˓servlet-class></servlet><servlet><servlet-name>DetalleProfesor</servlet-name><servlet-class>display.DetalleProfesor</servlet-

→˓class></servlet><servlet><servlet-name>ListaProfesores</servlet-name><servlet-class>display.ListaProfesores</servlet-

→˓class></servlet><servlet-mapping><servlet-name>ActualizarProfesor</servlet-name><url-pattern>/actualizarProfesor</url-pattern>

</servlet-mapping><servlet-mapping><servlet-name>DetalleProfesor</servlet-name><url-pattern>/detalleProfesor</url-pattern>

</servlet-mapping><servlet-mapping><servlet-name>ListaProfesores</servlet-name><url-pattern>/listaProfesores</url-pattern>

</servlet-mapping></web-app>

Ejecución del tutorial

Este ejemplo se puede ejecutar bajo cualquier contenedor de Servlet.Por ejemplo, para realizar la ejecución de pruebas se puede utilizarun producto como el Winstone Servlet Container que permite ejecu-tar servlets de forma muy sencilla. Se debe descargar el programawinstone-0.9.10.jar y copiarlo en el directorio /tutorial3/. Sin em-

54 Capítulo 1. Contenidos

Desarrollo con Java, Versión

bargo, para lograr que Winstone ejecute plantillas JSP es necesariodescargar algunas librerías adicionales que deben ser copiadas en eldirectorio /tutorial3/lib:

el-api-6.0.18.jar

jasper-6.0.18.jar

jasper-el-6.0.18.jar

jasper-jdt-6.0.18.jar

jsp-api-6.0.18.jar

jstl-api-1.2.jar

jstl-impl-1.2.jar

jtds-1.2.4.jar

juli-6.0.18.jar

servlet-api-2.5.jar

servlet-api.jar

urlrewrite-3.2.0.jar

Para ejecutar el servidor de servlets se puede crear un archivo de ins-trucciones, llamado run.bat, similar al siguiente en el directorio /tuto-rial3/ :

java -jar winstone-0.9.10.jar --httpPort=8089 --→˓commonLibFolder=lib--useJasper=true --webroot=root

Luego se puede acceder a la aplicación desde cualquier visualizadorweb y apuntando a la dirección http://localhost:8089/listaProfesores

Modelo del Dominio

A continuación se presenta el ejemplo de la aplicación Web de unSistema Universitario pero en este caso utilizando un modelo del Do-

1.4. Modelo del Dominio 55

Desarrollo con Java, Versión

minio. Específicamente, en este ejemplo se combinarán otros patronesdescritos por Fowler: modelo del dominio para la lógica del dominio,y controlador de página para la capa de presentación.

La capa de lógica del dominio

Para implementar la capa de lógica del dominio se utilizará la técnicade modelo del dominio. En este caso el modelo agrupa toda la lógicadel dominio, pero no se encarga del acceso a datos.

La primer clase necesaria consiste en la entidad profesor Profesor.javay residirá en el directorio /tutorial4/src/domain/. Esta clase es la quecontendría la lógica del dominio.

package domain;

public class Profesor {private int id;private String cedula;private String nombre;private String titulo;private String area;private String telefono;

public Profesor () {};public void setId(int id) {this.id=id;}public void setCedula(String cedula) {this.

→˓cedula=cedula;}public void setNombre(String nombre) {this.

→˓nombre=nombre;}public void setTitulo(String titulo) throws

→˓Exception {if (titulo.toLowerCase().equals("bachiller") ||

titulo.toLowerCase().equals("licenciado")→˓||

titulo.toLowerCase().equals("master") ||titulo.toLowerCase().equals("doctor"))

this.titulo=titulo;else

56 Capítulo 1. Contenidos

Desarrollo con Java, Versión

throw new Exception("Error en título de→˓profesor");}public void setArea(String area) {this.area=area;

→˓}public void setTelefono(String telefono) {this.

→˓telefono=telefono;}

public int getId() {return id;}public String getCedula() {return cedula;}public String getNombre() {return nombre;}public String getTitulo() {return titulo;}public String getArea() {return area;}public String getTelefono() {return telefono;}

}

El repositorio de datos

Para mantener almacenados y recuperar los diferentes objetos, se uti-lizará un objeto llamado ProfesorRepository.java residente en el mis-mo directorio /tutorial4/src/domain/. Esta clase mantendrá los datosde los objetos en memoria. Por tanto no será necesario utilizar unabase de datos en este tutorial.

package domain;

import java.util.Map;import java.util.HashMap;import java.util.Collection;

public class ProfesorRepository {private Map<String,Profesor> profesores;

ProfesorRepository() {profesores = new HashMap<String,Profesor>();

}public boolean insertProfesor(Profesor prof) {if (profesores.containsKey(prof.getId()))

1.4. Modelo del Dominio 57

Desarrollo con Java, Versión

return false;else

profesores.put(prof.getId()+"",prof);return true;

}public boolean deleteProfesor(Profesor prof) {if (!profesores.containsKey(prof.getId()))

return false;else

profesores.remove(prof.getId());return true;

}public Profesor findProfesor(String id) {if (!profesores.containsKey(id))

return null;else

return profesores.get(id);}public boolean updateProfesor(Profesor prof) {if (!profesores.containsKey(prof.getId()+""))

return false;else

profesores.put(prof.getId()+"",prof);return true;

}public Collection findAllProfesor() {return profesores.values();

}public void setProfesores(Map profesores) {this.profesores = profesores;

}}

La fábrica de objetos

Generalmente cuando se elabora un modelo del dominio es impor-tante crear una clase aparte que se encargue de crear instancias deobjetos. En este caso se utilizará la clase ProfesorFactory.java y se

58 Capítulo 1. Contenidos

Desarrollo con Java, Versión

ubicará en el mismo directorio /tutorial4/src/domain/

package domain;

public class ProfesorFactory {public Profesor Create(int id,String cedula,

→˓String nombre,String titulo,String area,String

→˓telefono) {try {

Profesor prof = new Profesor();prof.setId(id);prof.setCedula(cedula);prof.setNombre(nombre);prof.setTitulo(titulo);prof.setArea(area);prof.setTelefono(telefono);return prof;

} catch (Exception e) {return null;

}}

}

Compilando la capa del dominio

Se puede realizar la compilación de estas tres clases en forma separa-da del resto del código. La siguiente instrucción para ejecutar la com-pilación puede estar definida en un archivo compileDomainLayer.batresidente en el directorio /tutorial4/ (todo en una sola línea):

javac -d root/WEB-INF/classes src/domain/Profesor.→˓javasrc/domain/ProfesorFactory.java src/domain/

→˓ProfesorRepository.java

Nota: La versión del JDK debe ser superior a 6.0

1.4. Modelo del Dominio 59

Desarrollo con Java, Versión

Capa de presentación

El servicio de la universidad ha será implementado mediante con-troladores de página, en donde cada página se implementa como uncontrolador individual. La clase general para definir los controlado-res se llama PageController.java y debe residir en el directorio /tuto-rial4/src/display/.

package display;

import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

import org.springframework.web.context.*;import org.springframework.web.context.support.*;

public class PageController extends HttpServlet {

protected WebApplicationContext context;

public void init(ServletConfig config) throws→˓ServletException {

super.init(config);context =

WebApplicationContextUtils.→˓getWebApplicationContext(getServletContext());}

protected void forward(String target,→˓HttpServletRequest request,

HttpServletResponse response)throws ServletException, IOException {RequestDispatcher dispatcher =

context.getServletContext().→˓getRequestDispatcher(target);

dispatcher.forward(request,response);}

}

60 Capítulo 1. Contenidos

Desarrollo con Java, Versión

El controlador de listado de profesores

El primer controlador de página es el que permite mostrar el listadode profesores. Este archivo se llama ListaProfesores.java y reside enel mismo directorio /tutorial4/src/display/.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorRepository;import domain.Profesor;

public class ListaProfesores extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

try {Collection lista = profesores.

→˓findAllProfesor();List data = new ArrayList();Iterator itr = lista.iterator();while (itr.hasNext()) {

Profesor prof = (Profesor)itr.→˓next();

ProfesorDTO dto =→˓ProfesorAssembler.Create(prof);

data.add(dto);}

request.setAttribute("profesores",data);forward("/listaProfesores.jsp",request,

→˓response);

1.4. Modelo del Dominio 61

Desarrollo con Java, Versión

} catch (Exception e) {request.setAttribute("mensaje",e.

→˓getMessage());forward("/paginaError.jsp",request,

→˓response);}

}}

La plantilla JSP

Adicionalmente se utilizará, con en el tutorial anterior, una plantillaJSP para realizar el formateo de página en código HTML. El archivolistaProfesores.jsp se encarga de esta tarea y residirá en el directorio/tutorial4/root/.

<%@ page import="java.util.*" %><%@ page import="display.*" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css"><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8" /></head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2><% List profs = (List)request.getAttribute(

→˓"profesores"); %><table><thead><tr><th>Nombre</th><th>T&iacute;tulo</th><th>

→˓Area</th><th>Acciones</th></tr></thead><tbody><% for(int i = 0, n = profs.size(); i < n;

→˓i++) {ProfesorDTO prof = (ProfesorDTO) profs.

→˓get(i); %>

62 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<tr><td><%= prof.nombre %></td><td><%= prof.titulo %></td><td><%= prof.area %></td><td><a href='/detalleProfesor?id=<%= prof.

→˓id %>'><input type="submit" value="Detalle"/

→˓></a><a href='/eliminarProfesor?id=<%= prof.

→˓id %>'><input type="submit" value="Eliminar

→˓"/></a></td></tr><% } %>

</tbody><tfoot>

<tr><td><a href='/agregarProfesor'><input type="submit" name="action" value=

→˓"Agregar"/></a></td><td></td><td></td><td></td></tr>

</tfoot></table>

</html>

Nótese que la tabla generada cuenta con enlaces que invocarán la ru-tina que presenta el detalle del profesor (que se describe a continua-ción).

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código y y reside en el directorio /tutorial4/root/.:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

1.4. Modelo del Dominio 63

Desarrollo con Java, Versión

}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

El controlador de detalle de profesor

El controlador de detalle de profesor presentará otra tabla HTMLcon la información detallada del profesor. Este controlador es lla-mado DetalleProfesor.java y se ubica en el mismo directorio /tuto-

64 Capítulo 1. Contenidos

Desarrollo con Java, Versión

rial4/src/display. Es importante observar la utilización del id del pro-fesor para realizar la consulta al módula de tabla.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorRepository;import domain.Profesor;

public class DetalleProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);Profesor prof = profesores.

→˓findProfesor(idProf+"");ProfesorDTO dto = ProfesorAssembler.

→˓Create(prof);request.setAttribute("profesor",dto);forward("/detalleProfesor.jsp",request,

→˓response);} catch (Exception e) {

request.setAttribute("mensaje",e.→˓getMessage());

forward("/paginaError.jsp",request,→˓response);

}}

}

1.4. Modelo del Dominio 65

Desarrollo con Java, Versión

Plantilla JSP

La plantilla JSP que genera el código HTML del detalle del profesor,se presenta a continuación. El código de la plantilla se define en un ar-chivo llamado detalleProfesor.jsp que reside también en el directorio/tutorial4/root/.

<%@ page import="java.util.Map" %><%@ page import="display.*" %><html>

<head><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8"/><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><% ProfesorDTO prof = (ProfesorDTO)request.

→˓getAttribute("profesor"); %><form name="ActualizarProfesor" action="/

→˓actualizarProfesor" method="get"><input type="hidden" name="id" value="<%= prof.

→˓id %>"/><table><thead>

<tr><th></th><th></th></tr></thead><tbody><tr><td>Nombre:</td><td><input type="text"

→˓name="nombre"value="<%= prof.nombre %>"/></td></tr>

<tr><td>C&eacute;dula:</td><td><input type=→˓"text" name="cedula"

value="<%= prof.cedula %>"/></td></tr><tr><td>T&iacute;tulo:</td><td><input type=

→˓"text" name="titulo"value="<%= prof.titulo %>"/></td></tr>

<tr><td>Area:</td><td><input type="text" name=→˓"area"

66 Capítulo 1. Contenidos

Desarrollo con Java, Versión

value="<%= prof.area %>"/></td></tr><tr><td>Tel&eacute;fono:</td><td><input type=

→˓"text" name="telefono"value="<%= prof.telefono %>"/></td></tr>

</tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr></tfoot>

</table></form>

</html>

El controlador para actualizar información

Se presenta también el controlador de página que permite actuali-zar los datos de un profesor. La lógica de este controlador se ubicaen el archivo ActualizarProfesor.java y reside en el directorio /tuto-rial4/src/display/.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

import domain.ProfesorRepository;import domain.Profesor;

public class ActualizarProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

1.4. Modelo del Dominio 67

Desarrollo con Java, Versión

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);String cedula = request.getParameter(

→˓"cedula");String nombre = request.getParameter(

→˓"nombre");String titulo = request.getParameter(

→˓"titulo");String area = request.getParameter(

→˓"area");String telefono = request.getParameter(

→˓"telefono");Profesor prof = profesores.

→˓findProfesor(idProf+"");try {

if (cedula!=null) prof.→˓setCedula(cedula);

if (nombre!=null) prof.→˓setNombre(nombre);

if (titulo!=null) prof.→˓setTitulo(titulo);

if (area!=null) prof.setArea(area);if (telefono!=null) prof.

→˓setTelefono(telefono);} catch (Exception e) {}

response.sendRedirect("listaProfesores");} catch (Exception e) {

request.setAttribute("mensaje",e.→˓getMessage());

forward("/paginaError.jsp",request,→˓response);

}}

}

68 Capítulo 1. Contenidos

Desarrollo con Java, Versión

El DTO de profesor

En esta implementación se utiliza una clase tipo DTO (Data TransferObject) que facilite el paso de información hacia las vistas de datos.Para ello se utiliza la clase ProfesorDTO.java residente en el directo-rio /tutorial4/src/display/.

package display;

public class ProfesorDTO {public int id;public String cedula;public String nombre;public String titulo;public String area;public String telefono;

}

El ensamblador del DTO

Adicionalmente es necesario contar con una clase que realice el en-samblaje del DTO a partir de la entidad de profesor. Aquí se utiliza laclase ProfesorAssembler.java residente en el mismo directorio /tuto-rial4/src/display/.

package display;

import domain.Profesor;

public class ProfesorAssembler {public static ProfesorDTO Create(Profesor prof) {ProfesorDTO dto = new ProfesorDTO();dto.id = prof.getId();dto.cedula = prof.getCedula();dto.nombre = prof.getNombre();dto.titulo = prof.getTitulo();dto.area = prof.getArea();dto.telefono = prof.getTelefono();

1.4. Modelo del Dominio 69

Desarrollo con Java, Versión

return dto;}

}

Compilando la capa de presentación

Para compilar la capa de presentación es necesario contar con las li-brerías del framework Spring 3 (como se indicó antes) y con la libre-ría *servlet-api.jar** ubicadas en el directorio /tutorial4/root/WEB-INF/lib/.

Específicamente las librerías necesarias son las siguientes:

servlet-api.jar

spring-asm-3.2.0.M1.jar

spring-beans-3.2.0.M1.jar

spring-context-3.2.0.M1.jar

spring-core-3.2.0.M1.jar

spring-expression-3.2.0.M1.jar

spring-jdbc-3.2.0.M1.jar

spring-tx.3.2.0.M1.jar

spring-web-3.2.0.M1.jar

La siguiente instrucción para ejecutar la compilación puede estar defi-nida en un archivo compileDisplayLayer.bat residente en el directorio/tutorial4/ (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/display/

→˓PageController.javasrc/display/ActualizarProfesor.java src/display/

→˓DetalleProfesor.java

70 Capítulo 1. Contenidos

Desarrollo con Java, Versión

src/display/ListaProfesores.java src/display/→˓ProfesorAssembler.javasrc/display/ProfesorDTO.java

Configuración del contexto

El framework Spring permite crear archivos xml que definen la con-figuración del contexto de ejecución de la aplicación. El archivo deconfiguración llamado context.xml se deberá ubicar en el directorio/tutorial4/root/WEB-INF/ y contendrá la siguiente información.

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-

→˓instance"xmlns:context="http://www.springframework.org/

→˓schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/

→˓spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/

→˓spring-context-3.0.xsd"><bean id="profesorRepository" class="domain.

→˓ProfesorRepository"><property name="profesores">

<map><entry><key><value>1</value></key><ref bean="P001" />

</entry><entry><key><value>2</value></key><ref bean="P002" />

</entry><entry>

1.4. Modelo del Dominio 71

Desarrollo con Java, Versión

<key><value>3</value></key><ref bean="P003" />

</entry></map>

</property></bean><bean id="P001" class="domain.Profesor">

<property name="id" value="1"/><property name="cedula" value="101110111"/><property name="nombre" value="Carlos Perez"/><property name="titulo" value="Licenciado"/><property name="area" value="Administracion"/><property name="telefono" value="3456-7890"/>

</bean><bean id="P002" class="domain.Profesor">

<property name="id" value="2"/><property name="cedula" value="202220222"/><property name="nombre" value="Luis Torres"/><property name="titulo" value="Master"/><property name="area" value="Economia"/><property name="telefono" value="6677-3456"/>

</bean><bean id="P003" class="domain.Profesor">

<property name="id" value="3"/><property name="cedula" value="303330333"/><property name="nombre" value="Juan Castro"/><property name="titulo" value="Licenciado"/><property name="area" value="Matematica"/><property name="telefono" value="6755-7788"/>

</bean></beans>

Los aspectos importantes que se pueden observar en este archivo sonla declaración de una instancia (singleton) del repositorio de profeso-res y la forma como se crean los objetos en forma dinámica.

72 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Configuración del servidor

El servidor de servlets requiere del archivo de configuración de laaplicación para conocer en donde se ubica la clase a ejecutar. Ade-más este archivo permite indicar la ubicación y nombre del archivode contexto. Estos archivos de configuración del servlet siempre sellaman web.xml y deben residir en el directorio /tutorial4/root/WEB-INF/. Para este caso su contenido sería el siguiente:

<?xml version="1.0" encoding="ISO-8859-1"?><web-app 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"

version="2.4"><display-name>Sistema Universitario</display-name><description>Ejemplo de Rutinas de Transaccion</→˓description><context-param>

<param-name>contextConfigLocation</param-name><param-value>/WEB-INF/context.xml</param-value>

</context-param><listener>

<listener-class>org.springframework.web.context.

→˓ContextLoaderListener</listener-class>

</listener><servlet><servlet-name>ActualizarProfesor</servlet-name><servlet-class>display.ActualizarProfesor</

→˓servlet-class></servlet><servlet><servlet-name>DetalleProfesor</servlet-name><servlet-class>display.DetalleProfesor</servlet-

→˓class>

1.4. Modelo del Dominio 73

Desarrollo con Java, Versión

</servlet><servlet><servlet-name>ListaProfesores</servlet-name><servlet-class>display.ListaProfesores</servlet-

→˓class></servlet><servlet-mapping><servlet-name>ActualizarProfesor</servlet-name><url-pattern>/root/actualizarProfesor</url-

→˓pattern></servlet-mapping><servlet-mapping><servlet-name>DetalleProfesor</servlet-name><url-pattern>/root/detalleProfesor</url-pattern>

</servlet-mapping><servlet-mapping><servlet-name>ListaProfesores</servlet-name><url-pattern>/root/listaProfesores</url-pattern>

</servlet-mapping></web-app>

Ejecución del tutorial

Este ejemplo se puede ejecutar bajo cualquier contenedor de Servlet.Por ejemplo, para realizar la ejecución de pruebas se puede utilizarun producto como el Winstone Servlet Container que permite ejecu-tar servlets de forma muy sencilla. Se debe descargar el programawinstone-0.9.10.jar y copiarlo en el directorio /tutorial4/. Sin em-bargo, para lograr que Winstone ejecute plantillas JSP es necesariodescargar algunas librerías adicionales que deben ser copiadas en eldirectorio /tutorial4/lib:

el-api-6.0.18.jar

jasper-6.0.18.jar

jasper-el-6.0.18.jar

jasper-jdt-6.0.18.jar

74 Capítulo 1. Contenidos

Desarrollo con Java, Versión

jsp-api-6.0.18.jar

jstl-api-1.2.jar

jstl-impl-1.2.jar

jtds-1.2.4.jar

juli-6.0.18.jar

servlet-api-2.5.jar

servlet-api.jar

Para ejecutar el servidor de servlets se puede crear un archivo de ins-trucciones, llamado run.bat, similar al siguiente en el directorio /tuto-rial4/ (todo en una sola línea):

java -jar winstone-0.9.10.jar --httpPort=8089 --→˓commonLibFolder=lib--useJasper=true --webroot=root

Luego se puede acceder a la aplicación desde cualquier visualizadorweb y apuntando a la dirección http://localhost:8089/listaProfesores

Mapeo objeto/relacional

Este tutorial muestra la forma de desarrollar una aplicación que utilicemodelo del dominio como patrón de diseño de la capa de dominio, ymapeador objeto/relacional para la capa de acceso a datos.

Capa de lógica del dominio

Para implementar la capa de lógica del dominio se utilizará la técnicade modelo del dominio tal como el tutorial anterior. En este casoel modelo agrupa toda la lógica del dominio, pero no se encarga delacceso a datos.

1.5. Mapeo objeto/relacional 75

Desarrollo con Java, Versión

La primer clase necesaria consiste en la entidad profesor Profe-sor.java y residirá en el directorio /tutorial5/src/domain/. Esta clasees la que contendría la lógica del dominio.

package domain;

public class Profesor {private int id;private String cedula;private String nombre;private String titulo;private String area;private String telefono;

public Profesor () {};public void setId(int id) {this.id=id;}public void setCedula(String cedula) {this.

→˓cedula=cedula;}public void setNombre(String nombre) {this.

→˓nombre=nombre;}public void setTitulo(String titulo) throws

→˓Exception {if (titulo.toLowerCase().equals("bachiller") ||

titulo.toLowerCase().equals("licenciado")→˓||

titulo.toLowerCase().equals("master") ||titulo.toLowerCase().equals("doctor"))

this.titulo=titulo;else

throw new Exception("Error en título de→˓profesor");}public void setArea(String area) {this.area=area;

→˓}public void setTelefono(String telefono) {this.

→˓telefono=telefono;}public int getId() {return id;}public String getCedula() {return cedula;}public String getNombre() {return nombre;}public String getTitulo() {return titulo;}public String getArea() {return area;}

76 Capítulo 1. Contenidos

Desarrollo con Java, Versión

public String getTelefono() {return telefono;}}

El repositorio de datos

Para mantener almacenados y recuperar los diferentes objetos, se uti-liza el objeto llamado ProfesorRepository.java residente en el mis-mo directorio /tutorial5/src/domain/. Sin embargo, este tipo de ob-jeto solamente es una interfase Java como se puede observar a conti-nuación:

package domain;import java.util.Map;import java.util.HashMap;import java.util.Collection;

public interface ProfesorRepository {public boolean insertProfesor(Profesor prof);public boolean deleteProfesor(Profesor prof);public Profesor findProfesor(int id);public boolean updateProfesor(Profesor prof);public Collection findAllProfesor();

}

La fábrica de objetos

Generalmente cuando se elabora un modelo del dominio es impor-tante crear una clase aparte que se encargue de crear instancias deobjetos. En este caso se utilizará la clase ProfesorFactory.java y seubicará en el mismo directorio /tutorial5/src/domain/

package domain;

public class ProfesorFactory {public Profesor Create(int id,String cedula,

→˓String nombre,

1.5. Mapeo objeto/relacional 77

Desarrollo con Java, Versión

String titulo,String area,String→˓telefono) {

try {Profesor prof = new Profesor();prof.setId(id);prof.setCedula(cedula);prof.setNombre(nombre);prof.setTitulo(titulo);prof.setArea(area);prof.setTelefono(telefono);return prof;

} catch (Exception e) {return null;

}}

}

Compilando la capa del dominio

Se puede realizar la compilación de estas tres clases en forma sepa-rada del resto del código. La siguiente instrucción para ejecutar lacompilación puede estar definida en un archivo compileDomainLa-yer.bat residente en el directorio /tutorial5/ (todo en una sola línea):

javac -d root/WEB-INF/classes src/domain/Profesor.→˓javasrc/domain/ProfesorFactory.java src/domain/

→˓ProfesorRepository.java

Nota: La versión del JDK debe ser superior a 6.0

Capa de presentación

El servicio de la universidad será implementado mediante controla-dores de página (tal como se hizo en el tutorial anterior), en dondecada página se implementa como un controlador individual. Igual que

78 Capítulo 1. Contenidos

Desarrollo con Java, Versión

antes, la clase general para definir los controladores se llama Page-Controller.java y debe residir en el directorio /tutorial5/src/display/.

package display;

import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

import org.springframework.web.context.*;import org.springframework.web.context.support.*;

public class PageController extends HttpServlet {

protected WebApplicationContext context;

public void init(ServletConfig config) throws→˓ServletException {

super.init(config);context =WebApplicationContextUtils.

→˓getWebApplicationContext(getServletContext());

}

protected void forward(String target,→˓HttpServletRequest request,

HttpServletResponse response)throws ServletException, IOException {RequestDispatcher dispatcher =

context.getServletContext().→˓getRequestDispatcher(target);

dispatcher.forward(request,response);}

}

1.5. Mapeo objeto/relacional 79

Desarrollo con Java, Versión

El controlador de listado de profesores

El primer controlador de página es el que permite mostrar el listadode profesores. Este archivo se llama ListaProfesores.java y reside enel mismo directorio /tutorial5/src/display/.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;import domain.ProfesorRepository;import domain.Profesor;import util.ProfesorDTO;import util.ProfesorAssembler;

public class ListaProfesores extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

try {Collection lista = profesores.

→˓findAllProfesor();List data = new ArrayList();Iterator itr = lista.iterator();while (itr.hasNext()) {

Profesor prof = (Profesor)itr.next();ProfesorDTO dto = ProfesorAssembler.

→˓CreateDTO(prof);data.add(dto);

}request.setAttribute("profesores",data);forward("/listaProfesores.jsp",request,

→˓response);

80 Capítulo 1. Contenidos

Desarrollo con Java, Versión

} catch (Exception e) {request.setAttribute("mensaje",e.

→˓getMessage());forward("/paginaError.jsp",request,

→˓response);}

}}

La plantilla JSP

Adicionalmente se utilizará, con en el tutorial anterior, una plantillaJSP para realizar el formateo de página en código HTML. El archivolistaProfesores.jsp se encarga de esta tarea y residirá en el directorio/tutorial5/root/.

<%@ page import="java.util.*" %><%@ page import="util.*" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2><% List profs = (List)request.getAttribute(

→˓"profesores"); %><table>

<thead><tr><th>Nombre</th><th>T&iacute;tulo</th>

<th>Area</th><th>Acciones</th></tr></thead><tbody><% for(int i = 0, n = profs.size(); i < n;

→˓i++) {ProfesorDTO prof = (ProfesorDTO) profs.

→˓get(i); %><tr><td><%= prof.getNombre() %></td>

1.5. Mapeo objeto/relacional 81

Desarrollo con Java, Versión

<td><%= prof.getTitulo() %></td><td><%= prof.getArea() %></td><td><a href='/detalleProfesor?id=<%= prof.

→˓getId() %>'><input type="submit" value="Detalle"/

→˓></a><a href='/eliminarProfesor?id=<%= prof.

→˓getId() %>'><input type="submit" value="Eliminar

→˓"/></a></td></tr><% } %>

</tbody><tfoot>

<tr><td><a href='/agregarProfesor'><input type="submit" name="action" value=

→˓"Agregar"/></a></td><td></td><td></td><td></td></tr>

</tfoot></table>

</html>

Nótese que la tabla generada cuenta con enlaces que invocarán la ru-tina que presenta el detalle del profesor (que se describe a continua-ción).

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código y y reside en el directorio /tutorial5/root/.:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

}

82 Capítulo 1. Contenidos

Desarrollo con Java, Versión

table {font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

El controlador de detalle de profesor

El controlador de detalle de profesor presentará otra tabla HTMLcon la información detallada del profesor. Este controlador es lla-mado DetalleProfesor.java y se ubica en el mismo directorio /tu-torial5/src/display/. Es importante observar la utilización del id del

1.5. Mapeo objeto/relacional 83

Desarrollo con Java, Versión

profesor para realizar la consulta al módulo de tabla.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;import domain.ProfesorRepository;import domain.Profesor;import util.ProfesorDTO;import util.ProfesorAssembler;

public class DetalleProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);Profesor prof = profesores.

→˓findProfesor(idProf);ProfesorDTO dto = ProfesorAssembler.

→˓CreateDTO(prof);request.setAttribute("profesor",dto);forward("/detalleProfesor.jsp",request,

→˓response);} catch (Exception e) {

request.setAttribute("mensaje",e.→˓getMessage());

forward("/paginaError.jsp",request,response);}

}}

84 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Plantilla JSP

La plantilla JSP que genera el código HTML del detalle del profesor,se presenta a continuación. El código de la plantilla se define en un ar-chivo llamado detalleProfesor.jsp que reside también en el directorio/tutorial5/root/.

<%@ page import="java.util.Map" %><%@ page import="util.*" %><html>

<head><meta http-equiv="Content-Type" content="text/

→˓html;charset=UTF-8"/>

<title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><% ProfesorDTO prof =(ProfesorDTO)request.getAttribute("profesor");

→˓%><form name="ActualizarProfesor"

action="/actualizarProfesor" method="get"><input type="hidden" name="id" value="<%= prof.

→˓getId() %>"/><table><thead>

<tr><th></th><th></th></tr></thead><tbody><tr><td>Nombre:</td><td><input type="text"

→˓name="nombre"value="<%= prof.getNombre() %>"/></td>

→˓</tr><tr><td>C&eacute;dula:</td><td><input type=

→˓"text"name="cedula" value="<%= prof.

→˓getCedula() %>"/></td></tr>

1.5. Mapeo objeto/relacional 85

Desarrollo con Java, Versión

<tr><td>T&iacute;tulo:</td><td><input type=→˓"text"

name="titulo" value="<%= prof.→˓getTitulo() %>"/>

</td></tr><tr><td>Area:</td><td><input type="text"

→˓name="area"value="<%= prof.getArea() %>"/></td></

→˓tr><tr><td>Tel&eacute;fono:</td><td><input

→˓type="text"name="telefono" value="<%= prof.

→˓getTelefono() %>"/></td></tr>

</tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr>

</tfoot></table></form>

</html>

El controlador para actualizar información

Se presenta también el controlador de página que permite actualizarlos datos de un profesor. La lógica de este controlador se ubica enel archivo ActualizarProfesor.java y reside en el directorio /tuto-rial5/src/display/.

package display;import java.util.*;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import org.springframework.web.context.*;

86 Capítulo 1. Contenidos

Desarrollo con Java, Versión

import domain.ProfesorRepository;import domain.Profesor;

import util.ProfesorDTO;import util.ProfesorAssembler;

public class ActualizarProfesor extends→˓PageController {

public void doGet(HttpServletRequest request,HttpServletResponse response)

throws ServletException, IOException {ProfesorRepository profesores =

(ProfesorRepository) context.getBean(→˓"profesorRepository");

try {String id = request.getParameter("id");int idProf = Integer.parseInt(id);String cedula = request.getParameter(

→˓"cedula");String nombre = request.getParameter(

→˓"nombre");String titulo = request.getParameter(

→˓"titulo");String area = request.getParameter("area");String telefono = request.getParameter(

→˓"telefono");Profesor prof = profesores.

→˓findProfesor(idProf);try {

if (cedula!=null) prof.→˓setCedula(cedula);

if (nombre!=null) prof.→˓setNombre(nombre);

if (titulo!=null) prof.→˓setTitulo(titulo);

if (area!=null) prof.setArea(area);if (telefono!=null) prof.

→˓setTelefono(telefono);profesores.updateProfesor(prof);

1.5. Mapeo objeto/relacional 87

Desarrollo con Java, Versión

} catch (Exception e) {}response.sendRedirect("listaProfesores");

} catch (Exception e) {request.setAttribute("mensaje",e.

→˓getMessage());forward("/paginaError.jsp",request,

→˓response);}

}}

Plantilla JSP de mensaje de error

Se puede utilizar un archivo JSP adicional para desplegar los mensajesde error. En particular este archivo será llamado paginaError.jsp yresidirá en el directorio /tutorial5/root/.

<html><head><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8"/><title>Sistema Universitario</title>

</head><% String mensaje = (String)request.getAttribute(

→˓"mensaje"); %><h1>Error en operaci&oacute;n</h1><p><%= mensaje %></p>

</html>

El DTO de profesor

En esta implementación también se utiliza una clase tipo DTO (DataTransfer Object) que facilite el paso de información hacia las vistas dedatos. Para ello se utiliza la clase ProfesorDTO.java pero esta claseresidirá en el directorio /tutorial5/src/util/.

88 Capítulo 1. Contenidos

Desarrollo con Java, Versión

package util;

public class ProfesorDTO {private int id;private String cedula;private String nombre;private String titulo;private String area;private String telefono;

public int getId() {return id;}public String getCedula() {return cedula;}public String getNombre() {return nombre;}public String getTitulo() {return titulo;}public String getArea() {return area;}public String getTelefono() {return telefono;}public void setId(int id) {this.id=id;}public void setCedula(String ced) {cedula=ced;}public void setNombre(String nom) {nombre=nom;}public void setTitulo(String tit) {titulo=tit;}public void setArea(String are) {area=are;}public void setTelefono(String tel)

→˓{telefono=tel;}}

El ensamblador del DTO

Adicionalmente es necesario contar con una clase que realice el en-samblaje del DTO a partir de la entidad de profesor. Aquí se utiliza laclase ProfesorAssembler.java residente en el mismo directorio /tu-torial5/src/util/.

package util;import domain.Profesor;

public class ProfesorAssembler {public static ProfesorDTO CreateDTO(Profesor

→˓prof) {

1.5. Mapeo objeto/relacional 89

Desarrollo con Java, Versión

ProfesorDTO dto = new ProfesorDTO();dto.setId(prof.getId());dto.setCedula(prof.getCedula());dto.setNombre(prof.getNombre());dto.setTitulo(prof.getTitulo());dto.setArea(prof.getArea());dto.setTelefono(prof.getTelefono());return dto;

}public static void Update(Profesor prof,

→˓ProfesorDTO dto) {try {

prof.setId(dto.getId());prof.setCedula(dto.getCedula());prof.setNombre(dto.getNombre());prof.setTitulo(dto.getTitulo());prof.setArea(dto.getArea());prof.setTelefono(dto.getTelefono());

} catch (Exception e) {}

}}

Compilando la capa de presentación

Para compilar la capa de presentación es necesario contar con las li-brerías del framework Spring 3 (como se indicó antes) y con la li-brería servlet-api.jar ubicadas en el directorio /tutorial5/root/WEB-INF/lib/.

Específicamente las librerías necesarias son las siguientes:

servlet-api.jar

spring-asm-3.2.0.M1.jar

spring-beans-3.2.0.M1.jar

spring-context-3.2.0.M1.jar

spring-core-3.2.0.M1.jar

90 Capítulo 1. Contenidos

Desarrollo con Java, Versión

spring-expression-3.2.0.M1.jar

spring-jdbc-3.2.0.M1.jar

spring-orm-3.2.0.M1.jar

spring-tx.3.2.0.M1.jar

spring-web-3.2.0.M1.jar

La siguiente instrucción para ejecutar la compilación puede estar de-finida en un archivo compileDisplayLayer.bat residente en el direc-torio /tutorial5/ (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/display/

→˓PageController.javasrc/display/ActualizarProfesor.java src/display/

→˓DetalleProfesor.javasrc/display/ListaProfesores.java src/util/

→˓ProfesorAssembler.javasrc/util/ProfesorDTO.java

Capa de acceso a datos

Para la capa de acceso a datos se utilizará el patrón de mapeadorde datos. Para ello se requiere las librerías Spring e Hibernate. Enforma conjunta estas dos librerías facilitan el desarrollo de este tipode aplicaciones.

Un DAO (Data Access Object) debe incluir todo el código para reali-zar la conexión con la base de datos y ejecutar las instrucciones SQLde consulta y/o actualización de datos. Generalmente escribir todoeste código desde el principio resulta muy tedioso. Es por eso queSpring provee la clase HibernateDaoSupport que facilita en granmedida la escritura de clases tipo DAO.

1.5. Mapeo objeto/relacional 91

Desarrollo con Java, Versión

El DAO de profesor

Para empezar se definirá la clase ProfesorDAO.java que residirá enel directorio /src/data. Esta clase define el conjunto de operacionesque se llevan a cabo sobre la base de datos y mediante Hibernate. Elcontenido de dicho archivo sería el siguiente:

package data;import java.util.Collection;import util.ProfesorDTO;import util.ProfesorAssembler;import org.springframework.orm.hibernate3.support.→˓HibernateDaoSupport;

public class ProfesorDAO extends→˓HibernateDaoSupport {public boolean insert(ProfesorDTO profDTO) {getHibernateTemplate().saveOrUpdate(profDTO);return true;

}public boolean delete(ProfesorDTO profDTO) {getHibernateTemplate().delete(profDTO);return true;

}public ProfesorDTO findById(int id) {ProfesorDTO prof;prof = (ProfesorDTO)getHibernateTemplate().get(

ProfesorDTO.class,new Integer(id));return prof;

}public boolean update(ProfesorDTO profDTO) {getHibernateTemplate().saveOrUpdate(profDTO);return true;

}public Collection findAll() {return getHibernateTemplate().find("from

→˓ProfesorDTO");}

}

92 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Como se puede observar aquí también se utiliza el DTO del profesorpero en esta ocasión es para pasar los datos desde objetos del dominioa la capa de datos.

Repositorio basado en DAO

Ahora es necesario asociar esta clase tipo DAO con el modelo del do-minio de la capa de presentación. Este trabajo lo lleva a cabo la claseProfesorRepositoryDAOImpl.java, que es una clase equivalente ala utiliza en el modelo del dominio. Esta clase también reside en eldirectorio /src/data y su contenido sería:

package data;import java.util.Collection;import java.util.Iterator;import java.util.List;import java.util.ArrayList;import domain.ProfesorRepository;import util.ProfesorDTO;import util.ProfesorAssembler;import domain.Profesor;

public class ProfesorRepositoryDAOImplimplements ProfesorRepository {

private ProfesorDAO profDAO;ProfesorRepositoryDAOImpl(ProfesorDAO profDAO) {this.profDAO = profDAO;

}public boolean insertProfesor(Profesor prof) {ProfesorDTO profDTO = ProfesorAssembler.

→˓CreateDTO(prof);return (profDAO.insert(profDTO));

}public boolean deleteProfesor(Profesor prof) {ProfesorDTO profDTO = ProfesorAssembler.

→˓CreateDTO(prof);return (profDAO.delete(profDTO));

}public Profesor findProfesor(int id) {

1.5. Mapeo objeto/relacional 93

Desarrollo con Java, Versión

ProfesorDTO profDTO = profDAO.findById(id);if (profDTO!=null) {

Profesor prof = new Profesor();System.out.println(profDTO.getNombre());ProfesorAssembler.Update(prof,profDTO);return prof;

}return null;

}public boolean updateProfesor(Profesor prof) {ProfesorDTO profDTO = ProfesorAssembler.

→˓CreateDTO(prof);return (profDAO.update(profDTO));

}public Collection findAllProfesor() {Collection profsDTO = profDAO.findAll();List profList = new ArrayList();Iterator itr = profsDTO.iterator();while (itr.hasNext()) {

Profesor prof = new Profesor();ProfesorDTO profDTO = (ProfesorDTO)itr.next();ProfesorAssembler.Update(prof,profDTO);profList.add(prof);

}return profList;

}}

Base de datos

Se utilizará la misma base de datos SQLite del tutorial anterior pa-ra administrar los datos. Dicha base de datos debe llevar por nom-bre universidad.sqlite y debe estar ubicada en el directorio /tuto-rial5/root/database/. El código SQL utilizado para generar la tablade profesores sería el siguiente:

94 Capítulo 1. Contenidos

Desarrollo con Java, Versión

CREATE TABLE profesor (id INTEGER PRIMARY KEY,→˓cedula VARCHAR,

nombre VARCHAR, titulo VARCHAR, area VARCHAR,→˓telefono VARCHAR);INSERT INTO profesor VALUES(1,'101110111','Carlos→˓Perez','Licenciado','Administracion','3456-7890');

INSERT INTO profesor VALUES(2,'202220222','Luis→˓Torres',

'Master','Economia','6677-3456→˓');INSERT INTO profesor VALUES(3,'303330333','Juan→˓Castro','Licenciado','Matematica','6755-7788');

Para administrar una base de datos SQLite se puede utilizar alguno delos excelentes productos creados para ello, tal como SQLiteman ó elplugin para Firefox llamado SQLite Manager

Compilando la capa de datos

La compilación de la capa de datos también requiere las librerías deSpring 3.

La siguiente instrucción para ejecutar la compilación puede estar de-finida en un archivo compileDataLayer.bat residente en el directorio/tutorial5 (todo en una sola línea):

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/data/

→˓ProfesorRepositoryDAOImpl.javasrc/data/ProfesorDAO.java

Nota: La versión del JDK debe ser superior a 6.0

1.5. Mapeo objeto/relacional 95

Desarrollo con Java, Versión

Dialecto SQLite

Para que Hibernate reconozca cualquier base de datos es necesariocontar con un archivo de dialecto que le identifique a Hibernate al-gunas características importantes del motor de bases de datos. Extra-ñamente, la versión actual de Hibernate no cuenta con dicho archivode dialecto para SQLite. Sin embargo, resulta sencillo escribir dichoarchivo directamente.

A continuación se presenta el archivo SQLDialect.java, que resideen el directorio tutorial5/src/dialect, y cuyo contenido es:

package dialect;import java.sql.Types;import org.hibernate.dialect.Dialect;import org.hibernate.dialect.function.→˓StandardSQLFunction;import org.hibernate.dialect.function.→˓SQLFunctionTemplate;import org.hibernate.dialect.function.→˓VarArgsSQLFunction;import org.hibernate.type.StandardBasicTypes;

public class SQLiteDialect extends Dialect {public SQLiteDialect() {

super();registerColumnType(Types.BIT, "integer");registerColumnType(Types.TINYINT, "tinyint

→˓");registerColumnType(Types.SMALLINT,

→˓"smallint");registerColumnType(Types.INTEGER, "integer

→˓");registerColumnType(Types.BIGINT, "bigint");registerColumnType(Types.FLOAT, "float");registerColumnType(Types.REAL, "real");registerColumnType(Types.DOUBLE, "double");registerColumnType(Types.NUMERIC, "numeric

→˓");registerColumnType(Types.DECIMAL, "decimal

→˓");

96 Capítulo 1. Contenidos

Desarrollo con Java, Versión

registerColumnType(Types.CHAR, "char");registerColumnType(Types.VARCHAR, "varchar

→˓");registerColumnType(Types.LONGVARCHAR,

→˓"longvarchar");registerColumnType(Types.DATE, "date");registerColumnType(Types.TIME, "time");registerColumnType(Types.TIMESTAMP,

→˓"timestamp");registerColumnType(Types.BINARY, "blob");registerColumnType(Types.VARBINARY, "blob

→˓");registerColumnType(Types.LONGVARBINARY,

→˓"blob");// registerColumnType(Types.NULL, "null");registerColumnType(Types.BLOB, "blob");registerColumnType(Types.CLOB, "clob");registerColumnType(Types.BOOLEAN, "integer

→˓");

registerFunction("concat",new

→˓VarArgsSQLFunction(StandardBasicTypes.STRING, "","||", ""));

registerFunction("mod",new

→˓SQLFunctionTemplate(StandardBasicTypes.INTEGER,"?1 % ?2"));

registerFunction("substr",new StandardSQLFunction("substr",

StandardBasicTypes.STRING));registerFunction("substring",new StandardSQLFunction("substr",

StandardBasicTypes.STRING));}public boolean supportsIdentityColumns()

→˓{return true;}public boolean hasDataTypeInIdentityColumn()

→˓{return false;}public String getIdentityColumnString()

→˓{return "integer";}

1.5. Mapeo objeto/relacional 97

Desarrollo con Java, Versión

public String getIdentitySelectString() {return "select last_insert_rowid()";

}public boolean supportsLimit() {return true;}public String getLimitString(String query,

→˓boolean hasOffset) {return new StringBuffer(query.length() +

→˓20).append(query).append(hasOffset ? " limit ? offset ?" :

→˓" limit ?").toString();}public boolean supportsTemporaryTables()

→˓{return true;}public String getCreateTemporaryTableString() {

return "create temporary table if not→˓exists";

}public boolean dropTemporaryTableAfterUse()

→˓{return false;}public boolean

→˓supportsCurrentTimestampSelection() {return true;→˓}

public boolean→˓isCurrentTimestampSelectStringCallable() {return→˓false;}

public String→˓getCurrentTimestampSelectString() {

return "select current_timestamp";}public boolean supportsUnionAll() {return true;

→˓}public boolean hasAlterTable() {return false;}public boolean dropConstraints() {return false;

→˓}public String getAddColumnString() {

return "add column";}public String getForUpdateString() {return "";}public boolean supportsOuterJoinForUpdate()

→˓{return false;}

98 Capítulo 1. Contenidos

Desarrollo con Java, Versión

public String getDropForeignKeyString() {throw new UnsupportedOperationException(

"No drop foreign key syntax→˓supported by SQLiteDialect");

}public String

→˓getAddForeignKeyConstraintString(String→˓constraintName,

String[] foreignKey, String→˓referencedTable, String[] primaryKey,

boolean referencesPrimaryKey) {throw new UnsupportedOperationException(

"No add foreign key syntax→˓supported by SQLiteDialect");

}public String

→˓getAddPrimaryKeyConstraintString(String→˓constraintName) {

throw new UnsupportedOperationException("No add primary key syntax

→˓supported by SQLiteDialect");}public boolean

→˓supportsIfExistsBeforeTableName() {return true;}public boolean supportsCascadeDelete() {return

→˓false;}}

Compilando el dialecto

Para compilar el dialecto de SQLite se puede ejecutar el archivo com-pileDialect.bat desde el directorio tutorial5, y con el siguiente con-tenido:

javac -cp "root/WEB-INF/classes";"root/WEB-INF/lib/→˓*"-d root/WEB-INF/classes src/dialect/SQLiteDialect.→˓java

1.5. Mapeo objeto/relacional 99

Desarrollo con Java, Versión

Configuración de la aplicación

Este ejemplo se puede ejecutar bajo cualquier contenedor de Servlet.Por ejemplo, para realizar la ejecución de pruebas se puede utilizarun producto como el Winstone Servlet Container que permite eje-cutar servlets de forma muy sencilla. Se debe descargar el programawinstone-0.9.10.jar y copiarlo en el directorio /tutorial5/. Sin em-bargo (como antes), para lograr que Winstone ejecute plantillas JSPes necesario descargar algunas librerías adicionales que deben ser co-piadas en el directorio /tutorial5/lib:

el-api-6.0.18.jar

jasper-6.0.18.jar

jasper-el-6.0.18.jar

jasper-jdt-6.0.18.jar

jsp-api-6.0.18.jar

jstl-api-1.2.jar

jstl-impl-1.2.jar

jtds-1.2.4.jar

juli-6.0.18.jar

servlet-api-2.5.jar

servlet-api.jar

Adicionalmente es necesario que en el directoriotutorial5/root/WEB-INF/lib se encuentren las librerías queconforman el paquete Hibernate y todas sus dependencias quebásicamente son:

antlr.jar

asm-attrs.jar

asm.jar

c3p0-0.9.0.jar

100 Capítulo 1. Contenidos

Desarrollo con Java, Versión

cglib-2.1.3.jar

commons-collections-3.1.jar

commons-dbcp-1.4.jar

commons-logging-1.1.1.jar

commons-pool-1.6.jar

dom4j-1.6.1.jar

hibernate-jpa-2.0-api-1.0.1.Final.jar

hibernate3.jar

javassist-3.12.0.GA.jar

jta-1.1.jar

slf4j-api-1.6.1.jar

sqlite-jdbc-3.6.0.jar

Archivo de contexto

Es necesario crear un archivo de contexto en donde se realizará lacreación de una serie de objetos necesarios. Este archivo lleva pornombre context.xml y residirá en el directorio tutorial5/root/WEB-INF y su contenido sería:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-

→˓instance"xmlns:context="http://www.springframework.org/

→˓schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/

→˓spring-beans-3.0.xsdhttp://www.springframework.org/schema/context

1.5. Mapeo objeto/relacional 101

Desarrollo con Java, Versión

http://www.springframework.org/schema/context/→˓spring-context-3.0.xsd"><bean id="dataSource" class="org.apache.commons.

→˓dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="$

→˓{jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.

→˓username}"/><property name="password" value="${jdbc.

→˓password}"/></bean><bean id="sessionFactory"

class="org.springframework.orm.hibernate3.→˓LocalSessionFactoryBean">

<property name="dataSource" ref="dataSource→˓" />

<property name="configurationClass"value="org.hibernate.cfg.

→˓AnnotationConfiguration"/><property name="configLocation"><value>classpath:hibernate.cfg.xml</

→˓value></property>

</bean><bean id="transactionManager"

class="org.springframework.orm.hibernate3.→˓HibernateTransactionManager">

<property name="sessionFactory" ref=→˓"sessionFactory" /></bean><bean id="profesorDAO" class="data.ProfesorDAO"><property name="sessionFactory"><ref local=

→˓"sessionFactory"/></property></bean><bean id="profesorRepository" class="data.

→˓ProfesorRepositoryDAOImpl"><constructor-arg>

<ref bean="profesorDAO"/>

102 Capítulo 1. Contenidos

Desarrollo con Java, Versión

</constructor-arg></bean><context:property-placeholder location="WEB-INF/

→˓jdbc.properties"/></beans>

También es necesario el archivo jdbc.properties que reside en el mis-mo directorio tutorial5/root/WEB-INF y cuyo contenido es:

jdbc.driverClassName=org.sqlite.JDBCjdbc.url=jdbc:sqlite:root/database/universidad.→˓sqlitejdbc.username=sajdbc.password=root

Archivo de configuración de Hibernate

Hibernate 3 requiere de su propio archivo de configuración elcual se llamará hibernate.cfg.xml y residirá en el directorio/tutorial5/root/WEB-INF/classes y su contenido es:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//→˓EN"

"http://hibernate.sourceforge.net/hibernate-→˓configuration-3.0.dtd"><hibernate-configuration>

<session-factory><property name="show_sql">true</property><property name="format_sql">true</property><property name="dialect">dialect.

→˓SQLiteDialect</property><mapping resource="ProfesorDTO.hbm.xml"/>

</session-factory></hibernate-configuration>

1.5. Mapeo objeto/relacional 103

Desarrollo con Java, Versión

Metadatos para la clase Profesor

Hibernate 3 utiliza archivos de metadatos para establecer la relaciónentre los campos de cada tabla y los atributos de las clases. En es-te caso se utilizará un archivo llamado ProfesorDTO.hbm.xml queresidirá en el mismo directorio tutorial5/root/WEB-INF/classes ycuyo contenido sería:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/→˓Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-→˓mapping-3.0.dtd"><hibernate-mapping><class name="util.ProfesorDTO" table="profesor">

<id name="id" column="id" type="int"><generator class="native"></generator>

</id><property name="cedula" column="cedula" type=

→˓"string"></property><property name="nombre" column="nombre" type=

→˓"string"></property><property name="titulo" column="titulo" type=

→˓"string"></property><property name="area" column="area" type=

→˓"string"></property><property name="telefono" column="telefono"

→˓type="string"></property></class></hibernate-mapping>

El archivo de configuración de servlets

Por último, es necesario crear el archivo de definición de servlets pa-ra esta aplicación. Como es costumbre su nombre será web.xml, suubicación será tutorial5/root/WEB-INF:

104 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<?xml version="1.0" encoding="ISO-8859-1"?><web-app 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"

version="2.4"><display-name>Sistema Universitario</display-name><description>Ejemplo de Mapeo Relacional/Objeto/→˓description><context-param>

<param-name>contextConfigLocation</param-name><param-value>/WEB-INF/context.xml</param-value>

</context-param><listener>

<listener-class>org.springframework.web.context.

→˓ContextLoaderListener</listener-class>

</listener><servlet><servlet-name>ActualizarProfesor</servlet-name><servlet-class>display.ActualizarProfesor</

→˓servlet-class></servlet><servlet><servlet-name>DetalleProfesor</servlet-name><servlet-class>display.DetalleProfesor</servlet-

→˓class></servlet><servlet><servlet-name>ListaProfesores</servlet-name><servlet-class>display.ListaProfesores</servlet-

→˓class></servlet><servlet-mapping><servlet-name>ActualizarProfesor</servlet-name><url-pattern>/actualizarProfesor</url-pattern>

1.5. Mapeo objeto/relacional 105

Desarrollo con Java, Versión

</servlet-mapping><servlet-mapping><servlet-name>DetalleProfesor</servlet-name><url-pattern>/detalleProfesor</url-pattern>

</servlet-mapping><servlet-mapping><servlet-name>ListaProfesores</servlet-name><url-pattern>/listaProfesores</url-pattern>

</servlet-mapping></web-app>

Ejecución del Tutorial

Para ejecutar el servidor de servlets se puede crear un archivo de ins-trucciones, llamado run.bat (todo en una sola línea), similar al si-guiente en el directorio /tutorial5/:

java -jar winstone-0.9.10.jar --httpPort=8089--commonLibFolder=lib --useJasper=true --

→˓webroot=root

Luego se puede acceder a la aplicación desde cualquier visualizadorweb y apuntando a la dirección http://localhost:8089/listaProfesores

Uso de JSTL

La tecnología JavaServer Pages Standard Tag Library (JSTL) es uncomponente de Java EE. Extiende las ya conocidas JavaServer Pages(JSP) proporcionando cuatro bibliotecas de etiquetas (Tag Libraries)con utilidades ampliamente utilizadas en el desarrollo de páginas webdinámicas.

Estas bibliotecas de etiquetas extienden de la especificación de JSP(la cual a su vez extiende de la especificación de Servlet). Su APIpermite además desarrollar bibliotecas propias de etiquetas.

106 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Las bibliotecas englobadas en JSTL son:

core: iteraciones, condicionales, manipulación de URL y otrasfunciones generales.

xml: para la manipulación de XML y para XML-Transformation.

sql: para gestionar conexiones a bases de datos.

fmt: para la internacionalización y formateo de las cadenas decaracteres como cifras.

Creación de la base de datos

Para este ejemplo se utilizará nuevamente la base de datos de prueba,llamada universidad.db, utilizando SQLite. Es posible utilizar dife-rentes herramientas para crear bases de datos en este formato, entreellas se encuentra el plugin para Firefox llamado SQLite Manager, obien, la herramienta SQLiteBrowser.

Por el momento solo se utilizará una tabla con información de profe-sores de una universidad. El código SQL para crear dicha tabla seríael siguiente:

CREATE TABLE "profesor" (id INTEGER PRIMARY KEY ASC,cedula VARCHAR,nombre VARCHAR,titulo VARCHAR,area VARCHAR,telefono VARCHAR

);

Luego de crear la base de datos se agregaron algunos datos de ejemploa esta tabla. Las siguientes instrucciones SQL permiten poblar la tablaalguna información:

1.6. Uso de JSTL 107

Desarrollo con Java, Versión

INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (1,'101110111','Carlos Perez Rojas',

→˓'Licenciado','Administracion','3456-7890');

INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (2,'202220222','Luis Torres','Master',

'Economia','6677-3456');INSERT INTO profesor (id,cedula,nombre,titulo,area,→˓telefono)VALUES (3,'303330333','Juan Castro','Licenciado',

'Matematica','67455-7788');

Página de listado de profesores

La primer página consistirá del listado de todos los profesores que seencuentran en la base de datos. El código que se muestra a continua-ción (llamado listaProfesores.jsp) establece la conexión con la basede datos (utilizado JDBC), ejecuta la instrucción de consulta, recupe-ra los datos y crea una tabla HTML con la información obtenida.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"→˓prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/sql"→˓prefix="sql" %>

<sql:setDataSource dataSource="universidad"></→˓sql:setDataSource><sql:query var="profesores">

select * from profesor</sql:query><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1>

108 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<h2>Listado de profesores</h2><table><thead><tr><th>Cedula</th><th>Nombre</th><th>Titulo</th><th>Acciones</th></tr></thead><tbody><c:forEach var="profesor" begin="0" items="$

→˓{profesores.rows}"><tr><td>${profesor.cedula}</td><td>${profesor.nombre}</td><td>${profesor.titulo}</td><td><a href='/detalleProfesor.jsp?id=$

→˓{profesor.id}'><input type="submit" value="Detalle"/

→˓></a><a href='/eliminarProfesor.jsp?id=$

→˓{profesor.id}'><input type="submit" value="Eliminar

→˓"/></a></td></tr></c:forEach></tbody><tfoot><tr><td><a href='/agregarProfesor.jsp'>

<input type="submit" name="action" value=→˓"Agregar"/></a>

</td><td></td><td></td><td></td></tr></tfoot>

</table></html>

Es importante observar en este código que existen enlaces que accede-rán a otras páginas para realizar acciones con los datos. Por ejemplo,el enlace de “Detalle” ejecutará la página detalleProfesor.jsp con elparámetro ID; y el enlace de “Eliminar” ejecutará la página eliminar-Profesor.jsp con el mismo parámetro ID. También está presente otroenlace “Agregar” que invocará a la página agregarProfesor.jsp perosin parámetros.

1.6. Uso de JSTL 109

Desarrollo con Java, Versión

Detalle del profesor

La página detalleProfesor.jsp recibe como parámetro el ID de un pro-fesor, recupera sus datos desde la base y datos, y los muestra en unformulario HTML. La estructura general de la consulta a la base dedatos es muy similar a la anterior con la diferencia que se recuperasolo un registro particular.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"→˓prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/sql"→˓prefix="sql" %>

<sql:setDataSource dataSource="universidad"></→˓sql:setDataSource><sql:query var="profesores">

select * from profesor where id = ?<sql:param value="${param.id}" />

</sql:query><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="style.css">

</head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><form name="ActualizarProfesor" action=

→˓"actualizarProfesor" method="get"><table style="width:400px;"><thead><tr><th></th><th></th></tr></thead><tbody><c:forEach var="profesor" begin="0" items="$

→˓{profesores.rows}"><input type="hidden" name="id" value="$

→˓{profesor.id}"/><tr><td>Nombre:</td><td>

<input type="text" name="nombre" value="$→˓{profesor.nombre}"/></td></tr>

110 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<tr><td>Cedula:</td><td><input type="text" name="cedula" value="$

→˓{profesor.cedula}"/></td></tr><tr><td>Titulo:</td><td>

<input type="text" name="titulo" value="$→˓{profesor.titulo}"/></td></tr>

<tr><td>Area:</td><td><input type="text" name="area" value="$

→˓{profesor.area}"/></td></tr><tr><td>Telefono:</td><td>

<input type="text" name="telefono" value="$→˓{profesor.telefono}"/></td></tr>

</tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr></c:forEach></tfoot>

</tbody></table></form>

</html>

Este código también cuenta con un enlace adicional “Actualizar” quepermite tomar la información del formulario y realizar la actualiza-ción de datos en la base de datos, mediante la página actualizarPro-fesor.jsp

Hoja de estilo

Con el fin de mejorar la apariencia de este ejemplo se ha desarrolladouna pequeña hoja de estilo (css) que permite organizar mejor los datosde la tabla y el formulario. El archivo llamado style.css cuenta con elsiguiente código:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;

1.6. Uso de JSTL 111

Desarrollo con Java, Versión

color: #009;}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

Ambiente de ejecución

Para ejecutar este ejemplo es necesario contar con un servidor de ser-vlets que permita también la ejecución de plantillas JSTL. La herra-

112 Capítulo 1. Contenidos

Desarrollo con Java, Versión

mienta más utilizada para esto es el Apache Tomcat, el cuál es muypotente y cuenta con gran cantidad de parámetros de configuración.Sin embargo, para propósito de desarrollo y depuración de programasbasta con un ambiente más liviano tal como Winstone.

Winstone consiste de un único archivo de menos de 350 KB, llama-do winstone-0.9.10.jar, el cual puede ser ejecutado directamente me-diante Java. Sin embargo, poder utilizar plantillas JSP se requiere dela herramienta Jasper que consiste de múltiples librerías adicionales.

Para acceder a la base de datos SQLite, mediante JDBC, es necesariocontar con una librería que incluya el driver adecuado. Aún cuandoexisten diferentes librerías que hacen esto, ninguna es pequeña.

Estructura de directorios

La ubicación de los diferentes archivos de código, y librerías se mues-tra en el siguiente esquema de directorios:

tutorial6run.batwinstone-0.9.10.jardatabaseuniversidad.db

rootstyle.csslistaProfesores.jspdetalleProfesor.jsp

libel-api-6.0.18.jarjasper-6.0.18.jarjasper-el-6.0.18.jarjsp-api-6.0.18.jarjstl-impl-1.2jarjtds-1.2.4.jarjuli-6.0.18.jarservlet-api-2.5.jarsqlite-jdbc-3.5.9.jar

1.6. Uso de JSTL 113

Desarrollo con Java, Versión

Ejecución del ejemplo

Teniendo instalado el JDK de Java (no el JRE) basta con ejecutar elarchivo run.bat para iniciar el servidor. El archivo run.bat cuenta conlas siguientes instrucciones (todo en una sola línea) :

java -jar winstone-0.9.10.jar --webroot=root --→˓httpPort=8089

--commonLibFolder=lib --useJasper=true --→˓useJNDI=true

--jndi.resource.universidad=javax.sql.→˓DataSource

--jndi.param.universidad.driverClassName=org.→˓sqlite.JDBC

--jndi.param.universidad.→˓url=jdbc:sqlite:database/universidad.db

Luego se debe apuntar el visualizador (browser) de Web a la direcciónhttp://localhost:8089/listaProfesores.jsp

Nota: Es posible que el JDK de Java se encuentre instalado en otrodirectorio en su máquina.

Modelo/Vista/Controlador

Spring provee muchas opciones para configurar una aplicación. Lamás popular es usar archivos XML.

Capa del dominio

Se utilizará una única clase para ilustrar el desarrollo de una aplica-ción MVC. En este caso será la clase de Profesor.java. Esta clase seubica en el directorio src/domain y su código es el siguiente:

package universidad.domain;import java.io.Serializable;public class Profesor implements Serializable {

114 Capítulo 1. Contenidos

Desarrollo con Java, Versión

private String nombProf;private String idProf;private String tituloProf;public String getNombProf() {return nombProf;}public void setNombProf(String n) {nombProf=n;}public String getIdProf() {return idProf;}public void setIdProf(String id) {idProf=id;}public String getTituloProf() {return tituloProf;}public void setTituloProf(String tit)→˓{tituloProf = tit;}}

Capa de servicio

Aquí se utilizará una clase sencilla, llamada SimpleProfesorMana-ger.java, para configurar la capa de servicio. Adicionalmente se utili-zará una interfaz, llamada ProfesorManager.java, en donde se defini-rán los métodos utilizados por dicha clase. El código de dicha interfazse localiza en el directorio src/service y es el siguiente:

package universidad.service;import java.io.Serializable;import java.util.List;

import universidad.domain.Profesor;public interface ProfesorManager extends→˓Serializable{

public List<Profesor> getProfesores();}

El código de la clase SimpleProfesorManager.java se muestra a con-tinuación y se ubica en el mismo directorio:

package universidad.service;import java.util.ArrayList;import java.util.List;import universidad.domain.Profesor;

1.7. Modelo/Vista/Controlador 115

Desarrollo con Java, Versión

public class SimpleProfesorManager implements→˓ProfesorManager {private List<Profesor> profesores;public List<Profesor> getProfesores() {return profesores;

}public void setProfesores(List<Profesor>

→˓profesores) {this.profesores = profesores;

}}

El controlador

La capa de presentación consta de dos componentes, el controladory la vista. El controlador consta de una sola clase, llamada Profe-sorController.java, que carga el modelo de datos e invoca a la vista,llamada profesorView.jsp. El código se muestra a continuación y seubica en el directorio src/web.:

package universidad.web;import org.springframework.web.servlet.mvc.→˓Controller;import org.springframework.web.servlet.→˓ModelAndView;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.Map;import java.util.HashMap;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import universidad.service.ProfesorManager;

public class ProfesorController implements→˓Controller {protected final Log logger = LogFactory.→˓getLog(getClass());

116 Capítulo 1. Contenidos

Desarrollo con Java, Versión

private ProfesorManager ProfesorManager;

public ModelAndView→˓handleRequest(HttpServletRequest request,

HttpServletResponse response)throws ServletException, IOException {

String now = (new java.util.Date()).toString();logger.info("returning profesor view with " +

→˓now);

Map<String, Object> myModel = new HashMap→˓<String, Object>();

myModel.put("now", now);myModel.put("profesores", this.ProfesorManager.

→˓getProfesores());

return new ModelAndView("profesorView", "model",→˓ myModel);}

public void setProfesorManager(ProfesorManager→˓ProfesorManager) {

this.ProfesorManager = ProfesorManager;}

}

La vista

El archivo que genera la vista se llama profesorView.jsp y constade varias etiquetas que permiten listar la información de profeso-res. El código es el siguiente y este archivo se ubica en el directoriowar/WEB-INF/jsp.:

<%@ include file="/WEB-INF/jsp/include.jsp" %><html><head><title><fmt:message key="title"/></title></→˓head>

1.7. Modelo/Vista/Controlador 117

Desarrollo con Java, Versión

<body><h1><fmt:message key="heading"/></h1><p><fmt:message key="mensaje"/> <c:out value="$

→˓{model.now}"/></p><h3>Profesores</h3><table border="1">

<tr><th>Nombre</th><th>Cedula</th><th>Titulo</→˓th></tr>

<c:forEach items="${model.profesores}" var=→˓"prof">

<tr><td><c:out value="${prof.nombProf}"/></→˓td>

<td><c:out value="${prof.idProf}"/></td><td><c:out value="${prof.tituloProf}"/></td>

→˓</tr></c:forEach>

</table></body>

</html>

Como se puede observar es necesario contar con el archivo inclu-de.jsp que se ubica en el directorio war/WEB-INF/jsp y cuyo códigoes simplemente el siguiente:

<%@ page session="false"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/→˓jstl/core" %><%@ taglib prefix="fmt" uri="http://java.sun.com/→˓jsp/jstl/fmt" %>

También existe un archivo que cuenta con algunos mensajes que sedespliegan en la página y se llama messages.properties. Este archivose ubica en el directorio war/WEB-INF/classes y su contenido es elsiguiente:

title=Sistema Universitarioheading=Sistema Universitario - Iniciomensaje=Bienvenido, la fecha actual es

118 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Configuración

Para configurar la aplicación es necesario contar con un archivoweb.xml ubicado en el directorio war/WEB-INF con el siguientecontenido.:

<?xml version="1.0" encoding="UTF-8"?><web-app 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/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_

→˓4.xsd" ><servlet>

<servlet-name>universidad</servlet-name><servlet-class>org.springframework.web.servlet.

→˓DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup>

</servlet><servlet-mapping>

<servlet-name>universidad</servlet-name><url-pattern>*.htm</url-pattern>

</servlet-mapping><welcome-file-list>

<welcome-file>index.jsp

</welcome-file></welcome-file-list>

</web-app>

También se utilizará otro archivo de configuración para crear objetosde ejemplo que permitan probar la aplicación. Esto se hará utilizandoel archivo universidad-servlet.xml que se ubica en el mismo direc-torio war/WEB-INF. Su contenido es el siguiente:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"

1.7. Modelo/Vista/Controlador 119

Desarrollo con Java, Versión

xmlns:xsi="http://www.w3.org/2001/XMLSchema-→˓instance"xsi:schemaLocation="http://www.springframework.→˓org/schema/beanshttp://www.springframework.org/schema/beans/→˓spring-beans-2.5.xsd"><bean id="profesorManager"class="universidad.service.SimpleProfesorManager

→˓"><property name="profesores">

<list><ref bean="profesor1"/><ref bean="profesor2"/><ref bean="profesor3"/>

</list></property>

</bean><bean id="profesor1" class="universidad.domain.→˓Profesor">

<property name="nombProf" value="Juan Jimenez"/><property name="idProf" value="303450678"/><property name="tituloProf" value="Licenciado"/>

</bean><bean id="profesor2" class="universidad.domain.→˓Profesor">

<property name="nombProf" value="Pedro Perez"/><property name="idProf" value="102340567"/><property name="tituloProf" value="Maestria"/>

</bean><bean id="profesor3" class="universidad.domain.→˓Profesor">

<property name="nombProf" value="Luisa Linares"/→˓>

<property name="idProf" value="407860887"/><property name="tituloProf" value="Licenciada"/>

</bean><bean id="messageSource"class="org.springframework.context.support.

→˓ResourceBundleMessageSource"><property name="basename" value="messages"/>

120 Capítulo 1. Contenidos

Desarrollo con Java, Versión

</bean><bean name="/hello.htm" class="universidad.web.→˓ProfesorController">

<property name="profesorManager" ref=→˓"profesorManager"/></bean><bean id="viewResolver"class="org.springframework.web.servlet.view.

→˓InternalResourceViewResolver"><property name="viewClass"

value="org.springframework.web.→˓servlet.view.JstlView"/>

<property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/>

</bean></beans>

Por último es necesario contar con un archivo inicial que reenvíe lassolicitudes que se realizan al sitio, este archivo se llama index.jsp yse ubica en el directorio war. Su contenido es simplemente:

<%@ include file="/WEB-INF/jsp/include.jsp" %><c:redirect url="/hello.htm"/>

Compilación y ejecución

Para compilar la aplicación es necesario copiar en el directoriowar/WEB-INF/lib las librerías spring.jar y spring-webmvc.jar delframework Spring. También se requieren las librerías servlet-api-2.5.jar y commons-logging-1.1.1.jar pero estas pueden estar ubica-dos simplemente en el directorio lib.

Un script que permite compilar la aplicación tendría la siguiente for-ma (todo en una sola línea):

javac -classpath lib/servlet-api-2.5.jar;lib/→˓commons-logging-1.1.1.jar;war/WEB-INF/lib/spring-webmvc.jar -d war/WEB-INF/

→˓classes

1.7. Modelo/Vista/Controlador 121

Desarrollo con Java, Versión

src/service/*.java src/domain/*.java src/web/*.→˓java

Utilizando winstone se puede correr la aplicación utilizando simple-mente:

java -jar winstone-0.9.10.jar --webroot=war --→˓useJasper

luego basta con apuntar el navegador a la dirección:

http://localhost:8080

Controlador de aplicación con Spring

Spring provee muchas opciones para configurar una aplicación. Lamás popular es usar archivos XML.

Capa del dominio

Se utilizará una única clase para ilustrar el desarrollo de una aplica-ción MVC. En este caso será la clase de Profesor.java. Esta clase seubica en el directorio src/domain y su código es el siguiente:

package universidad.domain;import java.io.Serializable;public class Profesor implements Serializable {private String nombProf;private String idProf;private String tituloProf;public String getNombProf() {return nombProf;}public void setNombProf(String n) {nombProf=n;}public String getIdProf() {return idProf;}public void setIdProf(String id) {idProf=id;}public String getTituloProf() {return tituloProf;}

122 Capítulo 1. Contenidos

Desarrollo con Java, Versión

public void setTituloProf(String tit)→˓{tituloProf = tit;}}

Capa de servicio

Aquí se utilizará una clase sencilla, llamada SimpleProfesorMana-ger.java, para configurar la capa de servicio. Adicionalmente se utili-zará una interfaz, llamada ProfesorManager.java, en donde se defini-rán los métodos utilizados por dicha clase. El código de dicha interfazse localiza en el directorio src/service y es el siguiente:

package service;import java.io.Serializable;import java.util.List;import domain.Profesor;public interface ProfesorManager extends→˓Serializable{

public List<Profesor> getProfesores();public Profesor getById(String id);

}

El código de la clase SimpleProfesorManager.java se muestra a con-tinuación y se ubica en el mismo directorio:

package service;import java.util.ArrayList;import java.util.List;import java.util.Iterator;import domain.Profesor;public class SimpleProfesorManager implements→˓ProfesorManager {private List<Profesor> profesores;public List<Profesor> getProfesores() {return profesores;

}public void setProfesores(List<Profesor>

→˓profesores) {

1.8. Controlador de aplicación con Spring 123

Desarrollo con Java, Versión

this.profesores = profesores;}public Profesor getById(String id) {Iterator itr = profesores.iterator();Profesor prof;while (itr.hasNext()) {

prof = (Profesor)itr.next();if (prof.getIdProf().equals(id)) return prof;

}return null;

}}

El controlador

La capa de presentación consta de dos componentes, el controladory la vista. El controlador consta de una sola clase, llamada Profe-sorController.java, que carga el modelo de datos e invoca a las vis-tas, llamada listaProfesores.jsp y detalleProfesor.jsp. El código semuestra a continuación y se ubica en el directorio src/display.:

package display;

import org.springframework.beans.factory.→˓annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.→˓RequestMapping;import org.springframework.web.bind.annotation.→˓RequestMethod;import org.springframework.web.bind.annotation.→˓PathVariable;import org.springframework.web.bind.annotation.→˓RequestParam;import org.springframework.web.servlet.→˓ModelAndView;

import java.util.Map;

124 Capítulo 1. Contenidos

Desarrollo con Java, Versión

import java.util.HashMap;

import service.ProfesorManager;import domain.Profesor;

@Controller@RequestMapping("/profesor")public class ProfesorController {

@Autowiredprivate ProfesorManager ProfesorManager;

@RequestMapping(value="/listado", method =→˓RequestMethod.GET)public ModelAndView listado() {Map<String, Object> myModel = new HashMap

→˓<String, Object>();myModel.put("profesores", this.ProfesorManager.

→˓getProfesores());return new ModelAndView("listaProfesores",

→˓"model", myModel);}

@RequestMapping(value="/detalleProfesor/{idProf}",→˓ method = RequestMethod.GET)public ModelAndView detalleProfesor(@PathVariable(→˓"idProf") String id) {

Profesor prof = this.ProfesorManager.→˓getById(id);

if (prof == null)System.out.println("NULO");

return new ModelAndView("detalleProfesor",→˓"profesor", prof);}

@RequestMapping(value="/actualizarProfesor/→˓{idProf}", params = { "id", "nombre", "titulo",→˓"cedula" }, method = RequestMethod.GET)public String actualizarProfesor(

@PathVariable("idProf") String id,

1.8. Controlador de aplicación con Spring 125

Desarrollo con Java, Versión

@RequestParam("nombre") String nombre,@RequestParam("titulo") String titulo,@RequestParam("cedula") String cedula

) {Profesor prof = this.ProfesorManager.

→˓getById(id);prof.setNombProf(nombre);prof.setTituloProf(titulo);prof.setIdProf(cedula);return "forward:/profesor/listado";

}

public void setProfesorManager(ProfesorManager→˓ProfesorManager) {

this.ProfesorManager = ProfesorManager;} }

La vistas

El archivo que genera la vista de profesores se llama listaProfeso-res.jsp y consta de varias etiquetas que permiten listar la informaciónde profesores. El código es el siguiente y este archivo se ubica en eldirectorio /root/pages.:

<%@ include file="/pages/include.jsp" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="/resources/style.

→˓css"><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8" /></head><h1>Sistema Universitario</h1><h2>Listado de profesores</h2><table>

<thead>

126 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<tr><th>Nombre</th><th>Cedula</th><th>Titulo</→˓th><th>Acciones</th></tr>

</thead><tbody><c:forEach items="${model.profesores}" var=

→˓"prof"><tr><td>${prof.nombProf}</td><td>${prof.idProf}</td><td>${prof.tituloProf}</td><td><a href='/profesor/detalleProfesor/$

→˓{prof.idProf}'><input type="submit" value="Detalle"/

→˓></a><a href='/profesor/eliminarProfesor/$

→˓{prof.idProf}'><input type="submit" value="Eliminar

→˓"/></a></td></tr></c:forEach></tbody><tfoot><tr><td><a href='/profesor/agregarProfesor'>

<input type="submit" name="action" value=→˓"Agregar"/></a>

</td><td></td><td></td><td></td></tr></tfoot>

</table></body>

</html>

Como se puede observar es necesario contar con el archivo inclu-de.jsp que se ubica en el mismo directorio root/pages y cuyo códigoes simplemente el siguiente:

<%@ page session="false"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/→˓jstl/core" %><%@ taglib prefix="fmt" uri="http://java.sun.com/→˓jsp/jstl/fmt" %>

El otro archivo de vista es el que genera el detalle del profesor, es

1.8. Controlador de aplicación con Spring 127

Desarrollo con Java, Versión

llamado detalleProfesor.jsp y se encuentra ubicado en el mismo di-rectorio /root/pages

<%@ include file="/pages/include.jsp" %><html>

<head><title>Sistema Universitario</title><link rel="stylesheet" href="/resources/style.

→˓css"><meta http-equiv="Content-Type" content="text/

→˓html; charset=UTF-8" /></head><h1>Sistema Universitario</h1><h2>Detalle de Profesor</h2><form name="ActualizarProfesor" action="/

→˓profesor/actualizarProfesor/${profesor.idProf}"→˓method="get"><table style="width:400px;"><thead><tr><th></th><th></th></tr></thead><tbody><input type="hidden" name="id" value="$

→˓{profesor.idProf}"/><tr><td>Nombre:</td><td>

<input type="text" name="nombre" value="$→˓{profesor.nombProf}"/></td></tr>

<tr><td>Cedula:</td><td><input type="text" name="cedula" value="$

→˓{profesor.idProf}"/></td></tr><tr><td>Titulo:</td><td>

<input type="text" name="titulo" value="$→˓{profesor.tituloProf}"/></td></tr>

</td></tr></tbody><tfoot><tr><td><input type="submit" value="Actualizar

→˓" /></td><td></td></tr></tfoot>

</tbody></table>

128 Capítulo 1. Contenidos

Desarrollo con Java, Versión

</form></html>

Configuración

Para configurar la aplicación es necesario contar con un archivoweb.xml ubicado en el directorio root/WEB-INF con el siguientecontenido.:

<web-app id="WebApp_ID" 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/

→˓j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd

→˓">

<display-name>Sistema Universitario</display-→˓name>

<servlet><servlet-name>universidad</servlet-name><servlet-class>

org.springframework.web.servlet.→˓DispatcherServlet

</servlet-class><load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping><servlet-name>universidad</servlet-name><url-pattern>/</url-pattern>

</servlet-mapping>

<context-param><param-name>contextConfigLocation</param-

→˓name>

1.8. Controlador de aplicación con Spring 129

Desarrollo con Java, Versión

<param-value>/WEB-INF/universidad-servlet.→˓xml</param-value>

</context-param>

<listener><listener-class>org.springframework.web.

→˓context.ContextLoaderListener</listener-class></listener>

</web-app>

También se utilizará otro archivo de configuración para crear objetosde ejemplo que permitan probar la aplicación. Esto se hará utilizandoel archivo universidad-servlet.xml que se ubica en el mismo direc-torio root/WEB-INF. Su contenido es el siguiente:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/→˓schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-→˓instance"

xmlns:context="http://www.springframework.org/→˓schema/context"

xmlns:mvc="http://www.springframework.org/→˓schema/mvc"

xsi:schemaLocation="http://www.springframework.→˓org/schema/beans

http://www.springframework.org/schema/beans/→˓spring-beans.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/

→˓spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/

→˓spring-mvc-3.0.xsd">

<context:component-scan base-package="display"→˓/>

<bean id="profesorManager"class="service.SimpleProfesorManager">

130 Capítulo 1. Contenidos

Desarrollo con Java, Versión

<property name="profesores"><list>

<ref bean="profesor1"/><ref bean="profesor2"/><ref bean="profesor3"/>

</list></property></bean><bean id="profesor1" class="domain.Profesor">

<property name="nombProf" value="Juan→˓Jimenez"/>

<property name="idProf" value="303450678"/><property name="tituloProf" value=

→˓"Licenciado"/></bean><bean id="profesor2" class="domain.Profesor">

<property name="nombProf" value="Pedro→˓Perez"/>

<property name="idProf" value="102340567"/><property name="tituloProf" value="Maestria

→˓"/></bean><bean id="profesor3" class="domain.Profesor">

<property name="nombProf" value="Luisa→˓Linares"/>

<property name="idProf" value="407860887"/><property name="tituloProf" value=

→˓"Licenciada"/></bean><bean class="org.springframework.web.servlet.

→˓view.InternalResourceViewResolver"><property name="prefix" value="/pages/"/><property name="suffix" value=".jsp"/>

</bean>

<mvc:resources mapping="/resources/**"→˓location="/web-resources/"/>

<mvc:annotation-driven /></beans>

1.8. Controlador de aplicación con Spring 131

Desarrollo con Java, Versión

Por último es necesario contar con una hoja de estilo que se ubicaríaen el directorio /root/web-resources y se llamaría style.css:

body {line-height: 1.6em;font-family:"Lucida Sans Unicode", "Lucida Grande

→˓", Sans-Serif;color: #009;

}table {

font-size: 12px;margin: 45px;width: 480px;text-align: left;border-collapse: collapse;

}th, tfoot td {

font-size: 13px;font-weight: normal;padding: 8px;background: #b9c9fe;border-top: 4px solid #aabcfe;border-bottom: 1px solid #fff;color: #039;text-align: center;

}td {

padding: 8px;background: #e8edff;border-bottom: 1px solid #fff;color: #669;border-top: 1px solid transparent;

}tr:hover td {

background: #d0dafd;color: #339;

}input[type="text"] {

width: 250px;}

132 Capítulo 1. Contenidos

Desarrollo con Java, Versión

Ejecución

Utilizando winstone se puede correr la aplicación utilizando simple-mente:

java -jar winstone-0.9.10.jar --httpPort=8089 --→˓commonLibFolder=lib --useJasper=true --→˓webroot=root

luego basta con apuntar el navegador a la dirección:

http://localhost:8089/profesor/listado

1.8. Controlador de aplicación con Spring 133