Tag : JavaServer Faces 2.0 CRUD

JavaServer Faces 2.0 CRUD

Mostraremos como hacer una pequeño ejemplo Web en JavaServer Faces 2.0 que permita crear, leer, actualizar y borrar registros en una base datos de MySQL.  Todo esto con la ayuda de las herramientas de NetBeans.

En este ejemplo haremos uso de las siguientes tecnologías:

  • JavaServer Faces (JSF) 2.0
  • Java Persistence API (JPA) 2.0
  • Enterprise JavaBeans (EJB) 3.1

Será necesario tener instalado el siguiente software:

  1. NetBeans IDE 7.0, o superior.
  2. Java Development Kit (JDK) 6, o superior.
  3. GlassFish Application Server v3, o superior.
  4. MySQL 5.x o superior
También puedes ver el video donde hacemos este mismo ejemplo saltándonos algunos pasos:


Para este ejemplo seguiremos los siguientes pasos:

  1. Crear la base de datos
  2. Examinar la estructura de base de datos
  3. Crear el proyecto Web
  4. Generar las clases de entidad desde la base de datos
  5. Generar los JSF desde las clases de entidad
  6. Explorando la aplicación

Crear la base de datos

Si ya has creado una base de datos en MySQL antes, quizá sabes también que hay mas de una forma o herramienta para hacerlo. Aqui te mostraremos como hacerlo desde la sección de servicios de NetBeans. Si abres la ventana de Servicios de NetBeans y después das click en Databases, podrás ver que existe predefinido un item solo para registrar un servidor de base de datos de MySQL, para iniciar el servicio en NetBeans, debes dar click derecho y despues en propiedades para completar los datos de conexión.

En tu caso los datos de acceso serán los que hayas definido cuando instalaste MySQL y pon la IP del equipo donde lo tengas instalado (típicamente es localhost o 127.0.0.1).

Cuando hayas teminado de llenar los datos para conectarte, simplemente da click derecho al mouse y despues en conectar.

Ya que te hayas conectado es posible crear una nueva base de datos en las opciones del submenu con click derecho:

Yo he creado una BD llamada: ejemploJSF20.

Al crear la base de datos, también se crea una conexión a la misma y es posible ejecutar comandos de SQL sobre la nueva base.

Para este ejemplo te proporcionamos dos scripts de SQL que te permitirán crear las tablas necesarias y llenarlas de datos de ejemplo para ejecutar el ejercicio adecuadamente.

Descargar script de MySQL: script

Examinar la estructura de base de datos Una vez que has ejecutado los scripts puedes explorar la base de datos para ver las tablas y el contenido que has creado. No olvides refrescar el estado de la conexión.

Bien, ya se han creado y poblado las tablas que necesitaremos.

La siguiente es una descripción de las tablas:

Tabla Descripción Características
CLIENTE Cliente de la agencia de consultoria No-generada, llave primaria compuesta (cuyos campos no constituyen una llave foranea)
CONSULTOR Un empleado de la agencia de consultoría que los clientes pueden contratar sobre una base contractual Incluye un campo resumen de tipo LONG VARCHAR
ESTATUS_CONSULTOR El estado de un consultor con la agencia de consultoría (por ejemplo, activos e inactivos son estados posibles) No-generada, llave primaria de tipo CHAR
RECLUTADOR Un empleado de la agencia consultora responsable de la conexión de los clientes y consultores
PROYECTO Un proyecto de los clientes con consultores de la agencia. No-generada, llave compuesta que incluye dos campos constituyendo una llave foranea para la tabla CLIENTE
FACTURABLE Un conjunto de horas trabajadas por un consultor en un proyecto, para los que la consultoría de proyectos facture al cliente en cuestión Incluye un campo artefacto de tipo CLOB
DIRECCION Dirección de Facturación
CONSULTOR_PROYECTO Tabla de Union que indica que consultores están asignados a que proyectos. Referencia-cruzada PROYECTO y CONSULTOR, los primeros tienen una clave primaria compuesta

