Proyecto de Integración
 

Aplicación web con servlets y JSPs

Introducción

En esta sesión de integración vamos a refactorizar la aplicación web dinámica desarrollada en la sesión anterior separando la presentación (JSPs) del procesamiento (servlets). Además, añadiremos la funcionalidad de logout, y una serie de funcionalidades para la gestión de los libros por parte de los bibliotecarios (alta, edición y borrado). También mejoraremos la interfaz de las diferentes páginas mediante la introducción de una serie de elementos comunes a todas ellas (cabecera, menú de opciones, y pie).

Separación en servlets y JSPs

En la sesión anterior implementamos una aplicación web con una serie de servlets que se encargaban tanto de procesar la información necesaria como de generar un documento HTML en el que se presenta el resultado que se le mostrará al usuario. Hemos visto que si bien los servlets son adecuados para procesar la información, a la hora de generar la presentación es más conveniente utilizar JSPs. El patrón Modelo-Vista-Controlador (MVC) proporciona esta separación, dejando la vista (presentación) en los JSP separada del controlador y del modelo, que estarán implementados mediante servlets y otros componentes y clases Java.

En esta sesión vamos a refactorizar la aplicación web separando la lógica de negocio (modelo-controlador) y presentación (vista), de forma que los servlets simplemente procesarán la información necesaria, y proporcionarán el resultado de este procesamiento a un JSP que se encargará de generar la presentación de dicho resultado.

Vamos a comenzar viendo como separar en servlets y JSPs las funcionalidades de obtener el listado de libros y realizar reserva implementadas en la sesión anterior. Para ello crearemos dos JSPs llamados listadoLibros.jsp y datosLibro.jsp. El primero nos mostrará un listado de todos los libros (que habrá recibido desde el servlet SeleccionarLibroServlet como atributo de la petición) y junto a cada uno de ellos un enlace para ver los datos del libro. Al pulsar sobre este enlace se invocará el servlet PrepararReservaServlet que nos devolverá el contenido generado por datosLibro.jsp, lo cual nos mostrará una página con todos los datos del libro y su disponibilidad, permitiendo hacer una reserva si el libro no está reservado ya.

Nota
El listado de libros que estamos empleando se trata de un listado para usuarios alumnos y profesores, en él estos usuarios podrán reservar libros para ellos mismos. Más adelante en esta sesión haremos un listado para usuarios bibliotecarios en el que estos usuarios podrán dar libros de alta, editarlos, o borrarlos. No deberemos permitir que un bibliotecario pueda acceder al listado para usuarios, ni que un usuario pueda acceder al listado de bibliotecarios.

Esta es exactamente la misma funcionalidad que implementamos en la sesión anterior, pero en este caso, al realizar la presentación mediante JSPs, será mucho más cómodo y limpio definir la apariencia del documento web. Dado que lo deseable es separar lógica de negocio y presentación, será conveniente evitar introducir código Java directamente en los JSPs (scriptlets) siempre que sea posible. Para ello utilizaremos librerías de tags como JSTL.

Para poder utilizar JSTL, deberemos añadir la correspondiente dependencia al fichero POM:

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

Debemos tener en cuenta que los JSP que creemos no deben poder ser accedidos nunca directamente desde el navegador en el cliente, ya que necesitarán ser invocados por un servlet que procese la información necesaria y se la pase al JSP mediante un atributo de la petición. Para evitar que esto pudiese ocurrir, lo que haremos es guardar todos los JSP es un mismo directorio protegido mediante seguridad declarativa, al que nadie podrá acceder desde el lado del cliente (sólo se podrá acceder a él mediante include y forward desde dentro del servidor). Este directorio se llamará jsp e impediremos el acceso a su contenido introduciendo las siguientes etiquetas en el descriptor de despliegue (web.xml):

