miércoles, 28 de enero de 2009

CRUD con JSF usando ICE Faces

(Versión wiki: http://wiki.netbeans.org/CRUDconVisualiceFaces)

Este tutorial permite guiar los pasos para realizar una simple aplicación que mantiene una tabla de una base de datos. Permite realizar Insert, Update y Delete (CRUD= Create / Read / Update / Delete)
Además se considerará la funcionalidad importante de ICE faces, que es el uso de Ajax.
Para ello lo realizaremos con lo siguiente:
  • Java Development Kit 5 ó 6
  • NetBeans 6.5 con el Plugin VisualJSF, ICEFaces Design-Time and Run-Time Libraries, y ICEfaces Project Integration
  • Glassfish V2
  • La base de datos ejemplo TRAVEL de JavaDB

Creando la aplicación

Diseñando la aplicación

  1. Creamos un proyecto web presionando Mayúscula+Ctrl+N. Será una aplicación web que tendrá por nombre InsertUpdateDelete, utilizará Glassfish y activamos la opción que necesitamos usar el Visual Web ICEfaces
  2. El editor habrá abierto el archivo Page1.jsp en modo diseño. Como una advertencia aparece un texto indicando que no se las paletas de Visual JavaServer Faces (los componentes de Woodstock) no son permitidos en proyectos con ICEfaces.
    Así que lo tendremos muy en cuenta y no usaremos nada de esas paletas. Borramos ese mensaje de advertencia, seleccionándolo y presionando la tecla "Supr" (Delete)
  3. En esta ventana pegaremos de la paleta ICEfaces (Mayúscula+Ctrl+8) el componente DataTable, y le pondremos "tablaPersonas" como valor de la propiedad id
  4. Del panel de Prestaciones (Ctrl+5), abrimos la base de datos "travel", seleccionamos la tabla PERSON...
    ... lo arrastramos y lo soltamos sobre el DataTable que acabamos de pegar
  5. Si se presenta una ventana de diálogo donde se pregunta sobre qué objeto se pondrá los valores de la tabla...
    ... seleccionamos tablaPersonas. Con esto, la tabla se actualizará con un contenido parecido a esto.
    . Debemos notar que los campos mostrados son los mismos que se muestran en la tabla.
  6. Ejecutamos la aplicación, y veremos que en pocos clics tenemos una aplicación simple que muestra el contenido de la tabla PERSONS.
    Adicionalmente se puede agregar una opción para que se pueda ordenar por los campos.
    En ejecución:
    Además, podemos hacer un selector por filas, para ello en el modo de diseño hacemos clic derecho sobre la tabla y seleccionamos Add RowSelector..."
  7. Nos mostrará una ventana de diálogo donde nos pide a qué asociar el selector de filas
    Sin modificar nada, hacemos clic en Close

Preparando para el modelo de datos para actualizar los datos

  1. Ahora, crearemos una clase que tendrá el siguiente código:
    package insertupdatedelete.beans;

    import java.sql.Timestamp;
    import java.util.TreeMap;

    public class Person {

    private int personId;
    private String name;
    private String jobTitle;
    private int frequentFlyer;
    private Timestamp lastDateUpdated;

    public Person(TreeMap data) {
    personId = (Integer) data.get("PERSON.PERSONID");
    name = (String) data.get("PERSON.NAME");
    jobTitle = (String) data.get("PERSON.JOBTITLE");
    frequentFlyer = (Integer) data.get("PERSON.FREQUENTFLYER");
    lastDateUpdated = (Timestamp) data.get("PERSON.LASTUPDATED");
    }
    }

  2. Al final de la clase, antes de la última llave que cierra la clase, presionamos las teclas Alt+Insertar para insertar código. Se nos presentará un menú emergente, y seleccionamos la opción "Getter y Setter..." Esto nos permitirá crear los métodos sets y gets para todas las propiedades. Por ello, seleccionamos todas las propiedades, o marcamos la clase.
    ... y hacemos clic en "Generar"
  3. Ahora, nos ubicamos nuevamente al final de la clase, antes de la última llave, presionamos Alt+Insertar y seleccionamos Constructor. No seleccionamos ningún campo.
    Esto nos creará un constructor sin parámetros.
  4. Crearemos otro constructor repitiendo el paso anterior, pero esta vez seleccionaremos todos los campos.
  5. Agregue las siguientes propiedades a la clase Page1.java private Person blankPerson = new Person();
    private Person selectedPerson = blankPerson;
    private boolean editDisabled = true;
    Luego genere los setter y getters de las propiedades selectedPerson y editDisabled. Con esto lucirá la clase así:
  6. Ahora, necesitamos programar la lógica de negocio cuando se haga clic en alguna de las filas de la tabla. Cuando se hace clic en alguna de las filas de la tabla durante la ejecución de la aplicación, se ejecutará el método rowSelector1_processAction() de la clase Page1.java. Debemos editar este método con el siguiente código: public void rowSelector1_processAction(RowSelectorEvent rse) {
    int selectedRowIndex = rse.getRow();
    editDisabled=false;
    dataTable1Model.setRowIndex(selectedRowIndex);
    selectedPerson=new Person((TreeMap)dataTable1SortableDataModel.getRowData());
    }

El formulario de edición

Ahora, agregaremos un formulario de edición, de tal manera que cada vez que hagamos clic en una de las filas de la tabla, se muestre los campos de ese registro en ese formulario. Para ello haremos lo siguiente:
  1. De la paleta ICEFaces, seleccionar Form y soltarlo en la parte inferior de la tabla. Asegurémonos que no está dentro del otro formulario.
  2. Agregar los campos que querramos editar, por ejemplo, el nombre y el cargo.
  3. Por cada campo agregado, hacemos clic derecho y seleccionamos Bind to data... para seleccionar de donde se obtendrá los datos para el formulario.
    Notar que se está asociando al objeto selectedPerson
  4. Ahora, por cada campo, hacemos clic derecho nuevamente y seleccionamos Property binding... y hacemos que la propiedad disabled esté asociada a la propiedad editDisabled
  5. Agregamos un CommandButton en el form2, y también asociamos la propiedad disabled con el objeto editDisabled
¿Por qué hay que asociar el disabled con el objeto editDisabled ? Recordemos que cuando se selecciona una fila, el valor de editDisabled se vuelve a false (comenzaba con el valor true). Esto quiere decir, que los input-text y el button se mostrarán como desactivados hasta que cuando alguien le hace clic en una fila. Si sucede esto, los input-text y el button se volverán editables (disabled=false)

Agregando lógica de edición

  1. Hagamos clic derecho sobre el botón, y seleccionamos Edit event handler > Process Action.
    Eso nos creará el método processAction(). Editaremos el contenido de ese método con lo siguiente: public void button1_processAction(ActionEvent ae) {
    personDataProvider.setCachedRowSet((javax.sql.rowset.CachedRowSet) getValue("#{SessionBean1.personRowSet}"));
    persistPerson(selectedPerson);
    selectedPerson=blankPerson;
    editDisabled=true;
    }
  2. El método persistPerson() no existe, y el NetBeans nos mostrará un foquito en el margen izquierdo sugeriéndonos que debemos crear un método. Podemos hacerle clic sobre ese foco para que nos cree el método sugerido, o presionamos Alt+Enter. Editamos el contenido de este método con lo siguiente: private void persistPerson(Person selectedPerson) {
    if (personDataProvider != null) {
    java.util.Date d = new Date();
    Timestamp t = new Timestamp(d.getTime());
    if (personDataProvider.getRowCount() > 0) {
    personDataProvider.cursorFirst();
    do {
    if (personDataProvider.getValue("PERSON.PERSONID").equals(selectedPerson.getPersonId())) {
    personDataProvider.setValue("PERSON.NAME", selectedPerson.getName());
    personDataProvider.setValue("PERSON.JOBTITLE", selectedPerson.getJobTitle());
    personDataProvider.setValue("PERSON.FREQUENTFLYER", selectedPerson.getFrequentFlyer());
    personDataProvider.setValue("PERSON.LASTUPDATED", t);
    break;
    }
    } while (personDataProvider.cursorNext());
    personDataProvider.commitChanges();
    }
    }
    }
  3. Para terminar, debemos asegurarnos de que al cargarse la página por primera vez, debe mostrarse los datos actualizados. Debemos editar el método prerender() de Page1.java @Override
    public void prerender() {
    try {
    CachedRowSet cachedRowSet = (CachedRowSet) getValue("#{SessionBean1.personRowSet}");
    cachedRowSet.execute();
    personDataProvider.refresh();
    dataTable1SortableDataModel.setWrappedData(getValue("#{SessionBean1.personRowSet}"));
    } catch (SQLException ex) {
    log(ex.getMessage(), ex);

    }

    }
  4. Ejecutamos la aplicación, y veremos cómo se comporta

Recursos

El código fuente que utilicé para este proyecto se puede descargar desde aquí http://diesil-java.googlecode.com/files/CRUDicefaces.tar.gz


1 comentario:

Si quieres hacer una pregunta más específica, hazla en los foros que tenemos habilitados en Google Groups


Ah! solo se permiten comentarios de usuarios registrados. Si tienes OpenID, bienvenido! Puedes obtener su OpenID, aquí: http://openid.net/