Download tomcat-bient.CRASHED

Document related concepts
no text concepts found
Transcript
Crear tu Primera Aplicación Web Real con Tomcat 4 y
MySQL
Autor: OnJava (OnJava)
Traductor: Juan Antonio Palos (Ozito)

¿Qué Tecnologías Utilizar?
¿Qué Tecnologías Utilizar?
Hemos decidido utilizar las tecnologías del contenedor Servlet/JSP Tomcat 4 para implementar una
aplicación Web. Esto todavía tiene muchas opciones, y elegir entre las distintas tecnologías disponibles
no es fácil. Para este curso, hemos decidido dejarlo lo más simple posible y utilizar Java Server Pages
(JSPs) en combinación con clases Java.
Deberíamos evitar la utilización de JSPs para implementar lógica compleja; dichas aplicaciones pueden
ser divertidas de escribir, pero puede ser frustrante su depuración y casi imposible de entender y
mantener. Una solución realmente buena es usar JSPs para manejar la presentación de la página web
(porque para esto son buenas las JSPs), y Java para implementar la lógica compleja, como el acceso a
bases de datos. De esta forma, el software será fácil de escribir y de depurar, y posteriormente el código
será sencillo de entender y de mantener.
La aplicación Web puede servirse sobre en un servidor Web dedicado o sobre un ordenador personal con
Windows, Linux, o Mac OS X. Requiere un Java runtime environment (JDK 1.2 o superior ), y una versión
reciente del Contenedor Servlet/JSP Tomcat (versión 4 o superior). Todos estos paquetes están
disponibles en Internet de forma gratuita.
La aplicación Web también requiere una base de datos. Servirá casi cualquier base de datos relacional, si
acepta SQL y tiene un driver JDBC. MySQL tiene buena reputación y se ajusta a nuestro presupuesto
perfectamente. Podemos obtener la última versión de MySQL y su driver Connector/J JDBC
Driver desde MySQL.com.
Para dar acceso a Tomcat (y sus aplicaciones) a nuestra base de datos, debemos copiar el fichero del
driver JDBC de la base de datos al directorio common/lib de Tomcat. Finalmente, debemos
configurar los roles admin y manager de Tomcat, y los nombres de usuarios y las passwords.
Editamos el fichero tomcat-users.xml en el directorio conf de Tomcat, para que se parezca a
esto:
<?xml version='1.0'?>
<tomcat-users>
<role rolename="admin"/>
<role rolename="manager"/>
<user username="tomcatusername" password="tomcatpassword"
roles="admin,manager"/>
</tomcat-users>
Configurar la Base de Datos
Crear la Tabla Libros en la Base de Datos
Configurar la base de datos depende del software de base de datos que estemos utilizando. Necesitarás
corregir estas instrucciones si no utilizas MySQL. Libreria emplea una sola tabla llamada Libros en
una base de datos llamada biblioteca. La tabla Libros tiene siete campos:

id, la clave primaria, un campo numérico que se incrementa automáticamente.

isbn, un campo de 13 caracteres que contiene el código ISBN único para cada libro.

editorial, un campo de 24 caracteres que contiene el nombre de la editorial que ha
publicado el libro.

autor, un campo de 32 caracteres que contiene el nombre del autor del libro.

categoria, un campo de 32 caracteres que contiene la categoría a la que pertenece el libro.

titulo, un campo de 50 caracteres que contiene el título del libro.

ubicacion, un campo de 5 caracteres en el ubicación actual del libro en nuestro sistema de
estanterías.
Configuremos la base de datos MySQL. Primero arrancamos la Base de Datos utilizado la línea de
comandos mysql con permisos de root. Cuando se nos pida, introducimos la password.
Creamos la base de datos biblioteca y le concedemos permisos a mysqlusername en esa
base de datos con la password mysqlpassword. Los comandos son:
# mysql -u root -p
mysql> create database biblioteca;
mysql> grant all privileges on biblioteca.* to
mysqlusername@localhost \
identified by 'mysqlpassword' with grant option;
mysql> flush privileges;
Luego, creamos la tabla Libros en la base de datos biblioteca:
mysql> create table Libros ( \
id
tinyint(4) primary key auto_increment, \
isbn
varchar(13) NOT NULL, \
editorial varchar(24) NOT NULL, \
autor varchar(32) NOT NULL, \
categoria
varchar(32) NOT NULL, \
titulo varchar(50) NOT NULL, \
ubicacion
varchar(5) NOT NULL \
);
Enviamos los cambios con el comando commit;.
Para verificar la configuración de la tabla, ejecutamos el comando
ver algo como esto:
describe Libros;. Deberíamos
Ahora podemos insertar una fila de datos para probar la base de datos:
mysql> insert into libros(isbn, editorial, autor, categoria,
titulo, \
-> ubicacion) values ("84-415-0092-4", "Anaya Multimedia",\
-> "Varios", "Informática", "La Biblia de Java", "AB-14");
mysql> select * from Libros;
Las Clases Java de la Aplicación
La aplicación Web utilizada para demostrar las tecnologías usadas en este tutorial es una simple
aplicación de control de una librería (solo control y ubicación de los libros, no hay facturación, por
ejemplo), llamada Libreria . No es el propósito de este tutorial crear una aplicación completa, es sólo
un ejemplo.
Libreria tiene tres clases Java:

libreria.ContextListener es un oyente del contexto servlet al que Tomcat llamará cuando inicie y
detenga la aplicación Libreria. Esta clase crea un objeto de la clase LibrosBD y lo almacena
como un atributo de contexto con el nombre BaseDatos


libreria.LibrosBD es una clase que representa la base de datos de libros. Su constructor
establece una conexión a la base de datos (utilizando el objeto LibrosBD que se obtiene del
atributo de contexto BaseDatos), y la sesión se puede compartir entre varias sesiones web.
La clase proporciona varios métodos de acceso a la base de datos (para insertar, borrar,
modificar u obtener registros de la base de datos).
libreria.Libro es una clase Java que representa un libro. Las páginas JSP de la aplicación utilizan
esta clase como un Bean contenedor de datos para mostrarlos.
libreria.ContextListener
libreria.ContextListener es un oyente del contexto servlet al que se llamará cuando
arranque y cuando se pare la aplicación Libreria. Esto se configura en el descriptor de despliegue de la
aplicación web.xml. Cuando se arranca la aplicación Libreria se crea un ejemplar de la clase LibrosBD y
se almacena como un atributo de contexto; cuando se cierra la aplicación, el objeto LibrosBD se recupera
del atributo de contexto y se cierra la conexión con la base de datos. Entre tanto, las JSP recuperan el
objeto LibrosBD del atributo de contexto siempre que necesitan acceder a la base de datos.
Propósito de la clase ContextListener
El propósito de la clase Java libreria.ContextListener es crear un ejemplar de
libreria.LibrosBD y almacenarlo como un atributo del contexto servlet identificado como:
"BaseDatos". Esto permitirá a las páginas JSP recuperar el ejemplar de libreria.LibrosBD
y acceder a la tabla Libros.
libreria.ContextListener está configurado como un oyente de contexto servlet en el fichero
web.xml.
Métodos de la clase ContextListener

