Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
Inicio > Tutoriales > Lenguajes orientados a objeto > Java > J2EE > Crear tu Primera Aplicación Web Real con Tomcat 4 y MySQL
-Tutoriales

Crear tu Primera Aplicación Web Real con Tomcat 4 y MySQL


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

    Luego se recupera el objeto LibrosBD desde el contexto y se cierra la base de datos:

        LibrosBD LibrosBD = (LibrosBD) servletContext.getAttribute ("BaseDatos");
        LibrosBD.close ();
    

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

    Luego se recupera el propio DataSource:

        DataSource dataSource = (DataSource) envContext.lookup ("jdbc/biblioteca");

    Y por último se recupera la conexión desde el DataSource:

        this.connection = dataSource.getConnection ();

    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 LibrosBD que esté esperando una conexión:

        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 getLibro

  • close

    close simplemente cierra la conexión:

        this.connection.close ();

. Código Fuente Completo de la clase LibrosBD

//
//  LibrosBD.java
//

package libreria;

import java.sql.*;
import java.util.*;
import javax.sql.*;
import 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 id = null;
    private String isbn = null;
    private String editorial = null;
    private String autor = null;
    private String categoria = null;
    private String titulo = null;
    private String 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;
    }

}
 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network