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

martes, 13 de enero de 2009

Configurar NetBeans con WebLogic

(Tomado de http://www.nabble.com/Netbeans-6.5-can't-add-Weblogic-10.3-server-td20002675.html)
Considerando que se tiene instalado WebLogic 10.3 en c:\oracle\Middleware\wlserver_10.3, el usuario es weblogic y su contraseña weblogic:
1. Abrir el archivo %HOME_PATH%\.netbeans\6.5\config\J2EE\InstalledServers\.nbattrs Es un archivo en formato xml
2. Agregar la siguiente etiqueta:
<fileobject name="__instance_4__">
<attr name="debuggerPort" stringvalue="8787"/>
<attr name="displayName" stringvalue="BEA WebLogic Server"/>
<attr name="domainRoot" stringvalue="C:/oracle/Middleware/wlserver_10.3/samples/domains/wl_server"/>
<attr name="isLocal" stringvalue="true"/>
<attr name="password" stringvalue="weblogic"/>
<attr name="registeredWithoutUI" stringvalue="false"/>
<attr name="serverRoot" stringvalue="C:/oracle/Middleware/wlserver_10.3"/>
<attr name="url" stringvalue="deployer:WebLogic:http://localhost:7001:C:/oracle/Middleware/wlserver_10.3:C:/oracle/Middleware/wlserver_10.3/samples/domains/wl_server"/>
<attr name="username" stringvalue="weblogic"/>
</fileobject>

Notar el nombre del objeto creado:instance_4, debe ser un nombre único.
3. En la misma carpeta crear un archivo sin contenido cuyo nombre es el mismo que se ha declarado en el paso anterior.
4. Guardar y abrir el NetBeans. Podemos ver en el panel de Prestaciones el nuevo servidor.


nb-wl.jpg

martes, 6 de enero de 2009

Base de datos relacionales en Java: HSQLDB y Apache Derby (Parte 1)

Hola a todos
comenzaré este año con un post que quizás para algunos sea aburrido. Base de datos relacionales 100% Java.

Ojo, no estoy diciendo que sean bases de datos orientados a objetos. Eso es otro tema. Sino, que son bases de datos relacionales (esos de Entidad-relación, tuplas, relaciones, columnas, claves foráneas, etc.) cuyo motor está hecho en Java. Por tanto, si queremos modificar algo de su funcionamiento, pues encontraremos el código en Java. No en C, ni C++, ni C#, sino en Java.

Sabemos que los drivers de tipo 4 de JDBC se conectan directamente a la base de datos usando protocolos de red en java puro. Entonces, podemos suponer que usando bases de datos en java con jdbc en java, la conexión es mucho más directa, y se accede a los datos sin intermediarios. Bueno, es solo una suposición personal.

En este post comentaré de dos RBDMS en Java muy conocidos y usados: HSQLDB y Apache Derby. Haremos ejemplos usando NetBeans 6.5, aunque también funcionará en NetBeans 6.1.

Comenzaré con el que más me gusta y más conozco:

HSQLDB

Es la continuación del proyecto HypersonicSQL desde 2001. Permite varias sentencias SQL - ANSI92.

Descargaremos la biblioteca JDBC, que a su vez también es el RDBMS, de aquí:

http://downloads.sourceforge.net/hsqldb/hsqldb_1_8_0_10.zip

(La versión utilizada en este post es la 1.8.0.10)

Solo pesa 3.6 MB

Al descomprimirlo encontraremos varias carpetas. La carpeta lib contiene el driver hsqldb.jar y este .jar es el más importante para todo el HSQLDB, ya que es el JDBC y a su vez el motor de la base de datos.

Modos de uso

HSQLDB tiene los siguientes modos de uso:

HSQLDB Server

Es un modo cliente-servidor. Es decir, de la manera común que siempre hemos visto como operan los RBDMS como Oracle, MySQL, Firebird, PostgreSQL, etc. Esto es: se ejecuta la aplicación desde cualquier host quedando en espera (servidor), y desde cualquier otro host puede acceder como cliente al servidor.

Hagamos un ejemplo: Desde una ventana de la consola del Sistema Operativo, vayamos a la carpeta que se descomprimió el contenido del archivo .zip. En mi caso es d:\proys\lib\hsqldb. (Nota: el directorio hsqldb debe contener el directorio lib para poder realizar lo siguiente) Una vez allí ejecutamos lo siguiente:



java -cp lib/hsqldb.jar org.hsqldb.Server -database.0 file:data/demo_db -dbname.0 xdb


Al ejecutar esto, la ventana de consola muestra lo siguiente:


Ya sabemos qué significa java -cp y su argumento lib/hsqldb.jar.

Pero nuestra clase org.hsqldb.Server tiene cuatro argumentos importantes. Estos argumentos son realmente dos importantes:

-database.0 file:data/demo_db: Este parámetro indica cual es la base de datos que se va a crear físicamente. Como pueden crearse varias bases de datos, debemos diferenciar cada una usando un número después del parámetro -database.. Es decir, en este caso, nuestra base de datos tiene el número 0 (-database.0). Luego con el parámetro file: se especifíca  dónde se va a ubicar físicamente el archivo de la base de datos. En este caso se creará el archivo demo_db dentro de la carpeta data. Puede ser una ruta relativa o absoluta de disco. (file:data/demo_db)

-dbname.0 xdb Indica el nombre de la base de datos. También se tiene que especificar el número de la base de datos que debe coincidir con el argumento -database. En este ejemplo, el nombre de la base de datos es xdb. Esto es que para acceder desde Java debemos indicar el nombre xdb y no el archivo físico.

Esto quiere decir que si deseamos tener otra base de datos adicional llamada clientes, debemos escribir todo esto:


java -cp lib/hsqldb.jar org.hsqldb.Server -database.0 file:data/demo_db -dbname.0 xdb  -database.1 file:data/clientes_db -dbname.1 clientes

Ahora bien, ¿cómo se accede desde java? Bien, usaremos el NetBeans, en el panel de "Prestaciones" (Ctrl+5). En el nodo "Controladores" hagamos clic derecho y seleccionamos "Nuevo controlador..."

Con esto se abrirá una ventana de diálogo "Nuevo Driver JDBC". Hacemos clic en el botón "Agregar..." y buscamos el archivo hsqldb.jar (Sí, el mismo que usamos para ejecutar nuestro servidor... como dije antes: ese mismo archivo es el motor y el driver)

Una vez seleccionado, el NetBeans encontrará la clase controladora de la base de datos:


Clic en "Aceptar". Y se agregará un nuevo elemento bajo el nodo "Controladores" llamado "HSQLDB". Hacemos clic derecho sobre este nodo creado y seleccionamos "Conectar usando..." para crear una conexión usando este controlador. Se presentará la ventana de diálogo "nueva coneixón de base de datos...". Escribimos lo siguiente:
  • nombre de usuario: sa
  • password: (nada)
  • JDBC URL: jdbc:hsqldb:hsql://localhost/xdb


Note que el nombre de la base de datos es xbd tal como lo especificamos cuando ejecutamos el servidor. Clic en Aceptar, y al mostrarse el esquema que debemos seleccionar, dejamos la opción predeterminada  "INFORMATION_SCHEMA". Se creará un nuevo nodo de conexión, y al abrirlo podemos ver su contenido. Claro, en este momento no hay ninguna tabla creada.

Pero como podemos ver, es como cualquier otra conexión a base de datos.
Desde el IDE podemos crear tablas, usando sentencias SQL.

Es posible que las tablas creadas no se visualicen en el IDE de NetBeans. Pero sí podemos ejecutar sentencias SQL DDL o DML con total normalidad:

Ahora, podemos visualizar la carpeta hsqldb/data.Vemos que se ha creado al menos dos archivos por cada base de datos. Todas nuestras sentencias DDL (create, drop, alter, etc) y DML (select, insert, update, etc) se registrarán en el archivo de extensión .script. Es decir, que podemos modificar estos archivos manualmente para crear nuestras tablas y los datos que contendrán. Para poder modificar este archivo, debemos detener la base de datos.

También podemos acceder a las tablas de la base de datos utilizando una herramienta propia del hsqldb. Regresemos nuevamente a nuestra consola y ejecutemos lo siguiente (el servidor deberá aún estar en ejecución, asi que es necesario abrir una nueva ventana de consola)

java -cp lib/hsqldb.jar org.hsqldb.util.DatabaseManager


En la ventana de diálogo "Connect" que aparece escribimos el mismo URL que escribimos párrafos arriba, el mismo usuario y nada en la contraseña. El driver y el tipo son opcionales.

Clic en OK y listo.
Este manejador de base de datos es muy interesante, simple y efectivo. No detallaré esta herramienta ya que no es el motivo de este post.

Así pues, ya tenemos el servidor, y sabemos como conectarnos con él.

¿y cómo puede conectarse desde un programa java? Pues ya se puede imaginar:

Class.forName("org.hsqldb.jdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "sa", "");

Hsqldb Web Server

Este modo es muy interesante.Todos sabemos que por seguridad de redes los firewall evitan el uso de puertos adicionales a los permitidos. Los puertos por omisión del HSQLDB Server es el  9001 y el 544. Pero HSQLDB nos da la posibilidad de usar el puerto 80 como si fuera un servidor web.

Se ejecuta de la misma manera que el modo Server, pero se usa la clase WebServer. Es decir, debe ejecutarse de la siguiente manera:

java -cp lib/hsqldb.jar org.hsqldb.WebServer -database.0 file:data/demo_db -dbname.0 xdb

Ahora el URL del JDBC es: jdbc:hsqldb:httpd://localhost/xdb

Y todo funcionará igual.

Hsqldb Servlet

Es el modo servlet, es decir, debe estar ejecutado en una aplicación web y crear un servlet desde web.xml
    <servlet>
<servlet-name>hsqldb-servlet</servlet-name>
<servlet-class>org.hsqldb.Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hsqldb-servlet</servlet-name>
<url-pattern>/hsqldb/*</url-pattern>
</servlet-mapping>
No detallaré este modo ya que es mejor usar el modo servidor y no crear una aplicación web para crear un servidor.

Modo aislado (stand-alone)

Este modo es uno de los más útiles cuando se hace aplicaciones portables. Además, este modo permite tener una aplicación con la base de datos incrustada a ella sin necesidad de instalar alguna biblioteca adicional.

No requiere un servidor, simplemente al crear una conexión JDBC, ya se creó la base de datos.

Es decir, en nuestra aplicación usaremos el mismo driver org.hsqldb.jdbcDriver y el url que usaremos será jdbc:hsqldb:file:d:/hsqldb/clientes.

Connection conn = DriverManager.getConnection("jdbc:hsqldb:file:d:/proys/lib/hsqldb/data/demo_db", "sa", "");

La misma base de datos que hemos usado en el modo servidor, web server, es también usado en el modo stand-alone, y usando el mismo driver! Solo difiere el url.

Nota: solo se debe usar un modo a la vez, o es server, web server o stand-alone. Ya que necesita de bloqueos de archivo a nivel de sistema operativo.

Modo memoria

Es un modo muy interesante para ser usado en aplicaciones demo, que no se necesita guardar la información en un archivo físico. Si no que se crea la base de datos en memoria mientras dura la conexión. Naturalmente se tendrían que crear las tablas inmediatamente después de establecer la conexión.

Solo se debe cambiar el URL a: jdbc:hsqldb:mem:clientes.

y todo sigue igual

Final parte 1

Vemos que este driver/rdbms puede ser usado en dos modos marcados: servidor (server) y aislado (stand-alone). También podemos usar la misma base de datos en ambos modos. Esto también nos puede permitir trabajar en dos modos: standalone para desarrollo, y server para producción.

Se puede usar también en Hibernate, JPA, Spring, iBatis y cualquier framework que maneje base de datos. ya que cumple con las especificaciones de JDBC.

En la segunda parte hablaremos sobre Apache Derby.