Upload
rudy
View
267
Download
0
Embed Size (px)
Citation preview
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
DESARROLLANDO UNA APLICACIÓN EMPRESARIAL
1. Introducción La presente guía busca describir paso a paso la creación de una aplicación empresarial utilizando JEE específicamente usando las siguientes tecnologías:
Java EE 7 como plataforma
GlassFish 3.1.2 Server, como servidor de despliegue de nuestra aplicacion
JSF 2.1 para el modulo web
JPA 2.0 para administrar las clases de persistencia
EJB 3.1 para escribir nuestros java beans empresariales que implementen la logica del negocio
EclipseLink 2.3 para ORM (Object Relational Mapping) para maperar nuestras relaciones(tablas) a clases entidad
MySQL Server 5.1 como DBMS (Database Management Server) El entorno de desarrollo utilizado es eclipse indigo R2. Como ejercicio de práctica se propone desarrollar una aplicación web que permita gestionar servicios on line para una biblioteca, ver el archivo adjunto con el script sql para mysql. Los pasos a seguir son los siguientes: ‐ Crear la aplicación web, utilizando la recomendación JSF2, es decir el uso de Plantillas Facelets. ‐ Crear la aplicación ejb, que contendrá las clases de entidad, los ejbs dao y negocio ‐ Crear y configurar el Datasource JDNI para Mysql en Glassfish ‐ Accesar a los java beans desde la aplicación JSF Configuración inicial de eclipse a. Crear un directorio de trabajo donde gestionaremos nuestros proyectos, en nuestro caso
D:\workspace b. Desempaquetar el archivo libraries.rar dentro del folder workspace c. Ejecutar eclipse y seleccionar el espacio de trabajo definido en el paso a. la vista es la siguiente:
d. Vamos a configurar el servidor de aplicaciones glassfish, para hacer esto hacemos clic en new
server wizard de la ficha server:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
e. Seleccionamos dentro del folder GlassFish, el adaptador GlassFish 3.1.2, y hacemos click en next.
f. Indicamos el directorio del servidor de aplicaciones (el instalador fue desempaquetado en c:\glassfish3).
g. Para que glassfish funcione adecuadamente, es necesario referenciar un jdk y no un jre, entonces hacer click en Installed JRE preferences y agregar al jdk como JRE instalado, como se muestra a continuación:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Seleccionar el JRE definido y click en finish
Cambiar Default JRE por el JDK seleccionado previamente
h. Hacer click en finish para terminar el proceso, el resultado es el siguiente
2. El sistema de plantillas Facelets. Se basa en el uso de las siguientes etiquetas:
ui:composition: envuelve un conjunto de componentes para ser reutilizados en otra página, es la etiqueta que:
o envuelve o puede envolver la plantilla. o se utiliza para hacer referencia a una plantilla.
Todo lo que quede fuera de la etiqueta ui:composition no será renderizado.
ui:define: define un contenido nombrado para ser insertado en una plantilla, su contenido es un conjunto de componentes y se identifica con un name. Ese conjunto de componentes será insertado en una etiqueta ui:insert con el mismo name.
ui:insert: declara un contenido nombrado que debe ser definido en otra página,
ui:decorate: es la etiqueta que sirve para hacer referencia a una plantilla, como la etiqueta ui:composition, solo que con ui:decorate lo definido antes y después de la etiqueta sí será renderizado,
ui:param: nos sirve para declarar parámetros y su valor en el uso de plantillas y componentes por composición,
ui:include: es una etiqueta que sirve para incluir en una página el contenido de otra, como si el contenido de esta última formase parte de la primera.
Siguiendo las recomendaciones de facelets, las plantillas las incluiremos dentro del directorio WEB‐INF/facelets/templates/, de modo que no sean visibles desde el contenedor web.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
1. Crear una aplicación web dinámica JSFLab04WEB,
En la opción configuration, seleccionar JavaServer Faces v2.0 Project, click en next‐>next, en la ventana web Module, seleccionar la casilla Genera web.xml deployment descriptor, y click en next.
Ahora hay que seleccionar la librearia JSF a utilizar, y seleccionamos finish, de acuerdo a la siguiente:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Nuestro proyecto se ha creado, ahora procederemos a configurar nuestra plantilla. Ahora, probaremos si JSF esta trabajando apropiadamente. Para hacerlo crearemos nuestra página prueba. Hay que recordar que las paginas web en una aplicación web dinámica son creadas en el folder WebContent o en sus subfolderes. Las páginas fuera de este folder no serán publicadas por el servidor y no se tendrán acceso desde la web. Entoces, click derecho en el folder WebContent en el explorador de proyectos y click en new‐>XHTML Page. Escribir prueba en el campo nombre y click en finish, como se muestra en la figura:
Abrir el archivo prueba.xhtml y agregar el siguiente mensaje en el body:
Click derecho en el archivo prueba.xhtml y click en Run As ‐> Run on Server y veremos el mensaje de exito en el browser, pero dese cuenta que todavia se muestra en el browser /faces/test.xhtml. Necesitamos que se muestre test.jsf. Esto se logra haciendo pequeños cambios en nuestro archivo web.xml
<?xml version="1.0" encoding="ISO‐8859‐1" ?><!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http‐equiv="Content‐Type" content="text/html; charset=ISO‐8859‐1" /> <title>Insert title here</title> </head> <body> <div style="background‐color: navy; with:100%;color:white"> JSF ESTA FUNCIONANDO CORRECTAMENTE </div> </body> </html>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Abra el archivo web.xml y haga que parezca como lo siguiente. Encontrara el archivo web.xml bajo /WebContent/WEB‐INF/web.xml
En Servlet mapping, se ha especificado que el patron url sera *.jsf. Nuestra pagina de bienvenida sera index.jsf, ahora click derecho en la pagina prueba.xhtml otra vez y click en Run As ‐> Run on Server y veremos que la url ahora se esta mostrando con test.jsf como se puede ver en la figura:
La mejor forma de trabajar con facelets es creando una plantilla, entonces, a continuación crearemos las paginas header, footer y composition. En JSF 2.0, los facelts se crean usando plantillas y composicion de paginas. Veamos como se usan las plantillas para crear facelets. Siguiendo las recomendaciones de facelets, las plantillas las incluiremos dentro del directorio /WebContent/WEB‐INF/facelets/templates/, de modo que no sean visibles desde el contenedor web. Procedamos a crear dichos folders, haciendo click derecho en WEB‐INF y click New ‐> Folder. Click derecho en el folder templates y click en New ‐> XHTML Page. Si la opción XHTML no se muestra aqui, hacer click en New ‐> Other, y bajo GlassFish seleccionar XHTML Page como se muestra en la figura:
<?xml version="1.0" encoding="UTF‐8"?> <web‐app xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web‐app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web‐app_3_0.xsd" id="WebApp_ID" version="3.0"> <display‐name>JSFLab04WEB</display‐name> <welcome‐file‐list> <welcome‐file>index.jsf</welcome‐file> </welcome‐file‐list> <servlet> <servlet‐name>Faces Servlet</servlet‐name> <servlet‐class>javax.faces.webapp.FacesServlet</servlet‐class> <load‐on‐startup>1</load‐on‐startup> </servlet> <servlet‐mapping> <servlet‐name>Faces Servlet</servlet‐name> <url‐pattern>/faces/*</url‐pattern> <url‐pattern>*.jsf</url‐pattern> </servlet‐mapping> <context‐param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description> <param‐name>javax.faces.PROJECT_STATE</param‐name> <param‐value>Production</param‐value> </context‐param> <context‐param> <param‐name>javax.servlet.jsp.jstl.fmt.localizationContext</param‐name> <param‐value>resources.application</param‐value> </context‐param> <listener> <listener‐class>com.sun.faces.config.ConfigureListener</listener‐class> </listener> </web‐app>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Colocar el nombre del archivo a template y click Next. En la siguiente ventana seleccionar New Facelet Template. como se muestra en la figura y hacer click en Finish.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Click derecho en el folder templates para crear el archivo header.xhtml seleccionando New Facelet Header como se muestra en la siguiente figura, y click en finish:
Siga los mismos pasos para crear el archivo footer.xhtml en el folder templates seleccionando New Facelet Footer como se muestra en la figura:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Abra el archivo template.xhtml, elimine los comentarios y haga lo siguiente:
Esta pagina template se utilizara para crear nuestras paginas xhtml. Pueden ver que hemos creado áreas para la cabecera (header), el pie (footer) usando la etiqueta de insercion <ui>. Observe que hemos creado área de contenido usando la etiqueta de insercion <ui>, pero no incluimos la pagina. Nuestras páginas de composición estarán aquí, como lo veremos mas adelante. Ahora procederemos a crear nuestras páginas de composición mediante esta plantilla (template.xhtml).
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <head> <title><ui:insert name="title">Default title</ui:insert></title> </head> <body> <div id="header"> <ui:insert name="header"> <ui:include src="header.xhtml"/> </ui:insert> </div> <div id="content"> <ui:insert name="content"> </ui:insert> </div> <div id="footer"> <ui:insert name="footer"> <ui:include src="footer.xhtml"/> </ui:insert> </div> </body> </html>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Click derecho en el folder WebContent y crear una nueva página compuesta llamada index.xhtml seleccionando New Composition Facelet Page como se muestra a continuación:
Abre tu página compuesta y elimina las etiquetas header y footer, estos cargaran de la página plantilla. Coloca la ruta de pagina plantilla en la etiqueta <ui:composition>. Agrega los mensajes apropiados en el área de contenido. Tu página se vera así:
Abre las páginas header y footer y agrega los mensajes apropiados. Ejecuta tu proyecto. Finalmente el explorador de proyecto y la ventana del navegador se verán como sigue:
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="/WEB‐INF/facelets/templates/template.xhtml"> <ui:define name="content"> <p>Esta parte conforma la pagina compuesta.</p> </ui:define> </ui:composition> </html>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
A continuación mejoraremos nuestro proyecto, agregando una hoja de estilos, para ello crearemos un el folder resources y dentro de este el folder css (donde crearemos nuestro archivo con los estilos principales) y el folder images, para almacenar las imágenes que necesitemos, tal como se muestra a continuacion:
Click derecho en el folder css y crear un archivo con extensión css llamado default.css, y agregar el siguiente código:
No olvide eliminar los estilos de los archivos header.xhtml y footer.xhtml y modificar el archivo template.xhtml con el siguiente código <h:head> <h:outputStylesheet name="default.css" library="css"/> <title><ui:insert name="title">Sistema de Control Bibliotecario</ui:insert></title> </h:head>
#header{ float: left; font‐size:32px; width: 100%; line‐height:48px; margin: 0px auto; background‐color: navy; color: white; text‐align: center; } #content{ background‐color: #04859d; } #footer{ float: left; width: 100%; background‐color: navy; color:white; text‐align: center; }
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
3. Configurando la conexión a la base de datos desde eclipse Para realizar esta etapa del tutorial, primero se debe tener instalado el DBMS MySQL Server y tener ubicado el conector correspondiente, el conector se puede obtener de la dirección: http://www.mysql.com/downloads/connector/j/, utilizaremos la versión 5.1.20 (la ultima disponible cuando se realizo este tutorial). Instalado ya MYSQL, abrir una consola MySQL y crear la base de datos BIBLIOTECADB
Cierre la consola. En el Data Source Explorer de Eclipse, click derecho en Database Connections y hacer click en new, seleccionar el connection profile MySQL y colocar el nombre del perfil de conexión a bibliotecadb luego hacer click en next, tal como se muestra en la figura:
En la ventana New Connection Profile, hacer click en el botón New Driver Definition en la ventana Available drivers templates, seleccionar MySQL JDBC Driver versión 5.1. luego click en la ficha JAR List, seleccionar el conector registrado por default y eliminarlo (Remove JAR/Zip), luego hacer click en el boton Add JAR/Zip, como se muestra a continuación:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
A través del explorador seleccionar el conector correspondiente mysql‐connector‐java‐5.1.20‐bin y seleccionarlo.
Hacer click en abrir, luego click en Ok de la ventana Driver definition. Con el conector ya configurado, procedemos a registrar las propiedades de la conexión a la base de datos, ingresando el nombre de la base de datos, la url, el usuario y password, para verificar que existe conexión, hacer click en el botón Test Connection, posteriormente, hacer click en finish, según como se detalla en la siguiente figura:
En el Data Source Explorer se puede observar la conexión realizada:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Para crear las tablas en la base de datos, ejecutar el script sql proporcionado, desde la perspectiva Database Development, a través del SQL scrapbook
4. Creando la aplicación EJB y las clases entidad A continuación detallaremos los pasos necesarios para crear nuestra aplicación EJB, a través de la cual se tendrá acceso a los datos desde nuestra aplicación web previamente desarrollada. Con la perspectiva Java EE activa, desde el menú File‐>new, seleccionar EJB Project, en dicha ventana ingresar el nombre de nuestro proyecto JSFLab04EJB, verificar que el Target runtime sea GlassFish 3.1.2, y hacer click en el botón Modify de Configuration, se abre la ventana Project Faces, donde agregaremos a nuestro proyecto la Faceta JPA, que nos permitirá utilizar la API de persistencia JPA, tal como se muestra a continuación:
Luego hacemos click en Ok, y en la ventana EJB Project hacemos click en next‐>next, abriéndose la ventana JPA Facet, configurándolo según lo mostrado, y para finalizar haciendo click en finish, tal como se muestra a continuación:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Podemos observar que se ha creado el proyecto
En el folder ejbModule hacemos click derecho en new y seleccionamos JPA Entities from Tables en la ventana Select Tables, seleccionamos las tablas y hacemos click en next:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
En la siguiente ventana verificamos la correcta asociación de tablas y presionamos next, en la ventana Customize Default Entity Generation configuramos key generator y Package y hacemos click en finish, tal como se muestra a continuacion:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Eclipse creara clases entidad por cada tabla, el resultado es el siguiente:
Ahora que hemos creado nuestras clases entidad, crearemos la lógica del negocio, en el que iremos creando nuestros java beans llamados EJBs. Antes de crear nuestros EJBs, crearemos un nombre de origen de datos JNDI.
5. Creando y configurando un origen de datos JNDI para MySQL en GlassFish 3.1.2 Server En esta parte crearemos un nombre de origen de datos JNDI para que trabaje con nuestros EJBs(Enterprise Java Beans). Lo primero que hay que hacer es copiar el archivo mysql‐connector‐java‐5.1.20‐bin.jar en el folder lib del servidor GlassFish. La ruta de acceso debe tener este aspecto: glassfish3\glassfish\lib. Reiniciar eclipse y hacer lo siguiente: En la parte inferior en la ficha Servers, en la ventana de eclipse click derecho en GlassFish 3.1.2, seleccionar GlassFish ‐> View Admin Console. (Recuerde que GlassFish debe estar iniciado)
Esto abrirá la consola de administracion en la ventana del navegador. Una vez abierto, en el panel del lado izquierdo bajo Resources, click en JDBC y en JDBC Connection Pools. En el lado derecho click en el botón new.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
En la ventana New JDBC Connection Pool, ingresar el Pool Name MYSQL_Pool, seleccionar javax.sql.DataSource como Resource Type, y MySQL como Database Driver Vendor. En la esquina superior izquierda hacer click en el boton next.
En el listado de propiedades adicionales, encuentra las siguientes propiedades y completar como sigue: Url: jdbc:mysql://:3306/bibliotecadb URL: jdbc:mysql://:3306/bibliotecadb Port: 3306 DatabaseName: el nombre de tu base de datos (en nuestro caso bibliotecadb) ServerName: localhost User: root Password: el password de MySQL Click en finish y veremos el pool creado en la lista, haga click y luego click en el botón ping para probar si el pool ha sido creado satisfactoriamente. Sino fuese el caso, revisar las propiedades otra vez.
Debajo de JDBC click en JDBC Resources, click en new. En la ventana New JDBC Resource seleccionar MYSQL_Pool desde Pool Name, y colocar el nombre JNDI jdbc/bibliotecadsn; no olvide hacer click en Ok en la esquina superior derecha.
Ahora que ya tenemos creado nuestro DataSource, configuraremos nuestro archivo persistence.xml para accesar a esta fuente de datos. Abre tu persistence.xml, que se encuentra dentro del folder JPA Content.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
En las opciones de navegacion del archive xml, click en Connection y realizar los cambios que se muestran en la siguiente figura:
Grabar los cambios y verificar que el archive xml en la ficha Source sea similar a:
En el código se ha especificado una unidad de persistencia llamada JSFLab04EJB. Como tipo de transacción utilizaremos JTA (Java Transaction API). Como JTA DataSource, se ha especificado jdbc/bibliotecadsn, que nosotros creamos con anterioridad, y finalmente tenemos especificado nuestras clases entidad que han sido mapeadas de la base de datos.
6. Creando la lógica de la aplicación Los EJB que conforman la capa modelo y son responsables de la lógica de la aplicación se reparten en dos paquetes (ejb.dao, ejb.negocio). La distinción entre ambos paquetes se debe a su orientación. El paquete ejb.dao contiene EJB orientados principalmente a dar soporte a los casos de uso típicos en las tareas de mantenimiento de una Base de Datos (operaciones CRUD [create, read, update, delete]: acceso, altas, bajas y modificaciones). El paquete ejb.negocio ofrece soporte a casos de uso un poco más específicos de más alto nivel que hacen uso los EJBs del anterior paquete. En ambos casos se ha seguido la misma convención de nombrado:
XxxxDAO.java ó XxxxService.java: Clase de implementación del EJB (@Stateless o @Stateful)
XxxxDAOLocal.java ó XxxxServiceLocal.java: Interfaz local del EJB (@Local)
XxxxDAORemote.java ó XxxxServiceRemote.java: Interfaz remoto del EJB (@Remote) Por simplicidad ambas interfaces (local y remota) coinciden, aunque no suele ser lo habitual.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Paquete ejb.dao El paquete ejb.dao provee de EJBs para implementar las operaciones básicas sobre las entidades que componen la aplicación. La funcionalidad ofrecida por este conjunto de EJB se corresponde de un modo genérico con el patrón DAO (Data Access Object), que oculta las tecnologías y el modo de acceso a los datos, delegando, en este caso, las operaciones concretas en el EntityManager de JPA. En este caso se ha definido un DAO genérico (GenericDAO) con operaciones básicas (crear, buscar por ID, actualizar, borrar y otros métodos comunes). De esta clase heredan los demás EJBs (y sus interfaces local y remoto), añadiendo nuevas operaciones, usualmente operaciones de búsqueda específicas. Como ejemplo implementaremos las clases GenericDAO y UsuarioDAO, las otras clases seguirán la misma estructura. GenericDAO: Operaciones básicas sobre las entidades (independientes de la Entidad concreta) UsuarioDAO: Operaciones sobre Usuarios. Paquete ejb.negocio En este paquete se incluyen EJBs que implementan caso de uso específicos de la aplicación. En general proveen de operaciones de mayor complejidad que las del paquete ejb.dao, responsabilizándose de coordinar las invocaciones de otros EJBs encargados del manejo de datos. En este caso se implementa un patrón Service Facade puro. GestorUsuariosService: EJB sin estado responsable de la autenticación y de la gestión de usuarios (creación de nuevos Usuarios, junto con la alta de su respectivo Usuario, y modificación de los datos del usuario) Ahora crearemos un clase interfaz GenericDAOInterface y posterioremente la clase GenericDAO, haciendo click derecho en el paquete ejbModule de nuestro proyecto EJB y click en New ‐> Interface, ingresar el nombre del paquete 'ejb.beans’, el nombre de interfaz GenericDAOInterface y luego click en finish.
El código de la interfaz GenericDAOInterface, será:
package ejb.dao; import java.util.List; public interface GenericDAOInterface<T> { public void create(T entity); public void delete(T entity); public T update(T entity) ; public T findByID(Object entityID); public List<T> findAll(); public int count(); } Creada la interfaz GenericDAOInterface procedemos a crear la clase GenericDAO, haciendo click derecho en el paquete ejb.dao, new‐> Class, luego ingresar el nombre de la clase GenericDAO, en la
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
opción Interfaces agregar la interfaz ejb.dao.GenericDAOInterface<T>, se finaliza haciendo click en finish.
El código fuente de la clase GenericDAO, es: package ejb.dao; import java.lang.reflect.ParameterizedType; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.criteria.CriteriaQuery; public class GenericDAO<T> implements GenericDAOInterface<T> { private final static String UNIT_NAME = "JSFLab04EJB"; //Nombre de la Unidad de persistencia @PersistenceContext(unitName = UNIT_NAME) protected EntityManager em; @Override public void create(T entity) { em.persist(entity); //crea una tupla en la bd } @Override public void delete(T entity) { T entityToBeRemoved = em.merge(entity); em.remove(entityToBeRemoved); //elimina una tupla en la bd } @Override public T update(T entity) { return em.merge(entity); // Actualiza los datos de "entidad" en su correspondiente tupla BD } @SuppressWarnings("unchecked") @Override public T findByID(Object entityID) { Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; // Identifica la clase real de las entidades gestionada por este objeto (T.class) return em.find(entityClass, entityID); //retorna un objeto que coincide con el ID }
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
@Override @SuppressWarnings({ "unchecked", "rawtypes" }) public List<T> findAll() { //Devuelve la lista de objetos T Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; CriteriaQuery cq = em.getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); return em.createQuery(cq).getResultList(); } @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public int count() { //devuelve la cantidad de objetos almacenados en la bd Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; javax.persistence.criteria.CriteriaQuery cq = em.getCriteriaBuilder().createQuery(); javax.persistence.criteria.Root<T> rt = cq.from(entityClass); cq.select(em.getCriteriaBuilder().count(rt)); javax.persistence.Query q = em.createQuery(cq); return ((Long) q.getSingleResult()).intValue(); } }
Ahora crearemos nuestros EJBs. Para crear un enterprise java bean, click derecho en el paquete ejbModule‐>ejb.dao de nuestro proyecto EJB y click New ‐> Other. De la lista de asistentes seleccionar Session Bean (EJB 3.x) bajo EJB y hacer click en Next.
Ingresar el nombre de la clase UsuarioDAO y click en el botón browser de Superclass, buscar la clase GenericDAO que pertenezca al paquete ejb.dao y seleccionarlo. Luego seleccionar 'State type' como 'Stateless' tambien check en Local para crear una interfaz local y hacer click en finish.
Se ha creado la clase UsuarioDAO y su interfaz UsuarioDAOLocal, ahora indicaremos las operaciones a implementar en la interfaz, ingresando el siguiente código tanto en la interfaz como en la clase: Código para la interfaz UsuarioDAOLocal
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
package ejb.dao; import javax.ejb.Local; import entidades.Usuario; @Local public interface UsuarioDAOLocal extends GenericDAOInterface<Usuario>{ public Usuario buscarPorLogin(String login); } Código para la clase UsuarioDAO package ejb.dao; import java.util.List; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.persistence.Query; import entidades.Usuario; /** * Session Bean implementation class UsuarioDAO */ @Stateless @LocalBean public class UsuarioDAO extends GenericDAO<Usuario> implements UsuarioDAOLocal{ @SuppressWarnings("unchecked") public Usuario buscarPorLogin(String login) { Query q = em.createQuery("SELECT object(u) FROM Usuario AS u " + " WHERE u.loginUsuario = :login"); q.setParameter("login", login); List<Usuario> resultados = q.getResultList(); if (resultados ==null) { return null; // No encontrado } else if (resultados.size() != 1){ return null; // No encontrado } else { return resultados.get(0); // Devuelve el encontrado } } }
De manera similar implementar para las otras clases entidad. Ahora crearemos la clase GestorUsuariosService y su interfaz dentro de un paquete ejb.negocio, como se muestra:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Código para la interfaz GestorUsuariosServiceLocal package ejb.negocio; import javax.ejb.Local; import entidades.Usuario; @Local public interface GestorUsuariosServiceLocal { boolean autenticarUsuario(String login, String password); Usuario actualizarPassword(int idUsuario, String password); boolean existeUsuario(String login); Usuario actualizarUltimoAcceso(int idUsuario); } Código para la clase GestorUsuariosService package ejb.negocio; import java.util.Calendar; import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; import ejb.dao.UsuarioDAOLocal; import entidades.Usuario; /** * Session Bean implementation class GestorUsuariosService */ @Stateless @LocalBean public class GestorUsuariosService implements GestorUsuariosServiceLocal { @EJB UsuarioDAOLocal usuarioDAO; @Override public boolean autenticarUsuario(String login, String password) { Usuario usuario; boolean resultado = false; usuario = usuarioDAO.buscarPorLogin(login); if (usuario != null) { if (usuario.getPasswordUsuario().equals(password)) { resultado = true; } } return resultado; } @Override public Usuario actualizarPassword(int idUsuario, String password) { Usuario usuario = usuarioDAO.findByID(idUsuario); usuario.setPasswordUsuario(password); return usuarioDAO.update(usuario); } @Override public boolean existeUsuario(String login) { return (usuarioDAO.buscarPorLogin(login) != null); } @Override public Usuario actualizarUltimoAcceso(int idUsuario) { Usuario usuario = usuarioDAO.findByID(idUsuario); usuario.setUltimoAcceso(Calendar.getInstance().getTime()); //tiempo actual return usuarioDAO.update(usuario); } }
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Nuestro proyecto EJB quedaría como se muestra a continuacion:
7. Implementando un CRUD con JSF 2.0 en una pagina web En los puntos previos hemos creado nuestra lógica del negocio a través de EJBs, ahora vamos a crear nuestra aplicación web. Como ejemplo se creara un facelet mantenimientoUsuarios.xhtml que nos permita listar los usuarios registrados; además también crearemos otros facelets que nos permitan modificar y agregar nuevos usuarios. Primero agregaremos un botón en la página index.xhtml, que nos permita llamar al facelet mantenimientoUsuarios.xhtml, el código es:
<ui:define name="content"> <h:form> <h1> Opciones</h1> <h:commandButton action="usuarios/mantenimientoUsuarios" value="Mantenimiento de Usuarios" /> </h:form> </ui:define>
Al ejecutar nuestro proyecto, se vería así:
Ahora en nuestro proyecto web crearemos nuestra lógica web usando beans administrados (managed bean) que nos permitan accesar a la lógica del negocio desde los facelets. Por lo tanto, hacer click derecho en el paquete src y crear una nueva clase haciendo click en New ‐> class. Dar el nombre del paquete web.beans, y el nombre de la clase UsuarioManagedBean, y click finish.
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
El código para la clase UsuarioManagedBean, es:
package web.beans; import java.util.List; import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import ejb.dao.UsuarioDAOLocal; import entidades.Usuario; @ManagedBean (name = "usuarioMB") @SessionScoped public class UsuarioManagedBean { private Usuario usuario = new Usuario(); @EJB UsuarioDAOLocal servicioUsuarios; public Usuario getUsuario() { return usuario; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } public List<Usuario> listarUsuarios() { return servicioUsuarios.findAll(); } public String nuevoUsuario( ) { servicioUsuarios.create(usuario); return "mantenimientoUsuarios"; } public void reset() { usuario = new Usuario(); }
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
public void eliminarUsuario(int idUsuario) { Usuario us = servicioUsuarios.findByID(idUsuario); servicioUsuarios.delete(us); } public String actualizarUsuario(){ servicioUsuarios.update(usuario); return ("mantenimientoUsuarios"); //retorna el nombre del facelet para la navegacion } }
En el código anterior hemos inyectado nuestro EJB UsuarioDAOLocal usando la anotación @EJB. Esto permite acceder a los EJBs directamente en nuestra clase ManagedBean. Como se puede ver hemos llamado a distintos métodos directamente de la interfaz UsuarioDAOLocal.java. En los pasos siguientes crearemos nuestra página web para dar mantenimiento a los usuarios. Click derecho en el folder WebContent y crear un folder usuarios luego crear una página compuesta mantenimientoUsuarios.xhtml, dentro de WebContent‐>usuarios y colocar el código siguiente:
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="../WEB‐INF/facelets/templates/template.xhtml"> <ui:define name="content"> <f:view> <h:form> <h1><h:outputText value="Listado de Usuarios"/></h1> <h:dataTable value="#{usuarioMB.listarUsuarios()}" var="item"> <h:column> <f:facet name="header"> <h:outputText value="IdUsuario"/> </f:facet> <h:outputText value="#{item.idUsuario}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Nombre"/> </f:facet> <h:outputText value="#{item.nombreUsuario}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Apellidos"/> </f:facet> <h:outputText value="#{item.apellidoUsuario}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Direccion"/> </f:facet> <h:outputText value="#{item.direccionUsuario}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Correo Electronico"/> </f:facet> <h:outputText value="#{item.emailUsuario}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value=""/> </f:facet> <h:commandButton action="editarUsuario" value="Editar"> <f:setPropertyActionListener target="#{usuarioMB.usuario}" value="#{item}" /> </h:commandButton> <h:outputText value=" "/>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
<h:commandButton action="#{usuarioMB.eliminarUsuario(item.idUsuario)}" value="Eliminar"/> </h:column> </h:dataTable> <br/> <h:commandButton action="crearUsuario" value="Nuevo Usuario"> </h:commandButton> </h:form> </f:view> </ui:define> </ui:composition> </html>
Ahora vamos a probar nuestra aplicación, para ello tenemos que crear un proyecto empresarial, que estará compuesto de los proyectos JSFLab04EJB y JSFLab04WEB, haciendo click en el menú File ‐> New ‐> Enterprise Application Project y asignar el nombre JSFLab04EAR y hacer click en Next.
Luego seleccionar los proyectos depedientes de este proyecto y click en Finish:
Ahora procedemos a ejecutar el proyecto empresarial el resultado obtenido seria:
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
Y al hacer click en el botón Mantenimiento de Usuarios, el resultado obtenido seria:
Completamos la funcionalidad de la aplicación implementado los facelets crearUsuario.xhtml y editarUsuario.xhtml, creándolos dentro del folde usuarios El código fuente para el facelet crearUsuario.xhtml será:
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="../WEB‐INF/facelets/templates/template.xhtml"> <ui:define name="content"> <f:view> <h2>Registro de Nuevos Usuarios</h2> <h:form id="form"> <h:panelGrid columns="3"> <h:outputLabel for="nombre">Nombre</h:outputLabel> <h:inputText id="nombre" value="#{usuarioMB.usuario.nombreUsuario}" required="true"> <f:ajax event="blur" render="nombreMessage" /> </h:inputText> <h:message id="nombreMessage" for="nombre" /> <h:outputLabel for="apellidos">Apellidos</h:outputLabel> <h:inputText id="apellidos" value="#{usuarioMB.usuario.apellidoUsuario}" required="true"> <f:ajax event="blur" render="apellidosMessage" /> </h:inputText> <h:message id="apellidosMessage" for="apellidos" /> <h:outputLabel for="direccion">Direccion</h:outputLabel> <h:inputText id="direccion" value="#{usuarioMB.usuario.direccionUsuario}" required="true"> <f:ajax event="blur" render="direccionMessage" /> </h:inputText> <h:message id="direccionMessage" for="direccion" /> <h:outputLabel for="email">Email</h:outputLabel> <h:inputText id="email" value="#{usuarioMB.usuario.emailUsuario}" required="true"> <f:ajax event="blur" render="emailMessage" /> </h:inputText> <h:message id="emailMessage" for="email" /> <h:outputLabel for="telefono">Telefono</h:outputLabel> <h:inputText id="telefono" value="#{usuarioMB.usuario.telefonoUsuario}" required="true"> <f:ajax event="blur" render="telefonoMessage" /> </h:inputText> <h:message id="telefonoMessage" for="telefono" /> <h:outputLabel for="password">Password</h:outputLabel> <h:inputSecret id="password" value="#{usuarioMB.usuario.passwordUsuario}" required="true" redisplay="true"> <f:ajax event="blur" render="passwordMessage" /> </h:inputSecret>
Departamento de Sistemas, Estadistica e Informatica Facultad de Ingeniería ‐ UNC
Ingeniería de Software © 2012 Edwin Valencia Castillo
<h:message id="passwordMessage" for="password" /> <h:panelGroup /> </h:panelGrid> <h:commandButton value="Grabar" action="#{usuarioMB.nuevoUsuario()}" > </h:commandButton> <h:commandButton value="reset" action="#{usuarioMB.reset}" > <f:ajax execute="@form" render="@form" /> </h:commandButton> <h:messages globalOnly="true" layout="table" /> </h:form> </f:view> </ui:define> </ui:composition> </html>
El código para el facelet editarUsuario.xhtml será:
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="../WEB‐INF/facelets/templates/template.xhtml"> <ui:define name="content"> <f:view> <h2>Editar Usuario</h2> <h:form id="form"> <h:panelGrid columns="3"> <h:outputLabel for="nombre">Nombre</h:outputLabel> <h:inputText id="nombre" value="#{usuarioMB.usuario.nombreUsuario}" required="true"> <f:ajax event="blur" render="nombreMessage" /> </h:inputText> <h:message id="nombreMessage" for="nombre" /> <h:outputLabel for="apellidos">Apellidos</h:outputLabel> <h:inputText id="apellidos" value="#{usuarioMB.usuario.apellidoUsuario}" required="true"> <f:ajax event="blur" render="apellidosMessage" /> </h:inputText> <h:message id="apellidosMessage" for="apellidos" /> <h:outputLabel for="direccion">Direccion</h:outputLabel> <h:inputText id="direccion" value="#{usuarioMB.usuario.direccionUsuario}" required="true"> <f:ajax event="blur" render="direccionMessage" /> </h:inputText> <h:message id="direccionMessage" for="direccion" /> <h:outputLabel for="email">Email</h:outputLabel> <h:inputText id="email" value="#{usuarioMB.usuario.emailUsuario}" required="true"> <f:ajax event="blur" render="emailMessage" /> </h:inputText> <h:message id="emailMessage" for="email" /> <h:outputLabel for="telefono">Telefono</h:outputLabel> <h:inputText id="telefono" value="#{usuarioMB.usuario.telefonoUsuario}" required="true"> <f:ajax event="blur" render="telefonoMessage" /> </h:inputText> <h:message id="telefonoMessage" for="telefono" /> <h:outputLabel for="password">Password</h:outputLabel> <h:inputSecret id="password" value="#{usuarioMB.usuario.passwordUsuario}" required="true" redisplay="true"> <f:ajax event="blur" render="passwordMessage" /> </h:inputSecret> <h:message id="passwordMessage" for="password" /> <h:panelGroup /> </h:panelGrid> <h:commandButton value="Actualizar" action="#{usuarioMB.actualizarUsuario()}" > </h:commandButton> <h:commandButton value="reset" action="#{usuarioMB.reset}" > <f:ajax execute="@form" render="@form" /> </h:commandButton> <h:messages globalOnly="true" layout="table" /> </h:form> </f:view> </ui:define> </ui:composition> </html>