La base de datos incluye una variedad de relaciones. Al crear clases de entidad de una base de datos, el IDE genera automáticamente las propiedades del tipo de Java adecuada basada en el tipo de SQL de las columnas. La siguiente tabla describe las relaciones de entidades para consultar la base de datos. (Relaciones inversas no se muestran)

Entidad Entidad Relacionada Información Descripción
CLIENTE RECLUTADOR nullable con edición manual; nullable uno-a-muchos si no. CLIENTE tiene muchos RECLUTADORES y RECULTADOR tiene cero o un CLIENTE (si no es editado manualmente)
CLIENTE DIRECCION non-nullable uno-a-uno CLIENTE tiene una DIRECCION y DIRECCION tiene cero o un CLIENTE
CLIENTE PROYECTO non-nullable uno-a-muchos; en una entidad Proyecto, el valor del campo cliente es parte de la llave primaria del Proyecto CLIENTE tiene muchos PROYECTOs y un PROYECTO tiene un CLIENTE
CONSULTOR PROYECTO muchos-a-muchos CONSULTOR tiene muchos PROYECTOs y PROYECTO tiene muchos CONSULTORES
CONSULTOR FACTURABLE non-nullable uno-a-muchos CONSULTOR tiene muchas FACTURABLEs y FACTURABLE tiene un CONSULTOR
ESTATUS_CONSULTOR CONSULTOR non-nullable uno-a-muchos ESTATUS_CONSULTOR tiene muchos CONSULTOREs y CONSULTOR tiene un ESTATUS_CONSULTOR
CONSULTOR RECLUTADOR nullable uno-a-muchos CONSULTOR tiene cero o un RECLUTADOR y RECLUTADOR tiene muchos CONSULTOREs
FACTURABLE PROYECTO non-nullable uno-a-muchos FACTURABLE tiene un PROYECTO y PROYECTO tiene muchos FACTURABLEs

Crear el proyecto Web

Ahora es momento de crear el proyecto Web utilizando el framework de JSF

  1. En el menú superior debes elegir: File->New Project (Ctrl-Shift-N).
  2. Selecciona Web Application de la categoría Java Web. Da click en Next.
  3. Escribe el nombre del proyecto y la hubicación, para este ejemplo usamos el nombre ejemploJSF2. Despues da click en el botón Next
  4. Selecciona el servidor GlassFish v3 y especifica la versión de Java EE con la Java EE 6 Web. Da un click en Next.
  5. En el panel de Frameworks, selecciona la opción de JavaServer Faces. Da click en Finish.

Cuando das click en Finish, el IDE genera el proyecto de tipo Web y abre index.xhtml en el editor.

Generar las clases de entidad desde la base de datos

1.- Despues de conectar la IDE a la base de datos, usaremos el asistente o wizard que obtiene entidades de la base de datos para generar de forma rápida las clases basadas en las tablas de la base de datos. El IDE puede generar clases de entidad de cada tabla que selecciones, y puede generar además, cualquier clase de entidades para relacionar las tablas.

2.- En la ventana de Proyectos, dando un click derecho al nodo de ejemploJSF2, y seleccionando New->Entity Classes from Database. (Si esta opción no está en la lista, elija Otra. Despues, en el Wizard de File, seleccione la categoría de Persistence, después Entity Classes from Database).


3.- Selecciona New Data Source from the Data Source, arrastra la lista para abrir la ventana de dialogo Create Data Source.

4.- Selecciona el nombre JNDI jdbc/ejemploJSF2 y selecciona jdbc:mysql://localhost:3306/ejemploJSF2 como la base de conexión.

5.- Las tablas de la base de datos deberán aparecer en la lista de Tablas disponibles.

6.- Da click en el boton Add All para seleccionar todas las tablas. Da click en Next.

7.- Escribe jpa.ent como nombre de paquete. Asegurate que el checkbox para generar consultas con nombre se ha seleccionado “Generate Named Query Annotations”.

8.- Puedes dejar los valores por default que vienen, da click en Finish y el IDE comenzará a crear las entidades en el paquete que especificamos.