contextInitialized
Se llama a contextInitialized siempre que la aplicación web arranca.
Primero se recupera el contexto servlet desde el evento de contexto servlet:
ServletContext servletContext =
servletContextEvent.getServletContext ();
Luego se crea un ejemplar de LibrosBD y se graba en el contexto servlet identificado como:
"BaseDatos". Si este proceso lanza una excepción se guarda un log:
try {
LibrosBD LibrosBD = new LibrosBD ();
servletContext.setAttribute ("BaseDatos",
LibrosBD);
}
catch (Exception e) {
servletContext.log ("No se pudo crear el atributo
BaseDatos: " + e.getMessage());
}

contextDestroyed
Se llama a contextDestroyed cuando se cierra la aplicación web.
Primero se recupera el contexto servlet desde el evento ServletContexto:
ServletContext servletContext =
servletContextEvent.getServletContext ();
LibrosBD desde el contexto y se cierra la base de datos:
LibrosBD LibrosBD = (LibrosBD)
servletContext.getAttribute ("BaseDatos");
LibrosBD.close ();
Luego se recupera el objeto
Luego se elimina el atributo del contexto servlet:
servletContext.removeAttribute ("BaseDatos");
Código Fuente Completo de la clase ContextListener
//
//
//
ContextListener.java
package libreria;
import javax.servlet.*;
public final class ContextListener implements
ServletContextListener {
public void contextInitialized (ServletContextEvent
servletContextEvent) {
ServletContext servletContext =
servletContextEvent.getServletContext ();
try {
LibrosBD LibrosBD = new LibrosBD ();
servletContext.setAttribute ("BaseDatos", LibrosBD);
}
catch (Exception e) {
servletContext.log ("No se pudo crear el atributo
BaseDatos: " + e.getMessage ());
}
}
public void contextDestroyed (ServletContextEvent
servletContextEvent) {
ServletContext servletContext =
servletContextEvent.getServletContext ();
LibrosBD LibrosBD = (LibrosBD) servletContext.getAttribute
("BaseDatos");
LibrosBD.close ();
servletContext.removeAttribute ("BaseDatos");
}
}
libreria.LibrosBD
libreria.LibrosBD es una clase que representa la base de datos de libros. Su constructor
establece una conexión a la base de datos, y la sesión se puede compartir entre varias sesiones web. La
clase proporciona varios métodos de acceso a la base de datos.
Propósito de la clase LibrosBD
El propósito de la clase libreria.LibrosBD es establecer una conexión a la base de datos
pública y proporcionar métodos para acceder de forma segura y actualizar la tabla Libros contenida en
la base de datos sin conflictos con otros usuarios que estén accediendo a los mismos datos.
Sólo hay una conexión a la base de datos que es compartida por todos los usuarios de la aplicación Web
Libreria. Esto es adecuado mientras el número de usuarios concurrentes no sea excesivo. Vamos a
mantenerlo lo más simple posible, sólo debemos añadir soporte para varias conexiones si es realmente
necesario. Observa, sin embargo, que si vamos a realizar esas complejidades, es en esta clase Java
donde debemos hacerlas.
Métodos de la Clase LibrosBD

Constructor de LibrosBD:
Establece una conexión a la base de datos pública.
Hasta hace poco, si queríamos establecer una conexión a una base de datos desde un Servlet
bajo Tomcat teníamos que codificar el driver JDBC, la URL de la base de datos, y el nombre de
usuario y su password dentro del Servlet de esta forma:
Class.forName ("org.gjt.mm.mysql.Driver").newInstance
();
connection = DriverManager.getConnection
("jdbc:mysql://localhost/MiBase",
"mysqlusername",
"mysqlpassword");
No es buena idea codificar dicha información en el código fuente de la aplicación. Tomcat 4
resuelve este problema permitiendo al Servlet acceder a Tomcat y recuperar una conexión desde
el DataSource que se define en el fichero Libreria.xml, como veremos más adelante.
Primero se recupera el javax.naming.InitialContext para que se pueda realizar
una búsqueda JNDI:
InitialContext initialContext = new InitialContext ();
Después se recupera el contexto de la aplicación Libreria:
Context envContext = (Context) initialContext.lookup
("java:comp/env");
DataSource:
DataSource dataSource = (DataSource) envContext.lookup
("jdbc/biblioteca");
Luego se recupera el propio
DataSource:
this.connection = dataSource.getConnection ();
Y por último se recupera la conexión desde el
Todos los parámetros del DataSource tenemos que definirlos en el fichero
Libreria.xml (que veremos más adelante), aunque también se pueden modificar usando
las facilidades de administración de Tomcat, con la dirección
http://localhost:8080/admin .

getConnection
Se utilizan los métodos getConnection y releaseConnection para asegurarse de
que la conexión a la base de datos se puede compartir de forma segura, el recurso de la
conexión se controla utilizando los métodos sincronizados getConnection y
releaseConnection.
Primero getConnection espera hasta que se libera la conexión:
while (this.connectionFree == false) {
try {
wait ();
}
catch (InterruptedException e) {
}
}
Luego marca el indicador de conexión libre como no libre, así bloquea la conexión hasta que se
llame a releaseConnection:
this.connectionFree = false;
Luego se lo notifica a cualquier otro thread de LibrosBD que esté esperando una conexión:
notify ();
Finalmente devuelve la conexión:
return this.connection;

releaseConnection
Primero espera hasta que la conexión esté ocupada:
while (this.connectionFree == true) {
try {
wait ();
}
catch (InterruptedException e) {
}
}
Luego selecciona el indicador de conexión libre a libre, así desbloquea la conexión hasta que se
llame a getConnection:
this.connectionFree = true;
Finalmente se lo notifica a cualquier otro thread de
conexión:
LibrosBD que esté esperando una
notify ();
Todas las demás rutinas que acceden a la base de datos emplean getConnection y
releaseConnection, para que sólo pueda acceder a la base de datos un thread a la vez.

getLibro
El método getLibro toma un parámetro id y devuelve el Libro para ese id; si no se
puede encontrar ese id se devuelve un Libro null.
getLibro primero obtiene una conexión libre
this.getConnection ();
Luego crea una sentencia select, e inserta el id en la posición adecuada:
PreparedStatement preparedStatement =
this.connection.prepareStatement ("SELECT * FROM
Libros WHERE id = ?");
preparedStatement.setString (1, id);
Luego ejecuta la sentencia:
ResultSet resultSet = preparedStatement.executeQuery ();
Si la sentencia select devuelve datos, se ensambla un objeto Libro con los datos, se
cierra la consulta sql; se libera la conexión se devuelve el objeto Libro:
if (resultSet.next ()) {
Libro libro = new Libro (
resultSet.getString (1), resultSet.getString
(2), resultSet.getString (3),
resultSet.getString (4), resultSet.getString
(5), resultSet.getString (6),
resultSet.getString (7)
);
preparedStatement.close ();
this.releaseConnection ();
return libro;
}
Si la sentencia select no devuelve datos, se cierra la sentencia, se libera la conexión, y se
devuelve un objeto Libro null:
else {
preparedStatement.close ();
this.releaseConnection ();
return null;
}

insertarLibro, borrarLibro, modificarLibro, y obtenerLibros
Todos estos métodos utilizan una técnica similar a la del método

close
close simplemente cierra la conexión:
this.connection.close ();
getLibro
Código Fuente Completo de la clase LibrosBD
//
//
//
LibrosBD.java
package libreria;
import
import
import
import
java.sql.*;
java.util.*;
javax.sql.*;
javax.naming.*;
public class LibrosBD {
Connection connection;
private boolean connectionFree = true;
private ArrayList libros;
public LibrosBD () throws Exception {
try {
InitialContext initialContext = new InitialContext ();
Context envContext = (Context) initialContext.lookup
("java:comp/env");
DataSource dataSource = (DataSource) envContext.lookup
("jdbc/biblioteca");
this.connection = dataSource.getConnection ();
}
catch (Exception e) {
throw new Exception ("No se pudo abrir la base de datos
biblioteca: " + e.getMessage ());
}
}
protected synchronized Connection getConnection () {
while (this.connectionFree == false) {
try {
wait ();
}
catch (InterruptedException e) {
}
}
this.connectionFree = false;
notify ();
return this.connection;
}
protected synchronized void releaseConnection () {
while (this.connectionFree == true) {
try {
wait ();
}
catch (InterruptedException e) {
}
}
this.connectionFree = true;
notify ();
}
public Libro getLibro (String id) {
try {
this.getConnection ();
PreparedStatement preparedStatement =
this.connection.prepareStatement
("SELECT id, isbn, editorial, autor, categoria,
titulo, ubicacion FROM libros" +
" WHERE id = ?");
preparedStatement.setString (1, id);
ResultSet resultSet = preparedStatement.executeQuery
();
if (resultSet.next ()) {
Libro libro = new Libro (
resultSet.getString (1), resultSet.getString
(2), resultSet.getString (3),
resultSet.getString (4), resultSet.getString
(5), resultSet.getString (6),
resultSet.getString (7)
);
preparedStatement.close ();
this.releaseConnection ();
return libro;
}
else {
preparedStatement.close ();
this.releaseConnection ();
return null;
}
}
catch (SQLException e) {
this.releaseConnection ();
return null;
}
}
public int insertarLibro (Libro libro) {
int rowsAffected = 0;
try {
this.getConnection ();
PreparedStatement preparedStatement =
this.connection.prepareStatement
("INSERT INTO libros (isbn, editorial, autor,
categoria, titulo, " +
" ubicacion) VALUES (?, ?, ?, ?, ?, ?)");
preparedStatement.setString (1, libro.getIsbn ());
preparedStatement.setString (2, libro.getEditorial
());
preparedStatement.setString (3, libro.getAutor ());
preparedStatement.setString (4, libro.getCategoria
());
preparedStatement.setString (5, libro.getTitulo ());
preparedStatement.setString (6, libro.getUbicacion
());
rowsAffected = preparedStatement.executeUpdate ();
preparedStatement.close ();
this.releaseConnection ();
}
catch (SQLException e) {
this.releaseConnection ();
return 0;
}
return rowsAffected;
}
public int borrarLibro (String id){
int rowsAffected = 0;
try {
this.getConnection ();
PreparedStatement preparedStatement =
this.connection.prepareStatement ("DELETE FROM
libros WHERE id = ?");
preparedStatement.setString (1, id);
rowsAffected = preparedStatement.executeUpdate ();
preparedStatement.close ();
this.releaseConnection ();
}
catch (SQLException e) {
this.releaseConnection ();
return 0;
}
return rowsAffected;
}
public int modificarLibro (Libro libro) {
int rowsAffected = 0;
try {
this.getConnection ();
PreparedStatement preparedStatement =
this.connection.prepareStatement ("UPDATE libros
SET isbn=?, editorial=?," +
" autor=?, categoria=?, titulo=?, ubicacion=?
WHERE id =?");
preparedStatement.setString (1, libro.getIsbn ());
preparedStatement.setString (2, libro.getEditorial
());
preparedStatement.setString (3, libro.getAutor ());
preparedStatement.setString (4, libro.getCategoria
());
preparedStatement.setString (5, libro.getTitulo ());
preparedStatement.setString (6, libro.getUbicacion
());
preparedStatement.setString (7, libro.getId ());
rowsAffected = preparedStatement.executeUpdate ();
preparedStatement.close ();
this.releaseConnection ();
}
catch (SQLException e) {
this.releaseConnection ();
return 0;
}
return rowsAffected;
}
public Collection getLibros () {
libros = new ArrayList ();
try {
this.getConnection ();
PreparedStatement preparedStatement =
this.connection.prepareStatement
("SELECT id, isbn, editorial, autor, categoria,
titulo, ubicacion FROM libros");
ResultSet resultSet = preparedStatement.executeQuery
();
while (resultSet.next ()) {
Libro libro = new Libro (
resultSet.getString (1), resultSet.getString
(2), resultSet.getString (3),
resultSet.getString (4), resultSet.getString
(5), resultSet.getString (6),
resultSet.getString (7)
);
libros.add (libro);
}
preparedStatement.close ();
}
catch (SQLException e) {
return null;
}
this.releaseConnection ();
return libros;
}
public void close () {
try {
this.connection.close ();
}
catch (SQLException e) {
System.out.println (e.getMessage ());
}
}
}
libreria.Libro
libreria.Libro es una clase Java que representa un libro. Las clases que recolectan datos
todavía son una buena idea cuando se programan JSPs, por eso esta clase es una buena idea para la
aplicación Libreria.
El constructor de libreria.Libro almacena los campos del libro en el objeto. Esta clase también
incluye los habituales métodos get para recuperar los datos del libro:

Libro(String id, String isbn, String editorial, String autor,
String categoria,
String titulo, String ubicacion)

getId()

getIsbn()

getEditorial()

getAutor()

getCategoria()

getTitulo()

getUbicacion()
Propósito de la clase Libros
El propósito de esta clase es recolectar los datos relativos a un libro de nuestra base de datos.
Métodos de la clase Libros

Constructor de la clase Libro
El constructor almacena los campos suministrados del libro:
this.id = id;
this.isbn = isbn;
this.editorial = editorial;
this.autor = autor;
this.categoria = categoria;
this.titulo = titulo;
this.ubicacion = ubicacion;

getId, getIsbn, getEditorial, getAutor, getCategoria, getTitulo y
getUbicacion
Estos métodos devuelven los distintos campos que componente un libro.
Código Fuente Completo de la clase Libro
//
//
//
Libro.java
package libreria;
public class Libro
private String
private String
private String
private String
private String
private String
private String
{
id = null;
isbn = null;
editorial = null;
autor = null;
categoria = null;
titulo = null;
ubicacion = null;
public Libro (String id, String isbn, String editorial,
String autor, String categoria, String titulo, String
ubicacion) {
this.id = id;
this.isbn = isbn;
this.editorial = editorial;
this.autor = autor;
this.categoria = categoria;
this.titulo = titulo;
this.ubicacion = ubicacion;
}
public String getId () {
return this.id;
}
public String getIsbn () {
return this.isbn;
}
public String getEditorial () {
return this.editorial;
}
public String getAutor () {
return this.autor;
}
public String getCategoria () {
return this.categoria;
}
public String getTitulo () {
return this.titulo;
}
public String getUbicacion () {
return this.ubicacion;
}
}
Las Páginas JSP
La aplicación Libreria tiene siete páginas JSP. Cada una representa una página Web que realiza una
operación independiente sobre la base de datos. El estado de la base de datos en cada página es
independiente de su estado en la página anterior. Si la base de datos cambia debido a una solicitud de
otro usuario, la página Web lo detectará y reaccionará de la forma apropiada. Por ejemplo, si estamos
modificando un libro y otro usuario borra ese libro antes de que confirmemos la solicitud de modificación,
la JSP nos notificará el fallo al intentar modificar un libro que ahora no existe.
La página Index.jsp
Es la página principal de la aplicación web Libreria, y es la primera página que se muestra a un usuario
cuando entra en la aplicación Web. Muestra una tabla con todos los libros que hay en la tabla Libros
de la base de datos. Cada fila de la tabla muestra un libro individual, y enlaces para borrar o modificar es
libro. La parte inferior de la página tiene un enlace para poder añadir nuevos libros.

El enlace Añadir un Nuevo Libro pasa el control a la página Form_Insertar.jsp.

El enlace Borrar pasa el control a la página Form_Borrar.jsp con el id del libro a borrar.

El enlace Modificar pasa el control a la página Form_Modificar.jsp con el id del libro a
modificar.
Propósito de la Página Index.jsp
El propósito de Index.jsp es producir una página Web con una tabla que muestre el contenido de la
tabla Libros de la base de datos, con enlaces para añadir nuevos libros a la base de datos
[Form_Insertar.jsp]; borrar libros específicos de la base de datos [Form_Borrar.jsp]; y modificar libros
específicos en la base de datos [Form_Modificar.jsp].
La siguiente figura muestra un ejemplo de la página principal de la aplicación Libreria:
Aspecto de la Página
Este código HTML dibuja el aspecto de la página con un enlace a Form_Insertar.jsp en la parte inferior de
la página
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Página Principal de mi Librería</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Página Principal de mi Librería</center></h1>
--- Aquí va el código que muestra la tabla con los datos
<hr>
<center>
<destacar><a href="Form_Insertar.jsp">Añadir un Nuevo
Libro</a></destacar>
</center>
</body>
</html>
Mostrar la Tabla
Este código HTML muestra la tabla y sus cabeceras:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>Autor</th>
<th>Titulo</th>
<th>Ubicacion</th>
<th>Accion</th>
<th>ID</th>
</tr>
-- Aquí va el código que muestra los datos
</table>
Bucle por Todas las Filas de la Tabla
Este código Java recupera el ejemplar libreria.LibrosBD almacenado en el atributo
BaseDatos de la aplicación Web por libreria.ContextListener:
LibrosBD librosBD = (LibrosBD)
application.getAttribute ("BaseDatos");
Luego se recupera un objeto Collection con el contenido de la base de datos:
Collection libros = librosBD.getLibros();
Si el objeto Collection no es nulo, y contiene algún libro [es decir, su tamaño es mayor que cero], se
procesa el objeto Collection recuperando uno por uno todos sus libros:
if (libros != null) {
if (libros.size () > 0) {
for (Iterator iterator = libros.iterator();
iterator.hasNext(); ) {
... aquí va el código que muestra los datos de una
fila...
}
}
}
Mostrar un Libro en un Fila de la Tabla
Este código HTML mezclado con código Java muestra un libro en una fila de la tabla. El código Java
simplemente recupera campos individuales desde el libro:libro.getAutor() devuelve el nombre
del autor del libro; libro.getTitulo () devuelve el título del libro; libro.getUbicacion
() devuelve la ubicación del libro en nuestras estanterías; y libro.getId () devuelve el id. En la
primera columna de la tabla va el nombre del autor; en la segunda columna va el título; en la tercera
columna va la ubicación, en la cuarta columna un enlace a Form_Borrar.jsp, la palabra "o" y un enlace a
Form_Modificar.jsp; y en la columna final va el id:
<tr>
<td>
<%= libro.getAutor () %>
</td>
<td>
<%= libro.getTitulo () %>
</td>
<td>
<%= libro.getUbicacion () %>
</td>
<td align="center">
<destacar><a
href="Form_Borrar.jsp?id=<%= libro.getId () %>">
Borrar</a></destacar>
o
<destacar><a
href="Form_Modificar.jsp?id=<%= libro.getId () %>">
Modificar</a></destacar>
</td>
<td align="center">
<%= libro.getId () %>
</td>
</tr>
Cuando se selecciona el enlace "Borrar" se le pasa el parámetro id a la página Form_Borrar.jsp, y
cuando se selecciona el enlace "Modificar" se le pasa el mismo parámetro a la página Form_Modificar.jsp.
Código Completo de la Página Index.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Página Principal de mi Librería</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Página Principal de mi Librería</center></h1>
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>Autor</th>
<th>Titulo</th>
<th>Ubicacion</th>
<th>Accion</th>
<th>ID</th>
</tr>
<%
LibrosBD librosBD = (LibrosBD)
application.getAttribute ("BaseDatos");
Collection libros = librosBD.getLibros();
if (libros != null) {
if (libros.size () > 0) {
for (Iterator iterator = libros.iterator();
iterator.hasNext(); ) {
Libro libro = (Libro) iterator.next ();
%>
<tr>
<td>
<%= libro.getAutor () %>
</td>
<td>
<%= libro.getTitulo () %>
</td>
<td>
<%= libro.getUbicacion () %>
</td>
<td align="center">
<destacar><a
href="Form_Borrar.jsp?id=<%= libro.getId () %>">
Borrar</a></destacar>
o
<destacar><a
href="Form_Modificar.jsp?id=<%= libro.getId () %>">
Modificar</a></destacar>
</td>
<td align="center">
<%= libro.getId () %>
</td>
</tr>
<%
}
}
}
%>
</table>
<br>
<hr>
<center>
<destacar><a href="Form_Insertar.jsp">Añadir un Nuevo
Libro</a></destacar>
</center>
</body>
</html>
Insertar un Registro en la Base de Datos
Form_Insertar.jsp
Form_Insertar.jsp muestra un formulario en el que introduciremos los campos del nuevo libro.
En la parte inferior de la página hay en enlace para abortar la solicitud.
Propósito de la Página Form_Insertar.jsp
El propósito de esta página es producir una página Web con un formulario que el usuario rellena con los
datos de un libro. El usuario podría entonces enviar los datos del formulario para su procesamiento
transfiriendo el control a la página o abortar el proceso seleccionando un enlace de vuelta a la página
Index.jsp. En la siguiente figura podemos ver un ejemplo de la página Form_Insertar.jsp:
Aspecto de la Página Form_Insertar.jsp
Este código HTML crea el aspecto de la página con un enlace a la página Index.jsp, etiquetado como
"Volver a la Página Inicial [el libro no se añadirá]" en la parte inferior de la página:
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería: Insertar un nuevo libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería: Insertar un nuevo
libro</center></h1>
-- Aquí va el código que muestra el formulario -<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se añadirá]</a></destacar>
</center>
</body>
</html>
Dibujar el Formulario
Este código HTML mezclado con código Java crea un formulario cuya acción es "postear" los datos del
nuevo libro que hay en los campos de entrada a la página :
<form method="post" action="Insertar.jsp">
Luego se muestra una tabla; en la columna izquierda de la tabla se muestran los nombres de los campos;
la columna derecha contiene los campos de entrada:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"></td>
</tr>
</table>
Luego se define un campo oculto que simula la pulsación del botón submit cuando se pulsa la tecla
return:
<input name="pagemode" type="hidden" value="submit">
Luego se muestra el botón de envío del formulario etiquetado "Añadir el nuevo libro":
<input type="submit" value="Añadir el nuevo libro">
Cuando se pulsa el botón de envío, se pasan los parámetros isbn,
categoria, titulo y ubicacion a la página
editorial, autor,
Código Completo de la Página Form_Insertar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería: Insertar un nuevo libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería: Insertar un nuevo
libro</center></h1>
<form method="post" action="Insertar.jsp">
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"></td>
</tr>
</table>
<br>
<center>
<input name="pagemode" type="hidden" value="submit">
<input type="submit" value="Añadir el nuevo libro">
</center>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se añadirá]</a></destacar>
</center>
</body>
</html>
Insertar.jsp
Esta página muestra los campos que recibe del nuevo libro. Luego intenta añadir el nuevo libro a la base
de datos y muestra el éxito o el fracaso en el intento. En la parte inferior de la página hay un enlace a la
página Index.jsp.
Propósito de la Página Insertar.jsp
El propósito de esta página es producir una página Web con un tabla que muestre los parámetros del libro
que se le han pasado desde la página Form_Insertar.jsp; realmente realiza la actualización de la base de
datos; muestra si la base de datos se actualizó correctamente o no, y espera hasta que el usuario
seleccione el enlace de vuelta a Index.jsp. La siguiente figura muestra un ejemplo de la página
Insertar.jsp:
Aspecto de la Página Insertar.jsp
Este código HTML genera el aspecto de la página con un enlace a Index.jsp en la parte inferior de la
página:
<html>
<head>
<title>Librería -- Insertando un nuevo Libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Insertando un nuevo
Libro</center></h1>
-- aquí va el código para mostrar la tabla --- aquí va el código para actualizar la base de datos
y mostrar
el éxito o el fracaso de la operación -<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Mostrar la Tabla
Este código HTML mezclado con código Java muestra la tabla; en la columna izquierda se muestran los
nombres de los campos; la columna derecha contiene los datos del nuevo libro recuperados desde los
parámetros:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= request.getParameter ("isbn") %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= request.getParameter ("editorial")
%></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= request.getParameter ("autor") %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= request.getParameter ("categoria")
%></td>
</tr>
<tr>
<th>Título:</th>
<td><%= request.getParameter ("titulo") %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= request.getParameter ("ubicacion")
%></td>
</tr>
</table>
Actualizar la Base de Datos y Mostrar el Éxito o el Fracaso
Este código Java mezclado con código HTML recupera el ejemplar de libreria.LibrosBD
almacenado en el atributo BaseDatos de la aplicación por libreria.ContextListener:
LibrosBD librosBD =
(LibrosBD) application.getAttribute ("BaseDatos");
Esto construye un objeto Libro con los parámetros pasados desde Form_Insertar.jsp:
Libro libro = new Libro (
null,
request.getParameter ("isbn"),
request.getParameter ("editorial"),
request.getParameter ("autor"),
request.getParameter ("categoria"),
request.getParameter ("titulo"),
request.getParameter ("ubicacion")
);
Luego se añade el libro a la base de datos:
int rowsAffected = librosBD.insertarLibro (libro);
Si sólo se ve afectada una fila por la actualización de la base de datos se muestra el mensaje "Se ha
Añadido a la Base de Datos" en color verde, si no es así, se muestra el mensaje "No se Pudo Añadir el
Registro" en color rojo:
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha añadido a la
Base de Datos</font></h2>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se ha podido
Añadir el registro</font></h2>
</center>
<%
}
%>
Código Completo de la Página Insertar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Insertando un nuevo Libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Insertando un nuevo
Libro</center></h1>
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= request.getParameter ("isbn") %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= request.getParameter ("editorial")
%></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= request.getParameter ("autor") %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= request.getParameter ("categoria")
%></td>
</tr>
<tr>
<th>Título:</th>
<td><%= request.getParameter ("titulo") %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= request.getParameter ("ubicacion")
%></td>
</tr>
</table>
<%
LibrosBD librosBD = (LibrosBD)
application.getAttribute ("BaseDatos");
Libro libro = new Libro (
null,
request.getParameter ("isbn"),
request.getParameter ("editorial"),
request.getParameter ("autor"),
request.getParameter ("categoria"),
request.getParameter ("titulo"),
request.getParameter ("ubicacion")
);
int rowsAffected = librosBD.insertarLibro(libro);
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha añadido a la
Base de Datos</font></h2>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se ha podido
Añadir el registro</font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Borrar un Registro de la Base de Datos
Form_Borrar.jsp
Esta página lee el libro correspondiente al ID que ha recibido. Luego muestra los campos del libro en una
tabla para que podamos asegurarnos de que se va a borrar el libro correcto. En la parte inferior de la
página hay dos enlaces: uno para continuar con la solicitud de borrado del libro y otro para abortar la
solicitud.
Propósito de la Página Form_Borrar.jsp
El propósito de esta página es producir una página web con una tabla que muestre el libro que se va a
borrar. El usuario podría continuar el proceso de borrado seleccionado un enlace a la página Borrar.jsp o
abortar el proceso seleccionando un enlace de vuelta a Index.jsp. La siguiente imagen muestra un
ejemplo de la página Form_Borrar.jsp:
Aspecto de la Página Form_Borrar.jsp
Este código HTML crea el aspecto de la página con un enlace a Borrar.jsp etiquetado como "Borrar el
Libro nnn" y un enlace a Index.jsp etiquetado como "Volver a la Página Inicial [el libro no se
borrará]", en la parte inferior de la página:
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></center></h1>
-- aquí va el código para recuperar los datos del libro a
borrar -<br>
<center>
<destacar><a href="Borrar.jsp?id=<%= libro.getId
() %>">Borrar el libro
<%= request.getParameter ("id")
%></a></destacar>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo encontrar el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se borrará]</a></destacar>
</center>
</body>
</html>
Cuando se pulsa sobre el enlace "Borrar el Libro nnn" se le pasa el parámetro id al página Borrar.jsp.
Recuperar los Datos del libro a Borrar
Este código Java recupera el ejemplar de libreria.LibrosBD almacenado en el atributo
BaseDatos de la aplicación web por libreria.ContextListener:
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Luego obtiene de la base de datos el libro cuyo
Index.jsp:
id se ha pasado como parámetro a esta página desde
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
if (libro != null){
-- aquí va el código para mostrar la tabla -}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo encontrar el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
Mostrar la Tabla
Este código HTML mezclado con código Java muestra la tabla; en la columna izquierda se muestran los
nombres de los campos; la columna derecha contiene los datos del libro recuperados desde la base de
datos:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text" value="<%=
libro.getIsbn () %>"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"
value="<%= libro.getEditorial() %>"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"
value="<%= libro.getAutor () %>"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"
value="<%= libro.getCategoria () %>"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"
value="<%= libro.getTitulo () %>"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"
value="<%= libro.getUbicacion () %>"></td>
</tr>
</table>
Código Completo de la Página Form_Borrar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></center></h1>
<%
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
if (libro != null){
%>
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text" value="<%=
libro.getIsbn () %>"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"
value="<%= libro.getEditorial() %>"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"
value="<%= libro.getAutor () %>"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"
value="<%= libro.getCategoria () %>"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"
value="<%= libro.getTitulo () %>"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"
value="<%= libro.getUbicacion () %>"></td>
</tr>
</table>
<br>
<center>
<destacar><a href="Borrar.jsp?id=<%= libro.getId
() %>">Borrar el libro
<%= request.getParameter ("id")
%></a></destacar>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo encontrar el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se borrará]</a></destacar>
</center>
</body>
</html>
Borrar.jsp
Esta página lee el libro cuyo id se le ha pasado. Luego muestra los datos del libro en una tabla, intenta
borrar el libro de la base de datos, y muestra el éxito o el fracaso del intento.
Propósito de la Página Borrar.jsp
El propósito de esta página es producir una página web con una tabla que muestra el libro cuyo
parámetro id se ha pasado a esta página desde Form_Borrar.jsp; realmente realiza la actualización en la
base de datos; muestra si la base de datos se ha actualizado con éxito o no; y espera hasta que el
usuario seleccione el enlace de vuelta a la página Index.jsp. En la siguiente figura puedes ver un ejemplo
de la página Borrar.jsp:
Crear el Aspecto de la Página Borrar.jsp
Este código HTML genera el aspecto de la página con un enlace a Index.jsp en la parte inferior de la
página:
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Borrando un Libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></center></h1>
-- aquí se recuperan los datos del libro a borrar --- aquí se muestra la tabla de datos --- aquí va el código que actualiza la base de datos y
se
muestra el éxito o el fracaso de la operación -<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Recuperar los Datos del libro a Borrar
Este código Java recupera el ejemplar de libreria.LibrosBD almacenado en el atributo
BaseDatos de la aplicación web por libreria.ContextListener:
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Luego obtiene de la base de datos el libro cuyo
Form_Borrar.jsp:
id se ha pasado como parámetro a esta página desde
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
Mostar la Tabla
Este código HTML mezclado con código Java muestra la tabla; en la columna izquierda se muestran los
nombres de los campos; la columna derecha contiene los datos del libro a borrar recuperados de la base
de datos:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= libro.getIsbn() %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= libro.getEditorial() %></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= libro.getAutor() %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= libro.getCategoria() %></td>
</tr>
<tr>
<th>Título:</th>
<td><%= libro.getTitulo() %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= libro.getUbicacion() %></td>
</tr>
</table>
Actualizar la Base de Datos y Mostrar el Éxito o el Fracaso
Este código Java mezclado con código HTML borra el libro cuyo parámetro
parámetro:
id se le ha pasado como
int rowsAffected = librosBD.borrarLibro (request.getParameter
("id"));
Si sólo se ve afectada una fila en la actualización de la base de datos se muestra en verde el mensaje
"Se ha borrado el libro nnn"; si no es así, se muestra en rojo el mensaje "No se pudo borrar el libro
nnn":
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha Borrado el Libro
<%= request.getParameter ("id") %></font></h2>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo borrar el libro
<%= request.getParameter ("id") %></font></h2>
</center>
<%
}
Código Completo de la Página Borrar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Borrando un Libro</title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Borrando el Libro <%=
request.getParameter ("id") %></center></h1>
<%
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
if (libro != null){
%>
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= libro.getIsbn() %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= libro.getEditorial() %></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= libro.getAutor() %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= libro.getCategoria() %></td>
</tr>
<tr>
<th>Título:</th>
<td><%= libro.getTitulo() %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= libro.getUbicacion() %></td>
</tr>
</table>
<%
int rowsAffected = librosBD.borrarLibro
(request.getParameter ("id"));
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha borrado el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo borrar el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
}
else {
%>
<center>
<h2><font color="#cc0000">No se encontró el libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Modificar un Registro de la Base de Datos
Form_Modificar.jsp
Form_Modificar.jsp muestra un formulario HTML con los valores actuales del libro. También
tiene un botón para enviar el formulario y un enlace para abortar la solicitud.
Propósito de la Página Form_Modificar.jsp
El propósito de esta página es producir una página web que muestre los datos del libro a modificar. El
usuario podría o modificar los datos del formulario y enviar el formulario para su procesamiento
transfiriendo el control a la página Modificar.jsp o abortar el proceso seleccionando un enlace de vuelta a
la página Index.jsp. La siguiente imagen nos muestra un ejemplo de la página Form_Modificar.jsp:
Crear el Aspecto de la Página Form_Modificar.jsp
Este código HTML crea el aspecto de la página con un enlace en la parte inferior hacia la página Index.jsp
etiquetado como "Volver a la Página Inicial [el libro no se modificará]".
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Modificando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Modificando el Libro <%=
request.getParameter ("id") %></center></h1>
-- aquí va el código que recupera el libro a modificar --- aquí va el código para mostrar el formulario -<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se modificará]</a></destacar>
</center>
</body>
</html>
Recuperar los Datos del libro a Modificar
Este código Java recupera el ejemplar de libreria.LibrosBD almacenado en el atributo
BaseDatos de la aplicación web por libreria.ContextListener:
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Luego obtiene de la base de datos el libro cuyo
Index.jsp:
id se ha pasado como parámetro a esta página desde
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
Mostrar el Formulario
Este código HTML mezclado con código Java crea un formulario cuya acción es "postear" los datos
modificados del libro que hay en los campos de entrada a la página Modificar.jsp:
<form method="post" action="Modificar.jsp">
Uno de estos campos es un campo oculto que contiene el id del libro a modificar -- esto nos asegura que
el parámetro id pasado desde la página Index.jsp se pasa a la página Modificar.jsp.
<input name="id" type="hidden" value="<%= libro.getId () %>">
Luego se muestra una tabla; en la columna izquierda de la tabla se muestran los nombres de los campos;
la columna derecha contiene los campos de entrada pre-rellenos con los datos existentes:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text" value="<%=
libro.getIsbn () %>"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"
value="<%= libro.getEditorial() %>"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"
value="<%= libro.getAutor () %>"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"
value="<%= libro.getCategoria () %>"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"
value="<%= libro.getTitulo () %>"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"
value="<%= libro.getUbicacion () %>"></td>
</tr>
</table>
Luego se define un campo oculto que simula la pulsación del botón submit cuando se pulsa la tecla
return:
<input name="pagemode" type="hidden" value="submit">
Luego se muestra el botón de envío del formulario etiquetado "Modificar el Libro nnn":
<input align="center" type="submit" value="Modificar el Libro
<%= request.getParameter ("id")%>">
Cuando se pulsa el botón de envío, se pasan los parámetros isbn,
categoria, titulo y ubicacion a la página Modificar.jsp
editorial, autor,
Código Completo de la Página Form_Modificar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería -- Modificando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería -- Modificando el Libro <%=
request.getParameter ("id") %></center></h1>
<%
LibrosBD librosBD = (LibrosBD) application.getAttribute
("BaseDatos");
Libro libro = (Libro) librosBD.getLibro
(request.getParameter ("id"));
if (libro != null){
%>
<form method="post" action="Modificar.jsp">
<input name="id" type="hidden" value="<%= libro.getId
() %>">
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><input name="isbn" type="text" value="<%=
libro.getIsbn () %>"></td>
</tr>
<tr>
<th>Editorial:</th>
<td><input name="editorial" type="text"
value="<%= libro.getEditorial() %>"></td>
</tr>
<tr>
<th>Autor:</th>
<td><input name="autor" type="text"
value="<%= libro.getAutor () %>"></td>
</tr>
<tr>
<th>Categoría:</th>
<td><input name="categoria" type="text"
value="<%= libro.getCategoria () %>"></td>
</tr>
<tr>
<th>Título:</th>
<td><input name="titulo" type="text"
value="<%= libro.getTitulo () %>"></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><input name="ubicacion" type="text"
value="<%= libro.getUbicacion () %>"></td>
</tr>
</table>
<br>
<center>
<input name="pagemode" type="hidden"
value="submit">
<input align="center" type="submit"
value="Modificar el Libro
<%= request.getParameter ("id") %>">
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se pudo encontrar el
libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial
[el libro no se modificará]</a></destacar>
</center>
</body>
</html>
Modificar.jsp
Modificar.jsp muestra en una tabla los campos modificados del libro recibido. Luego intenta
modificar la base de datos y muestra el éxito o el fracaso del intento.
Propósito de la Página Modificar.jsp
El propósito de esta página es producir una página web con una tabla que muestre los parámetros del
libro pasados desde la página Form_Modificar.jsp; realmente realiza la actualización de la base de datos;
muestra si la base de datos se ha actualizado con éxito o no; y espera hasta que el usuario pulse el
enlace de vuelta a la página Index.jsp. Aquí tenemos un ejemplo de la página Modificar.jsp:
Aspecto de la Página Modificar.jsp
Este código HTML genera el aspecto de la página con un enlace a Index.jsp en la parte inferior de la
página:
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería: Modificando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería: Modificando el Libro
request.getParameter ("id") %></center></h1>
<%=
-- aquí va el código que muestra la tabla --- aquí va el código que actualiza la base de datos y
muestra
el éxito o el fracaso de la operación -<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Mostrar la Tabla
Este código HTML mezclado con código Java muestra la tabla; en la columna izquierda se muestran los
nombres de los campos; la columna derecha contiene los datos del libro recuperados de los parámetros:
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= request.getParameter ("isbn") %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= request.getParameter ("editorial")
%></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= request.getParameter ("autor") %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= request.getParameter ("categoria")
%></td>
</tr>
<tr>
<th>Título:</th>
<td><%= request.getParameter ("titulo") %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= request.getParameter ("ubicacion")
%></td>
</tr>
</table>
Actualizar la Base de Datos y Mostrar el Éxito o el Fracaso
Este código Java mezclado con código HTML recupera el ejemplar de libreria.LibrosBD
almacenado en el atributo BaseDatos de la aplicación por libreria.ContextListener:
LibrosBD librosBD = (LibrosBD)
application.getAttribute ("BaseDatos");
Esto construye un objeto Libro desde los parámetros pasados desde Form_Modificar.jsp:
Libro libro = new Libro
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
);
(
("id"),
("isbn"),
("editorial"),
("autor"),
("categoria"),
("titulo"),
("ubicacion")
Luego se modifica el libro en la base de datos:
int rowsAffected = librosBD.modificarLibro (libro);
Si sólo se ve afectada una fila por la actualización de la base de datos se muestra el mensaje "Se ha
modificado el Libro nnn" en color verde, si no es así, se muestra el mensaje "No se pudo modificar el
libro nnn" en color rojo:
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha modificado el Libro
<%= request.getParameter ("id") %></font></h2>
</center>
<%
}
else {
%>
<center>
<h2><font color="#cc0000">No se Pudo modificar el Libro
<%= request.getParameter ("id") %></font></h2>
</center>
<%
}
Código Completo de la Página Modificar.jsp
<%@ page language="java" import="java.util.*, libreria.*" %>
<html>
<head>
<title>Librería: Modificando el Libro <%=
request.getParameter ("id") %></title>
</head>
<body bgcolor="#ffffee">
<h1><center>Librería: Modificando el Libro
<%=
request.getParameter ("id") %></center></h1>
<table align="center" cellpadding="2" cellspacing="2"
border="1"
width="80%" bgcolor="#dddddd">
<tr>
<th>ISBN:</th>
<td><%= request.getParameter ("isbn") %></td>
</tr>
<tr>
<th>Editorial:</th>
<td><%= request.getParameter ("editorial")
%></td>
</tr>
<tr>
<th>Autor:</th>
<td><%= request.getParameter ("autor") %></td>
</tr>
<tr>
<th>Categoría:</th>
<td><%= request.getParameter ("categoria")
%></td>
</tr>
<tr>
<th>Título:</th>
<td><%= request.getParameter ("titulo") %></td>
</tr>
<tr>
<th>Ubicación:</th>
<td><%= request.getParameter ("ubicacion")
%></td>
</tr>
</table>
<%
LibrosBD librosBD = (LibrosBD)
application.getAttribute ("BaseDatos");
Libro libro = new Libro (
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
request.getParameter
("id"),
("isbn"),
("editorial"),
("autor"),
("categoria"),
("titulo"),
("ubicacion")
);
int rowsAffected = librosBD.modificarLibro(libro);
if (rowsAffected == 1) {
%>
<center>
<h2><font color="#00cc00">Se ha modificado el
Libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
else
{
%>
<center>
<h2><font color="#cc0000">No se pudo modificar el
Libro
<%= request.getParameter ("id")
%></font></h2>
</center>
<%
}
%>
<hr>
<center>
<destacar><a href="Index.jsp">Volver a la Página
Inicial</a></destacar>
</center>
</body>
</html>
Ficheros de Configuración
Ya estamos listos para crear los ficheros de configuración de nuestra aplicación Librería :
Libreria/WEB-INF/web.xml
Libreria/WEB-INF/web.xml es el descriptor de despliegue para la aplicación Web. Contiene
dos parámetros clave.
El parámetro listener identifica la clase Java del oyente libreria.ContextListener, al
que se llamará durante la arrancada y parada de la aplicación.
<listener>
<listener-class>listener.ContextListener</listener-class>
</listener>
El parámetro welcome-file-list controla el punto de entrada a la aplicación. El siguiente código
selecciona la página Index.jsp como único punto de entrada a la aplicación Librería:
<welcome-file-list>
<welcome-file>Index.jsp</welcome-file>
</welcome-file-list>
Propósito del Fichero web.xml
Es el descriptor de despliegue de la aplicación y está contenido en el directorio WEB-INF. Define varios
parámetros que son usados cuando se despliega la aplicación en el contenedor de Servlets/JSP Tomcat.
display-name
Configura el nombre de la aplicación web que se mostrará en los listados de Tomcat. La siguiente línea
selecciona este parámetro de la aplicación Libreria como "Aplicación Web de Libreria":
<display-name>Aplicación Web de Libreria</display-name>
description
Configura la descripción de la aplicación Web. La siguiente línea selecciona la descripción de la aplicación
Libreria como "Esta aplicación mantiene una base de datos de libros.":
<description>Esta aplicación mantiene una base de datos de
libros.</description>
listener
Configura la aplicación web para que se ejecute un oyente de contexto servlet cuando se arranque o se
pare la propia aplicación Web. Las siguiente líneas seleccionan que el oyente de contexto servlet de la
aplicación Librería sea libreria.ContextListener
<listener>
<listener-class>libreria.ContextListener</listener-class>
</listener>
welcome-file-list
Configura el punto de entrada a la aplicación web. Las preferencias por defecto para este parámetro se
seleccionan en el fichero conf/web.xml de Tomcat. Usando nuestro editor de texto, podemos echar
una mirada a la parte final de nuestro fichero conf/web.xml. Deberíamos ver algo como esto:
<!-- ==================== Default Welcome File List
===================== -->
<!-- When a request URI refers to a directory, the default
servlet looks -->
<!-- for a "welcome file" within that directory and, if present,
-->
<!-- to the corresponding resource URI for display. If no
welcome file
-->
<!-- is present, the default servlet either serves a directory
listing,
-->
<!-- or returns a 404 status, depending on how it is configured.
-->
<!--->
<!-- If you define welcome files in your own application's
web.xml
-->
<!-- deployment descriptor, that list *replaces* the list
configured
-->
<!-- here, so be sure that you include any of the default values
that
-->
<!-- you wish to include.
-->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>Home.jsp</welcome-file>
</welcome-file-list>
Es posible realizar cambios globales en nuestra configuración de Tomcat modificando el fichero
conf/web.xml, pero no recomiendo hacerlo. Es mucho mejor seleccionar las preferencias en el
parámetro welcome-file-list de la propia aplicación. Las siguiente líneas seleccionan el punto
de entrada de la aplicación Librería como Index.jsp
<welcome-file-list>
<welcome-file>Index.jsp</welcome-file>
</welcome-file-list>
Código Fuente Completo del Fichero web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Aplicación Web de Libreria</display-name>
<description>Esta aplicación mantiene una base de datos de
libros.</description>
<listener>
<listener-class>libreria.ContextListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>Index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Libreria.xml
Propósito del Fichero Libreria.xml
El fichero Libreria.xml contiene los detalles del "contexto" de la aplicación Libreria, es decir, los
parámetros que Tomcat usará cuando ejecute la aplicación, entre ellos la definición del DataSource a
utilizar, o el tipo de "Log" que va a tener esta aplicación, por ejemplo.
Este código define el path de contexto, el documento base, el nivel de depuración, el marcador de
recargable, y el marcador de contexto cruzado:
<Context path="/Libreria" docBase="Libreria" debug="1"
reloadable="true" crossContext="true">
... Aquí va la definición del Logger ...
... Aquí va la definición del DataSource ...
</Context>
Lo más importante a observar en este trozo de código son los atributos
veamos una breve descripción de cada uno de ellos.

path y docBase, pero
path indica el path que utilizaremos para acceder a nuestra aplicación una vez instalada en
Tomcat y formará parte de la URI para acceder a la aplicación desde nuestro navegador, por
ejemplo http://localhost:8080/Libreria en nuestro caso.

docBase también conocido como Raíz del Documento se utiliza para indicar el directorio
donde van a residir los ficheros de la aplicación cuyo contexto estamos configurando. Nota: Si
nuestra aplicación se encuentra empaquetada en un fichero WAR, en el atributo docBase
deberemos poner el path completo del fichero .war.

debug indica el nivel de log de esta aplicación, cuando mayor sea el número que pongamos
aquí, mayor será el nivel de detalle que veremos en los ficheros de log.

reloadable especifica si queremos que Tomcat monitorice cada cierto tiempo las clases de
esta aplicación para ver si han cambiado, pero debemos tener en cuenta que esta operación
consume muchos recursos y que puede ser muy útil para entornos de prueba pero puede ser
una mala idea para entornos de producción.

crossContext indica si queremos que las llamadas a
ServletContext.getContext() dentro de esta aplicación sobre otras aplicaciones
Web que se ejecuten en el mismo host virtual devuelvan siempre un request
dispatcher válido. En entornos de alta seguridad se puede seleccionar a false para
hacer que getContext() siempre devuelva null.
Hay muchos otros atributos del elemento context, podrás encontrar más información sobre ellos en el
fichero Context.html que viene en la documentación de Tomcat, en el directorio C:\Archivos
de programa\Apache Group\Tomcat 4.1\webapps\tomcat-docs\config\
Definición de Logger
Este código define un objeto Logger como una clase
org.apache.catalina.logger.FileLogger. En el directorio logs de Tomcat se creará
un fichero log llamado localhost_Libreria_log.YYYY-MM-DD.txt donde
YYYY-MM-DD es la fecha del log:
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="localhost_Libfreria_log." suffix=".txt"
timestamp="true"/>
Definición del DataSource
Este código define un Resource llamado jdbc/biblioteca como una clase
javax.sql.DataSource:
<Resource name="jdbc/biblioteca" auth="Container"
type="javax.sql.DataSource"/>
Este código define el ResourceParams llamado jdbc/biblioteca como una clase
org.apache.commons.dbcp.BasicDataSourceFactory:
<ResourceParams name="jdbc/biblioteca">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
... aquí van los parámetros de la base de datos ...
... aquí van los parámetros del Repositorio de Conexiones
...
</ResourceParams>
Parámetros de la Base de Datos
url
La URL de la base de datos url
=
jdbc:mysql://localhost:1306/biblioteca?autoReconnect=true. Por
defecto, MySQL cierra las conexión inactivas después de 8 horas. Si esto sucede, usando
autoReconnect=true se hará que Tomcat se reconecte automáticamente. Otras bases de datos
podrían funcionar de forma diferente:
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:1306/biblioteca?autoReconnect=true
</value>
</parameter>
driverClassName
El nombre de la clase del driver JDBC, driverClassName = org.gjt.mm.mysql.Driver
que es el nombre de la clase para el driver MySQL Connector/J JDBC .
<parameter>
<name>driverClassName</name>
<value>org.gjt.mm.mysql.Driver</value>
</parameter>
Nota: Recuerda que debes situar el fichero JAR
mysql-connector-java-2.0.14-bin.jar en el directorio ..\common\lib de
Tomcat.
username
El nombre de usuario para acceder a la base de datos MySQL
username = mysqlusername.
<parameter>
<name>username</name>
<value>mysqlusername</value>
</parameter>
password
password = mysqlpassword.
<parameter>
<name>password</name>
<value>mysqlpassword</value>
</parameter>
La password MySQL para acceder a la base de datos,
Parámetros del Repositorio de Conexiones
maxActive
El número máximo de conexiones en el repositorio, maxActive = 100. Seleccionamos
maxActive = 0 para que no haya limite. Debemos asegurarnos de configurar
max_connections lo suficientemente grande para manejar todas las conexiones a nuestra base de
datos.
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
maxIdle
El número máximo de conexiones inactivas a retener en el repositorio,
maxIdle = 0 para que no haya límite.
maxIdle = 30. Seleccionamos
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
maxWait
El tiempo máximo a esperar para obtener una conexión disponible [en milisegundos], maxWait =
10000. Seleccionamos maxWait = -1 para esperar indefinidamente. Si hay un timeout, se lanza una
Exception.
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
removeAbandoned
Si removeAbandoned
= true entonces cuando haya pocas conexiones disponibles en el
repositorio de conexiones se recuperará y reciclará cualquier conexión abandonada que se encuentre. El
valor por defecto es removeAbandoned = false.
<parameter>
<name>removeAbandoned</name>
<value>true</value>
</parameter>
removeAbandonedTimeout
El número de segundos que una conexión tiene que estar inactiva hasta que sea considerada
abandonada por el repositorio de conexiones. removeAbandonedTimeout = 300 es el tiempo
por defecto.
<parameter>
<name>removeAbandonedTimeout</name>
<value>300</value>
</parameter>
logAbandoned
Si logAbandoned = true el repositorio de conexiones guardará un seguimiento de pila del código
que abandonó un recurso de conexión.
<parameter>
<name>logAbandoned</name>
<value>true</value>
</parameter>
Código Fuente Completo del fichero Libreria.xml
<Context path="/Libreria" docBase="Libreria"
debug="1" reloadable="true" crossContext="true">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="localhost_Libreria_log." suffix=".txt"
timestamp="true"/>
<Resource name="jdbc/biblioteca" auth="Container"
type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/biblioteca">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:1306/biblioteca?autoReconnect=true
</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>org.gjt.mm.mysql.Driver</value>
</parameter>
<parameter>
<name>username</name>
<value>mysqlusername</value>
</parameter>
<parameter>
<name>password</name>
<value>mysqlpassword</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>removeAbandoned</name>
<value>true</value>
</parameter>
<parameter>
<name>removeAbandonedTimeout</name>
<value>300</value>
</parameter>
<parameter>
<name>logAbandoned</name>
<value>true</value>
</parameter>
</ResourceParams>
</Context>
Desplegar y Ejecutar la Aplicación
Desplegar la Aplicación
Descarga el fichero Libreria.zip que debe tener el siguiente contenido:
Descomprime el fichero Librería.zip en el directorio \webapps de tu instalación de Tomcat.
Aségurate de que en el directorio
Libreria.xml.
\webapps además del directorio \Libreria tienes el fichero
Este debería ser el aspecto del despliegue de tu aplicación:
C:\tomcat 4.1\
|
-> webapps\
|
|- Libreria.xml
-> Libreria\
|
|- Borrar.jsp
|- Form_Borrar.jsp
|- Form_Insertar.jsp
|- Form_Modificar.jsp
|- Index.jsp
|- Insertar.jsp
|- Modificar.jsp
-> WEB-INF\
|
|- web.xml
-> classes\
|
-> libreria\
|
|- ContextListener.class
|- Libro.class
|- LibosBD.class
Modifica el fichero Libreria.xml para adecuar la URL de la base de datos a la de tu máquina, además del
nombre de usuario y la password que utilizas para acceder a MySQL.
Ejecutar la Aplicación
Antes de ejecutar la aplicación debes asegurarte de que has seguido los pasos indicados en la sección
Crear la Tabla Libros en la Base de Datos.
Ahora solo queda arrancar Tomcat de la forma habitual, dirigir tu navegador favorito a la dirección
http://localhost:8080/Libreria/Index.jsp, y deberías ver la pantalla inicial de la
aplicación:
Ahora ya puedes empezar a insertar, borrar y modificar registros.