<security-constraint>
    <web-resource-collection>
        <web-resource-name>JSPs</web-resource-name>
        <url-pattern>/jsp/*</url-pattern>
    </web-resource-collection>
    <auth-constraint></auth-constraint>
</security-constraint>

Modificación de los servlets

Lo primero que deberemos hacer es modificar los servlets implementados en la sesión anterior, para que simplemente obtengan y procesen la información necesaria, pasándole el resultado generado a un JSP que será quien se encargue de realizar la presentación.

En primer lugar tenemos el servlet SeleccionarLibroServlet. Este servlet obtendrá el listado de todos los libros mediante el DAO, y le pasará un atributo listaLibros en el ámbito de la petición al JSP /jsp/biblio/listadoLibros.jsp o /jsp/usuario/listadoLibros.jsp, según si el usuario que ha entrado es de tipo bibliotecario o alumno/profesor, para así mostrar un listado adaptado a cada tipo de usuario.

Podemos observar que ahora el servlet ya no se encarga de imprimir el listado de libros, sino que simplemente hace un forward al JSP que se encargará de hacerlo. Lo mismo deberemos hacer con el servlet PrepararReservaServlet, que ya no deberá mostrar el formulario para introducir los datos de la reserva, sino que únicamente obtendrá los datos del libro y se los pasará al JSP datosLibro.jsp que mostrará los datos del libro, su disponibilidad, y en caso de no estar reservado un enlace para realizar la reserva. No hará falta introducir el usuario que realizará la reserva, ya que siempre se hará la reserva para el usuario autenticado actualmente (se obtiene mediante getRemoteUser).

Para que este servlet le pase los datos a los JSP hemos creado una serie de Transfer Objects que contienen los datos que queremos mostrar de cada objeto del dominio, ya procesados para que puedan mostrarse directamente y no sea necesario realizar ningún procesamiento complejo en el JSP. Introduciremos estos objetos LibroTo, OperacionTo, y UsuarioTo en el paquete org.especialistajee.jbib.model.to del proyecto jbib-comun.

Por último, nos queda el servlet RealizarReservaServlet. En este caso, si la reserva se realiza con éxito, se hará una redirección a la página con los datos del libro que acabamos de reservar, en la que ya aparecerá como reservado.

Destacamos también que en todos estos servlets, en caso de haber un error se hace un forward al JSP error.jsp. Este será un documento común que utilizaremos para mostrar cualquier error que se produzca en nuestra aplicación.

Nota
Dado que hemos refactorizado los servlets y que el comportamiento no es el mismo que en la sesión anterior, el caso de prueba PrepararReservaServletTest implementado en la sesión anterior ya no funcionará. Los casos de prueba deberían crearse a partir de la especificación final de los componentes. Dado que en próximas sesiones la capa web volverá a ser refactorizada, de momento para evitar problemas eliminaremos el caso de prueba de la aplicación.

Elementos comunes

Antes de escribir los JSPs necesarios para nuestra aplicación, vamos a aprovechar para introducir una serie de elementos comunes a todas las páginas del sitio web. Estos elementos son la cabecera, el menú de opciones y el pie. Los definiremos en ficheros jspf independientes, y los incluiremos en todas las páginas mediante la directiva include.

El fragmento para la cabecera estará dentro del directorio jsp creado anteriormente y se llamará cabecera.jspf.

Para el menú, crearemos el fragmento jsp/biblio/menu.jspf con las opciones para los bibliotecarios, y el fragmento jsp/usuario/menu.jspf con las opciones para los alumnos y profesores. Separaremos de esta forma, en directorios distintos, los JSP destinados a cada tipo de usuario.

Por último, introduciremos el fragmento del pie de página común jsp/pie.jspf.

Creación de los JSPs

Vamos a pasar ahora a crear los JSPs necesarios para las funcionalidades a implementar. En primer lugar crearemos el JSP para mostrar el listado de libros, tanto para bibliotecarios (jsp/biblio/listadoLibros.jsp), como para usuarios profesores y alumnos (jsp/usuario/listadoLibros.jsp), cada uno de ellos en el directorio correspondiente a su tipo de usuario.

En segundo lugar, dentro del directorio para usuarios profesores y alumnos (jsp/usuario) crearemos el JSP jsp/usuario/datosLibro.jsp (por el momento sólo vamos a crear esta pantalla para este tipo de usuarios, en próximas sesiones habrá que crear una similar para que los bibliotecarios puedas ver el estado de los libros y realizar préstamos).

Por último, introduciremos la página de error común (jsp/error.jsp) que será mostrada cada vez que ocurra un error en alguna operación.

Ahora ya podremos probar la aplicación, que deberá funcionar de forma similar a la anterior sesión, pero con la nueva interfaz que acabamos de crear.

Hoja de estilo

Podemos observar que los elementos de nuestros JSPs se encuentran organizados dentro de una serie de bloques div que representan los diferentes componentes de nuestros documentos web (cabecera, menú lateral, cuerpo, pie). Esta organización nos permitirá aplicar una hoja de estilo CSS para indicar el aspecto y la ubicación que tendrá cada uno de estos elementos. Podemos crear una hoja de estilo como el siguiente fichero /css/style.css dentro de la carpeta web de nuestra aplicación.

Listado de libros

Nuevas funcionalidades

Vamos ahora a añadir nuevas funcionalidades a la aplicación, siguiendo el mismo esquema de separación de responsabilidades entre servlets y JSPs que hemos visto para las anteriores. Concretamente, añadiremos la posibilidad de dar de alta nuevos libros, o editar o borrar los libros ya existentes. Todas estas operaciones serán exclusivas de los usuarios de tipo bibliotecario.

Mapa de navegación de la web

Deberemos implementar los siguientes servlets en el paquete org.especialistajee.jbib.web:

  • LibroDelServlet: Recibe un parámetro isbn con el ISBN del libro a borrar. Si el borrado se realiza de forma correcta, nos llevará de nuevo al listado de libros, donde veremos que el libro borrado ya no aparece en la lista.
  • LibroPreAddServlet: Nos mostrará el formulario para introducir los datos del libro a dar de alta. Este formulario deberemos crearlo en un JSP de nombre /jsp/biblio/altaLibro.jsp.
  • LibroAddServlet: Recibirá del formulario anterior los datos del libro a insertar, los introducirá en un objeto LibroDomain, y mediante el DAO los insertará en la base de datos. Una vez hecha la inserción, nos llevará a la página del listado de libros, donde aparecerá el nuevo libro.
  • LibroPreUpdateServlet: Recibe un parámetro isbn con el ISBN del libro a editar. Obtendrá los datos de este libro de la base de datos y se los pasará mediante un atributo libro en el ámbito de la petición al JSP modificaLibro.jsp que nos mostrará un formulario que tendrá como valores por defecto los datos actuales del libro.
  • LibroUpdateServlet: Este será el servlet invocado por el formulario anterior. Recibirá los nuevos datos del libro de dicho formulario y los actualizará en la base de datos. Una vez hecha la actualización nos llevará al listado principal donde veremos el libro modificado.

Si se produjese algún error en cualquiera de los servlets anteriores, se realizará un forward a error.jsp para mostrar la información del error producido.

Hemos visto que nuestro servlets necesitan dos JSPs con los formularios para el alta y la modificación de los libros. Estos JSPs son:

  • /jsp/biblio/altaLibro.jsp: Contiene un formulario en el que deberemos introducir los datos del nuevo libro (isbn, titulo, autor, y número de páginas). Este formulario llamará al servlet LibroAddServlet. Alta de libros
  • /jsp/biblio/modificaLibro.jsp: Contiene un formulario para editar los datos del libro. Recibirá en el ámbito de la petición un atributo libro con los datos actuales del libro a editar. Mostrará estos datos como valores por defecto en los campos del formulario (isbn, titulo, autor y número de páginas). En este caso es importante que el campo ISBN sea de sólo lectura, ya que este es el identificador del libro y no debe ser modificado. Respecto a la fecha de alta, no es necesario permitir que se edite este campo. Modificación de libros

Estos dos JSPs deberán tener todos los elementos comunes de la estructura de las páginas de nuestro sitio web (cabecera, menú y pie).

Por último, nos queda por implementar la funcionalidad de logout. Para ello crearemos un servlet LogoutServlet. Lo único que deberá realizar este servlet es invalidar la sesión actual y llevarnos de nuevo a la página principal para que nos vuelva a pedir los datos de login.

Resumen

Proyecto a entregar (1) Proyecto a entregar (2)

En esta sesión se deberá entregar el proyecto de integración actualizando el proyecto web con los siguientes puntos:

  • Añadir la dependencia de JSTL al fichero pom.xml de Maven.
  • Añadir seguridad declarativa para impedir el acceso al directorio jsp desde el cliente.
  • Añadir los fragmentos de JSP con los elementos comunes de todas las páginas: cabecera (jsp/cabecera.jspf), menú (jsp/biblio/menu.jspf, jsp/usuario/menu.jspf), y pie (jsp/pie.jspf).
  • Añadir los transfer objects LibroTo, OperacionTo y UsuarioTo al proyecto común.
  • Modificar los servlets SeleccionarLibroServlet, PrepararReservaServlet, y RealizarReservaServlet.
  • Añadir los servlets LibroDelServlet, LibroPreAddServlet, LibroAddServlet, LibroPreUpdateServlet, LibroUpdateServlet, y LogoutServlet.
  • Añadir los JSPs listadoLibros.jsp (para usuarios y bibliotecarios), datosLibro.jsp, altaLibro.jsp, modificaLibro.jsp, y error.jsp.
  • Añadir la hoja de estilo /css/style.css.

El plazo final de entrega será el jueves 16 de diciembre. Se realizará una sesión on-line de dudas el martes 14 de 19:00 a 21:00.