Al utilizar el asistente para crear clases de entidad de una base de datos, el IDE examina las relaciones entre las tablas de base de datos. En la ventana de Proyectos, si se expande el nodo del paquete jpa.ent, se puede ver que el IDE genera una clase de entidad para cada tabla, excepto para la tabla de PROYECTO_CONSULTOR. El IDE no ha creado una clase de entidad para PROYECTO_CONSULTOR porque la tabla es una union de tablas.

El IDE también ha generado dos clases adicionales para las tablas con llaves primarias compuestas: CLIENTE y PROYECTO. Las clases de llave primaria de estas tablas (ClientePK.java y ProyectoPK.java) tiene PK concatenado.

Si nos fijamos en el código generado para las clases de entidad se puede ver que el asistente añade anotaciones @GeneratedValue a los campos auto generados de ID y las anotaciones @Basic (optional = “false”) a algunos de los campos en las clases de entidad. En base a las anotaciones @Basic (optional = “false”), las páginas que el asistente JSF Pages from Entity Classes genera, incluyen un código con controles para prevenir las violaciónes para columnas con valor no nulo.

Generando los JSF desde las clases de entidad

Ahora que hemos creado las clases de entidad, haremos la interfaz web para mostrar y modificar los datos. Usaremos el asistente JSF Pages from Entity Classes para generar páginas JavaServer Faces. El código generado por el asistente o wizzard se basa en las anotaciones de persistencia contenidas en las clases de entidad.

Para cada clase de entidad, el asistente genera lo siguiente:

  • Un bean de sesión sin estado para la creación, lectura, modificación y eliminación de entidades.
  • Un bean JSF manejador, session-scoped,
  • Un directorio que contiene cuatro archivos Facelets para realizar de CRUD (Create.xhtml, Edit.xhtml, List.xhtml, y View.xhtml)
  • Clases que serán usadas por los beans JSF manejadores (JsfUtil, PaginationHelper)
  • Un paquete de propiedades para los mensajes localizados, y una entrada correspondiente en el archivo de configuración del proyecto (faces-config.xml se crea si no existe)
  • Archivos Web auxiliares, incluyendo una hoja de estilos predeterminada para renderear componentes y un archivo plantilla para Facelets.

Para generar las páginas JSF

1.- En la ventana Proyectos, haz click en el nodo del proyecto y elije New> JSF Pages from Entity Classes para abrir el asistente. (Si esta opción no aparece en la lista, elije Otro. Luego, en el asistente de archivos, selecciona la categoría JavaServer Faces, a continuación, JSF Pages from Entity Classes)


La lista de clases de entidad disponibles muestra las siete clases de entidad que figuran en el proyecto. El cuadro no muestra las clases ClientPK.java y ProjectPK.java.

2.- Haz click en Agregar todo para mover todas las clases a la Selección de cuadro de clases de entidad.

Haz click en Siguiente.

3.- En el paso 3 del asistente, Generamos páginas JSF y clases, escribe jpa.con para el paquete controlador de JPA y jsf.con para las clases de respaldo de los  JSFs.

4.- Escribe jsf para el folder donde estarán los JSFs

5.- Escribe ‘/Bundle’ en el campo “Localization Bundle Name”. Esto generará un paquete llamado recursos en donde estará el archivo Bundle.properties (Si se deja en blanco, el paquete de propiedades, se creará en el paquete default del proyecto.)

Para que el IDE se adapte mejor a tus convenciones de proyecto, puedes personalizar los archivos generados por el asistente. Haz click en el enlace Customize Template para modificar el archivo de plantillas utilizadas por el asistente.

5.- En general, puedes acceder y realizar cambios en todas las plantillas gestionada por el IDE usando el Administrador de plantillas (Tools > Templates).

Si expandes el nodo Web Pages, veras que el IDE genera una carpeta para cada una de las clases de entidad. Cada carpeta contiene los archivos de Create.xhtml, Edit.xhtml, List.xhtml y View.xhtml. El IDE también modificó el archivo index.xhtml insertando los enlaces a cada una de las páginas List.xhtml.

Cada bean JSF manejador es específico para los cuatro archivos Facelets correspondientes e incluye el código que invoca métodos en el bean de sesión adecuado.

