Proyecto de Integración
 

Aplicación web con JSF

Objetivo

El objetivo de esta sesión es utilizar la tecnología JSF para implementar un nuevo módulo de la aplicación, en concreto el módulo del administrador que se encarga de la gestión de libros (altas, bajas y modificaciones).

En concreto, las funcionalidades que debemos implementar son las siguientes:

  • Acceso del usuario. implementaremos una página de login desde la cual un bibliotecario podrá acceder a su menú.
  • Listado de libros. Una vez el bibliotecario se ha logado correctamente, accederemos a una vista donde tendremos el listado de libros. Se tratará de una tabla paginada por Ajax.
  • Alta de libros. Consistirá en un popup Ajax desde el cual podremos crear un libro nuevo (isbn, título, texto - , autor, número de páginas y portada). Todos los campos serán obligatorios.
  • Modificación de libros. Será una vista igual que la anterior, pero nos permitirá modificar un libro existente.
  • Visualización de libros. Mediante otro popup, veremos la información básica del libro. No habrá ningún input de texto. Si el libro no tiene carátula, se visualizará una imagen por defecto.
  • Eliminación de libros. En el caso que la situación del libro lo permita, se procederá al borrado del mismo. Usaremos mensajes flash para indicar si un libro se ha eliminado correctamente o no.

Partiremos de un proyecto nuevo con el arquetipo de richfaces 4.

A continuación mostramos las distintas pantallas que hay que implementar.

Pantalla 1 (acceso):

Acceso

Pantalla 2 (listado de libros):

Listado de libros

Pantalla 3 (modificación de libro):

Modificación de linro

Pantalla 4 (alta de libro):

Alta de libro

Pantalla 5 (detalle de libro):

Detalle

Pantalla 6 (borrado de libro):

Borrado

Puesta en común

Durante los primeros minutos de la sesión, haremos una puesta en común para determinar entre todos qué elementos formarán parte del modelo, cómo diseñaremos las vistas y cuántos controladores implementaremos.

Pistas

Subida de ficheros

Para la subida de ficheros, emplearemos el componente rich:fileUpload. Éste tiene un atributo llamado fileUploadListener, que debe relacionarse con un método de un objeto java (ejemplo: fileUploadListener="#{booksController.listener}")

Por su parte, el método del objeto java deberá guardarse el fichero subido, y no lo guardará hasta que se realice el guardado del libro:

@ManagedBean
@SessionScoped
public class BooksController implements Serializable{
	org.richfaces.model.UploadedFile uploadedFile;
	...

	public void listener(FileUploadEvent event) throws Exception {
		FacesContext facesContext = FacesContext.getCurrentInstance();		
		uploadedFile = event.getUploadedFile();
	}
	...
}

Para guardar el fichero, lo haremos en un directorio cualquiera de nuestro ordenador. Lo guardaremos cuando hayamos editado un libro existente o bien guardado uno nuevo.

private void saveFile(){
	File f = null;
	OutputStream os = null;

	try {
		f = new File("/home/especialista/Escritorio/" + currentBook.getIsbn() + ".jpg");
		if (f != null)
			f.delete();

		os = new FileOutputStream(f);
		IOUtils.copy(uploadedFile.getInputStream(), os);
	} catch (IOException e) {
		FacesContext.getCurrentInstance().addMessage(
			"uploadForm",
			new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"Fallo en la subida del fichero", null));

	}
}

Para el copiado de ficheros, se ha hecho uso de la librería org.apache.tomcat.util.http.fileupload.IOUtils. Ésta librería viene por defecto en el directorio lib de tomcat, con lo que deberemos añadir en nuestro fichero pom.xml una dependencia con la librería tomcat-coyote, versión 7.0.21, con ámbito provided

Creación de directorios virtuales

A la hora de obtener las imágenes para mostrarlas, éstas tienen que estar en una url accesible, y nuestra carpeta del ordenador no lo es. Es por este motivo que tenemos que crear un directorio virtual. Para ello, deberemos editar el fichero server.xml de nuestro tomcat, y añadir un nuevo contexto para nuestro host localhost:

<Context path="/jbib-images" docBase="/home/especialista/Escritorio" />

De esta manera, yendo a la url http://localhost:8080/jbib-images/[ISBN].jpg, ya podremos acceder a las carátulas de los libros que acabamos de subir.

Despliegue de la aplicación con cargo

En caso de querer desplegar la apliacación sobre apache tomcat en lugar de hacerlo sobre eclipse, deberemos añadir dos plug-ins al fichero pom.xml. El primero de ellos, maven clean, se encarga de borrar los ficheros y directorios que nostros le indiquemosm ya que por defecto, el comando mvn clean únicamente elimina el directorio target.

Por su parte, el plugin cargo es el responsable de desplegar nuestra aplicación en nuestro apache tomcat.

Deberemos introducir las siguientes líneas en la sección build/plugins de nuestro fichero pom.xml:

<!-- Maven clean -->
<plugin>
	<artifactId>maven-clean-plugin</artifactId>
	<version>2.4.1</version>
	<configuration>
		<filesets>
			<fileset>
				<directory>/opt/apache-tomcat-7.0.21/webapps</directory>
				<includes>
					<include>**/*jsf*</include>
				</includes>
				<followSymlinks>false</followSymlinks>
			</fileset>
			<fileset>
				<directory>/opt/apache-tomcat-7.0.21/webapps/jbib-web-jsf-2011</directory>
				<followSymlinks>false</followSymlinks>
			</fileset>
		</filesets>
	</configuration>
</plugin>

<!-- CARGO -->
<plugin>
	<groupId>org.codehaus.cargo</groupId>
	<artifactId>cargo-maven2-plugin</artifactId>

	<configuration>
		<wait>true</wait>
		<container>
			<containerId>tomcat7x</containerId>
			<type>installed</type>
			<home>/opt/apache-tomcat-7.0.21</home>
		</container>
		<configuration>
			<type>existing</type>
			<home>/opt/apache-tomcat-7.0.21</home>
		</configuration>
		<deployer>
			<type>installed</type>
			<deployables>
				<deployable>
					<groupId>org.especialistajee.jbib</groupId>
					<artifactId>jbib-web-jsf</artifactId>
					<type>war</type>
				</deployable>
			</deployables>
		</deployer>
	</configuration>
	<executions>
		<execution>
			<id>verify-deploy</id>
			<phase>install</phase>
			<goals>
				<goal>deployer-deploy</goal>
				<goal>start</goal>
			</goals>
		</execution>
		<execution>
			<id>clean-undeploy</id>
			<phase>pre-clean</phase>
			<goals>
				<goal>stop</goal>
			</goals>
		</execution>
	</executions>
</plugin>

Así, cuando hagamos mvn clean, se eliminará tanto el war como el directorio que contiene la aplicación. Cuando ejecutemos mvn install, se desplegará la aplicación en apache tomcat, y se levantará el servidor. Cuando hagamos ctrl+c, pararemos el servidor.

Conflictos con los jar

Durante el módulo de jsf, se ha visto la validación mediante hibernate-validator. También vimos que esta librería tenía dependencias con la versión 1.6.4 de la librería slf4j-api. Nuestro proyecto jsf-modelo ya incluye una dependencia con la versión 1.5.8 de la misma librería. Deberemos actualizar el pom de ese proyecto para que no haya conflicto de versiones.