Expande el nodo o folder de recursos para localizar la hoja de estilos jsfcrud.css que fue generado por el asistente. Si abres la página de la aplicación de bienvenida (index.xhtml) o el archivo Facelets de plantilla (template.xhtml) en el editor, verás que contiene una referencia a la hoja de estilos.

El archivo Facelets de plantilla es usado por cada uno de los cuatro archivos de Facelets para cada clase de entidad.

<h:outputStylesheet name="css/jsfcrud.css"/>

Si expandes los paquetes fuente del nodo se pueden ver los beans controladores de JPA, los bean manejadores de JSF, clases de utilidad, y archivos de propiedades que el asistente genera.

El asistente también genera un archivo de configuración de Faces (faces-config.xml) para registrar la ubicación del paquete de propiedades. Si expandes el nodo de archivos de configuración y abres faces-config.xml en el editor de XML, se puede ver que se incluye la siguiente entrada.

<application>
<resource-bundle>
<base-name>recursos/Bundle</base-name>
<var>bundle</var>
</resource-bundle>
</application>

Además, si exploras el paquete de recursos, encontrarás en el archivo de Bundle.properties, mensajes para el idioma del cliente por defecto. Los mensajes se derivan de las propiedades de la entidad de clase.

Para agregar un paquete de propiedades nuevas haz click en el archivo Bundle.properties y selecciona Customize. La ventana de diálogo Customizer te permite añadir nuevas configuraciones regionales para la aplicación.

Explorando la Aplicación

Ahora que el proyecto contiene las clases de entidad, los EJBs de sesión para controlar las clases de entidad, y JSF de front-end para mostrar y modificar la base de datos, intenta ejecutar el proyecto para ver los resultados.

En seguida se presentan algunos ejercicios opcionales que te ayudarán a familiarizarte con la aplicación, así como las características y funcionalidad que el IDE.

  • Examinar el proyecto terminado
  • Rellenar la base de datos con una secuencia de comandos de SQL
  • Explorar el Editor de Facelets
  • Exploración de la integridad de base de datos, con validación de campo
  • Edición de clases de la entidad

Examinar el proyecto terminado

1.- Para ejecutar el proyecto, haz click derecho en el nodo del proyecto en la ventana de proyectos y selecciona Run o Ejecutar.

Como puedes ver, nuevos enlaces se han añadido a la página de bienvenida (index.xhtml) con ayuda del asistente. Los enlaces creados se ofrecen como puntos de entrada a las páginas de Facelets que proporcionan la funcionalidad CRUD sobre la base de datos de la aplicación.

2.- Haz click en el vínculo Show All Consultor Items. Tomando en cuenta el código anterior, puedes ver que la página de destino es /consultor/List (En JSF 2.0, la extensión de archivo se infiere debido a la navegación implícita)

Si no olvidaste ejecutar el segundo script de SQL que se encarga de rellenar algunas tablas podrás ver algunos datos, para el caso de Consultores se muestra al menos un registro.

Como podrás ver, las ociones: crear, ver, editar y elimimar son generadas también por el asistente.

Explorar en el Editor de páginas Facelets

1.- Abra el archivo /consultor/List.xhtml en el editor. Línea 8 indica que la página se basa en el archivo Facelets template.xhtml para crearse.

2.- Busca el archivo template.xhtml.

3.- En plantilla se usa la etiqueta

<ui:insert>

para insertar contenido como el título y el cuerpo.

4.- Regresa al archivo List.xhtml (presiona Ctrl-Tab).  La etiqueta ui:define ui:define se utiliza para definir el contenido que se aplicarán al título de la plantilla y el cuerpo. Este patrón se utiliza para todos los cuatro archivos de Facelets (Create.xhtml, Edit.xhtml, List.xhtml, y View.xhtml) generados para cada clase de entidad.

5.- Coloca el cursor sobre cualquiera de las expresiones EL que usan los mensajes localizados contenida en el archivo Bundle.properties. Presiona Ctrl-Espacio para ver el mensaje localizado.

6.- Desplazate hasta el final del archivo y busca el código para el enlace Crear nuevo consultor (Línea 92). Este es el siguiente:

<h:commandLink action="#{consultorController.prepareCreate}" value="#{bundle.ListConsultorCreateLink}"/>

7.- Presiona Ctrl-Espacio en la acción del atributo commandLink para invocar el pop-up de la documentación.

El atributo action indica el método que controla la solicitud cuando se hace click en el enlace en el navegador. La siguiente documentación se proporciona:

MethodExpression representa la acción de la aplicación que se invoca cuando este componente es activado por el usuario. La expresión debe evaluar un método público que no toma parámetros y devuelve un objeto (el método toString () se llama para obtener el resultado lógico), que se pasa a NavigationHandler para esta aplicación.

En otras palabras, el valor de acción generalmente se refiere a un método en un bean JSF manejador que se evalúa a una cadena. La cadena es utilizada por NavigationHandler de JSF de remitir la solicitud a la vista apropiada. Podrás verificar esto en los siguientes pasos.

8.- Pon el cursor en consultorController y presione Ctrl-Space. La funcionalidad de completado del editor, indica que consultorController es un bean JSF controlador.

9.- Mueve el cursor a prepareCreate y pulsa Ctrl-Espacio. La función de completado de código enumera los métodos que figuran en el bean ConsultorController.

Explorando la integridad de base de datos con validación de campos

1.- Desde la página con la Lista de Consultores en el navegador, haz click en ‘Create New Consultor”. Deberá aparecer el formulario de creación de Consultores.

2.- Ingresa los siguientes datos en el formulario. Por el momento, dejar los campos RecruiterId y StatusId en blanco.

Campo Valor
ConsultorId 2
Email

jorge.listo@consultores.com&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;

Password jorge.listo
TarifaPor 75
TarifaPorHoraFacturable 110
FechaContratacion 07/22/2008
Resumen Soy el mejor ¡Contratame!
ReclutadorId
EstatusId

3.- Haz click en Guardar. Al hacerlo, un error de validación se marca para el campo EstatusId.

¿Por qué ocurrió esto? Reexamina el diagrama entidad-relación de la base de datos. Como se indica en la tabla de relaciones, CONSULTOR y ESTATUS_CONSULTOR comparten una relación no-nula, uno-a-muchos. Por lo tanto, cada entrada en la tabla CONSULTOR debe contener una referencia a una entrada en la tabla ESTATUS_CONSULTOR. Esto se denota por la clave externa consultor_fk_estatus_consultor que une las dos tablas.


4.- Para superar el error de validación, selecciona entity.ConsultorStatus [EstatusId = A] de la lista de EstatusId desplegable.

Nota: Puedes dejar el campo en blanco RecruiterId. Como se indica en el diagrama de relación, la relación entre CONSULTOR y la tabla de RECLUTADOR puede ser nula, uno-a-muchos, lo que significa que las entradas de CONSULTOR no necesitan estar asociadas con una entrada en RECLUTADOR.

5.- Haz click en Guardar. Aparecerá un mensaje indicando que la entrada consultor se ha guardado correctamente. Si haces click en Show All Consultor Items, verás la entrada que se ha guardado en la tabla.


En general, las páginas Facelets generadas, proveen de errores para facilitar la entrada que el usuario introduce:

* Campos vacíos para campos no-nulas.
* Modificaciones a los datos que no puede ser alterados (por ejemplo, las claves primarias).
* Introducción de datos que no son del tipo correcto.
* Modificaciones a los datos cuando la vista de un usuario ya no está sincronizada con la base de datos.

Editando las Clases de Entidad

En la seccion anterior vimos cómo la lista desplegable de EstatusId no era muy amigable. Quizá ya te has dado cuenta de que el texto que se muestra para cada elemento es una representación en cadena de cada entidad EstatusConsultor encontrada.

Veremos cómo usar completamente el editor de código, documentación y apoyo a la navegación como conclusión. También modificaremos el mensaje que se envía al usuario para que sea más amigable.

1.- Abre el archivo /consultor/Create.xhtml. Este es el formulario Create New Consultor que acabas de ver en el navegador. Desplazate hacia abajo para ver el código del la lista desplegable EstatusId (en negrita a continuación).

<h:selectOneMenu id="reclutadorId" value="#{consultorController.selected.reclutadorId}" title="#{bundle.CreateConsultorTitle_reclutadorId}" >
<f:selectItems value="#{reclutadorController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="#{bundle.CreateConsultorLabel_estatusId}" for="estatusId" />
<h:selectOneMenu id="estatusId" value="#{consultorController.selected.estatusId}" title="#{bundle.CreateConsultorTitle_estatusId}" required="true" requiredMessage="#{bundle.CreateConsultorRequiredMessage_estatusId}">
<f:selectItems value="#{estatusConsultorController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>

2.- Examina el valor aplicado a la etiqueta . El atributo “value” determina el texto que se muestra para cada elemento de la lista desplegable.

3.- Presione Ctrl-Espacio en itemsAvailableSelectOne. La función de completar código del editor indica que getItemsAvailableSelectOne() de EstatusConsultorController devuelve un arreglo de objetos selectItem.

4.- Coloca el cursor sobre el valor de retorno selectItem[] en la firma del método, y pulsa Ctrl-Space para invocar la documentación pop-up.


Si lo deseas haz click en el navegador web (el icono del navegador web) para abrir la documentación Javadoc en un navegador web externo.

Como puedes ver, la clase SelectItem pertenece al freamwork de JSF. El componente de UISelectOne, como se menciona en la documentación, está representado por la etiqueta de que se examinó en el paso 1.

5.- Presiona Ctrl, a continuación, pasa el ratón sobre el metodo findAll(). Un pop-up aparece mostrando la firma del método.


Puedes ver que aquí ejbFacade.findAll() devuelve una lista de objetos ConsultantStatus.

6.- Desplazate sobre a JsfUtil.getSelectItems. Mueve el ratón sobre getSelectItems y presiona la tecla Ctrl, a continuación, haz click en el enlace que aparece.

Nota: Recuerda que JsfUtil es una de las clases de que se genera cuando se completó del asistente para JSF Pages from Entity Classes.

El método que itera a través de la lista de entidades (es decir, la lista de objetos EstatusConsulor), creando un SelectItem para cada uno. Como se indica en negrita a continuación, cada SelectItem se crea usando el objeto de entidad y una etiqueta para el objeto.

 public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {
      int size = selectOne ? entities.size() + 1 : entities.size();
      SelectItem[] items = new SelectItem[size];
      int i = 0;
      if (selectOne) {
          items[0] = new SelectItem("", "---");
          i++;
      }
      for (Object x : entities) {
          items[i++] = new SelectItem(x, x.toString());
      }
      return items;
  }

La etiqueta se crea usando el método toString(), y es la representación del objeto. (Véase la definición Javadoc para el constructor SelectItem (valor java.lang.Object, java.lang.String etiqueta))

Ahora que has comprobado que es el resultado de toString() es lo que se representa en el navegador al ver los elementos en una lista desplegable, modificaremos el método toString () de EstatusConsultor.

7.- Abre la clase EstatusConsultor en el editor. Modifica el método toString() para devolver el estatusId y descripcion. Estos son corresponden a las dos columnas de la tabla ESTATUS_CONSULTOR.

  @Override
  public String toString() {
      return estatusId + ", " + descripcion;
  }

8.- Ejecuta el proyecto de nuevo. Cuando el navegador muestra la página de bienvenida, haz click en el vínculo Mostrar todos los artículos de consultores, a continuación, haz click en Crear nuevo consultor.

Inspecciona la lista desplegable EstatusId. Verás que ahora muestra el ID de estado y la descripción para el expediente de la que figura en el cuadro ESTATUS_CONSUTOR de la base de datos.

Listo, teminamos.

Este post esta basado en la traducción del ejemplo: http://netbeans.org/kb/docs/web/jsf20-crud.html

para JSF 2.0 y NetBeans 7.0 o superior

Espero que este ejemplo sea de utilidad para ustedes.