martes, 10 de septiembre de 2013

Desarrollando una lista de TO-DO usando base de datos y el Framework ZK.

clip_image002

Te mostraremos, paso a paso, como construir una sencilla aplicación web con ZK que use una base de datos. La aplicación web permitirá almacenar sucesos que vamos a hacer en el futuro o sea una lista de TO-DO. Una aplicación web así, requeriría usar una base de datos. Para la conclusión de este tutorial usaremos una base de datos Java (HSQL DB) la cual no requiere que instalemos un servidor de base de datos [1].

Pasos para ejecutar la aplicación:

  1. Descargue el código fuente de aquí.
  2. cd todo
  3. mvn jetty:run (si usted no tiene maven instalado por favor descárguelo aquí )
  4. Abra su navegador y coloque la siguiente url: http://localhost:8080/todo

clip_image003

Todos los Escenarios

§ Introduce toda la información relativa a un evento y presiona el botón  Add  para insertarlo en la base de datos.

§ Selecciona cualquier fila en la tabla para mostrar la información del evento en los campos de abajo para que modificar su información, después presiona el botón  Update  para modificar la información.

§ Selecciona cualquier fila en la tabla y presiona el botón  Delete  para eliminar el "Event" seleccionado.

Modelo

En los siguientes párrafos, el esquema de la base de datos, el objeto del dominio y el objeto DAO serán introducidos.

Esquema de la base de datos

Una tabla de la base de datos la cual va a almacenar los datos de nuestra aplicación, necesitará los siguientes atributos: event id, event name, event priority and event date.

El esquema de base de datos está listado abajo.

Field

Type

id

varchar(50)

name

varchar(50)

priority

int

date

date

Objeto Dominio

Para la la tabla de arriba, creamos el objeto de dominio correspondiente, como se indica:

public class TodoEvent {

private String id;

private String name;

private int priority;

private Date date;

public TodoEvent(String id, String name, int priority, Date date) {

this.id = id;

this.name = name;

this.priority = priority;

this.date = date;

}

// getter and setter methods are ommited, please refer to the source code.

}

Objeto de Acceso a Datos


Para que fácilmente se acceda a nuestra base de datos necesitaremos un objeto DAO con los siguientes métodos: findAll(),delete(),insert() and update().

public class EventDAO {

// The implementation is ommited, please refer to the source code.

public List<TodoEvent> findAll() {

}

public boolean delete(TodoEvent evt) {

}

public boolean insert(TodoEvent evt) {

}

public boolean update(TodoEvent evt) {

}

}

La Vista


Tu primer componente ZK


El primer paso es crear un fichero cuya extensión debe ser zul, pongamos todo.zul, y situamos este fichero bajo el directorio de nuestra aplicación web, por ejemplo, $TOMCAT_HOME/webapps/ProjectName/. Declaras un componente ZK de igual forma a como declaras un componente usando HTML.

Prueba a declarar tu primer componente  window  de la siguiente forma:

<window title="To do list" border="normal">

</window>

Después inicia Tomcat y usa el navegador para visitar la página, eg. http://localhost:8080/todo/todo.zul. El resultado se muestra abajo,  window  con el título 「To do List」.

Todo en ZK es un componente. Puedes cambiar el título, el alto y el borde de tu  window  Es muy sencillo e intuitivo. Intenta cambiar estos atributos y comprueba el resultado.

Relaciones jerárquicas entre los componentes de ZK


Lo siguiente, vamos a intentar enriquecer esta página con más componentes ZK. Para mostrar datos en una tabla, podemos usar un componente  listbox  el cual está diseñado para mostrar datos. Para insertar un listbox lo declaramos dentro de los tags del componente  window, como se indica:

<window title="To do list" border="normal">

<listbox id="box" multiple="true" rows="5">

</listbox>

</window>

En este ejemplo, el componente  listbox  es un componente hijo de  window. Sí, hay relaciones jerárquicas entre los componentes de ZK, te encontrarás una excepción UI si intentas declarar un componente dentro de un contexto equivocado, por ejemplo, al declarar un componente  window  como hijo de un componente  listbox.

Un componente anidado


Un listbox es un componente anidado, el cual soporta dos tipos de componentes hijos, listhead (aka: columna de la tabla), and listitem (aka: fila de la tabla). Con la declaración del  listbox, asignamos el atributo id a 「box」, ahora podemos usar este atributo para referenciar el listbox.

<window id="win" title="To do list" width="640px" border="normal">

<listbox id="box" multiple="true" rows="5">

<listhead>

</listhead>

<listitem>

</listitem>

</listbox>

</window>

Aún no hemos terminado. Vamos a declarar tres componentes listheader dentro de los tags de listhead. Necesitamos tres columnas -- 「Item」, 「Priority」, and 「Date」 -- dentro de la tabla, como se indica:

<window id="win" title="To do list" width="640px" border="normal">

<listbox id="box" multiple="true" rows="5">

<listhead>

<listheader label="Item" />

<listheader label="Priority" width="80px" />

<listheader label="Date" width="170px" />

</listhead>

<listitem>

</listitem>

</listbox>

</window>

Tenemos tres columnas en nuestra tabla, cada fila de la tabla también requerirá tres campos. Declaramos tres componentes listcell dentro de los tags del componente listitem.

<window id="win" title="To do list" width="640px" border="normal">

<listbox id="box" multiple="true" rows="5">

<listhead>

<listheader label="Item" />

<listheader label="Priority" width="80px" />

<listheader label="Date" width="170px" />

</listhead>

<listitem>

<listcell />

<listcell />

<listcell />

</listitem>

</listbox>

</window>

La estructura anidada del componente  listbox  quedaría así:

listbox 
+-- listhead
|    |
|    +-- listheader
|
+-- listitem
      |
     +-- listcell

Componentes para introducir información


En adición a mostrar estos eventos en el  listbox, necesitamos introducir información relativa al evento, incluyendo el evento name (campo texto), el evento priority (campo numérico) y el evento date (campo fecha). Para lograr esto, declare un textbox, un intbox y un datebox dentro de los tags del componente  window  de la siguiente forma:

<window id="win" title="To do list" width="640px" border="normal">

<listbox id="box" multiple="true" rows="5">

<listhead>

<listheader label="Item" />

<listheader label="Priority" width="80px" />

<listheader label="Date" width="170px" />

</listhead>

<listitem>

<listcell />

<listcell />

<listcell />

</listitem>

</listbox>

Item: <textbox id="name" cols="25" />

Priority: <intbox id="priority" cols="1" />

Date: <datebox id="date" cols="8" />

<button id="add" label="Add" />

<button id="update" label="Update" />

<button id="delete" label="Delete" />

</window>

 


Componentes Layout


Para distinguir los componentes de entrada de datos (input) de los componentes listbox de abajo, declaramos un groupbox para agrupar los componentes. Esto dibujará un borde alrededor de los componentes que estén contenidos dentro del groupbox, en este caso, los componentes de entrada de datos (input).

<window id="win" title="To do list" width="640px" border="normal">

<listbox id="box" multiple="true" rows="5">

<listhead>

<listheader label="Item" />

<listheader label="Priority" width="80px" />

<listheader label="Date" width="170px" />

</listhead>

<listitem>

<listcell />

<listcell />

<listcell />

</listitem>

</listbox>

<groupbox>

<caption label="Event" />

Item: <textbox id="name" cols="25" />

Priority: <intbox id="priority" cols="1" />

Date: <datebox id="date" cols="8" />

<button id="add" label="Add" />

<button id="update" label="Update" />

<button id="delete" label="Delete" />

</groupbox>

</window>

Adicionalmente a los componentes  groupbox  declaramos un componente  caption  para mostrar una etiqueta 「Event」 a lo largo de la caja que agrupa a los componentes. El componente caption trabaja de forma similar al legendario elemento en HTML.

Controlador


Nuestros requisitos incluyen mostrar, añadir, editar y borrar sucesos/eventos. En los siguientes párrafos, implementaremos las interacciones entre nuestra aplicación web y la base de datos.

Definiendo un Controlador


El primer paso es definir un EventController el cual herede de org.zkoss.zk.ui.util.GenericForwardComposer.

Implementando org.zkoss.zk.ui.util.GenericForwardComposer

Crea un EventController el cual heredará de org.zkoss.zk.ui.util.GenericForwardComposer permitiéndote un fácil acceso a la vista y definir un CRUD mediante los métodos Java definidos.

// org.zkforge.todo.event.EventController.java

public class EventController extends GenericForwardComposer {

private static final long serialVersionUID = -9145887024839938515L;

private EventDAO eventDao = new EventDAO();

// Note: Something is omitted at here. You can view detail about this class on source code.

public List<TodoEvent> getAllEvents() {

return eventDao.findAll();

}

public void onClick$add() {

}

public void onClick$update() {

}

public void onClick$delete() {

}

}

Asociando el Controlador con la Vista

Para implementar la interacción entre la Vista y el Controlador asignamos el atributo apply al componente window en la ruta de nuestro EventController.

<window id="win" title="To do list" width="640px" border="normal"

apply="org.zkforge.todo.event.EventController">

......

Visualizando datos en una Vista


Para visualizar los datos recuperados de la base de datos en nuestra Vista solo requerimos tres pasos:


  • Activar un mecanismo de DataBinding Mechanism
  • Asociar datos con la Vista
  • Definir una plantilla

Activando el mecanismo de DataBinding

Para usar el mecanismo Data Binding, deberemos activar el Data Binding Manager (org.zkoss.zkplus.databind.AnnotateDataBinderInit) en la parte superior de la página.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

<window id="win" title="To do list" width="640px" border="normal"

apply="org.zkforge.todo.event.EventController">

....

Asociando los datos con la vista

El paso siguiente es recuperar los datos de la base de datos mediante el EventController usando la expresión (win$composer.allEvents) para invocar EventController.getAllEvents(). El método EventController.getAllEvents() devuelve una lista que contiene todos los eventos almacenados en la base de datos que pueden ser asociados al atributo model del Listbox.

<window id="win" title="To do list" width="640px" border="normal"

apply="org.zkforge.todo.event.EventController">

<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}">

....

Puedes seguir los siguientes pasos para definir una plantilla de Interfaz de Usuario para renderizar los datos dentro de la vista.

Definiendo una plantilla

Es posible definir una plantilla de interfaz de usuario para renderizar DataBinding dentro de los correspondientes componentes de interfaz de usuario. Esto se logra gracias a la utilización de los atributos que ofrece el componente "listitem" definiendo una variable para representar cada instancia a reflejar.

<window id="win" title="To do list" width="640px" border="normal"

apply="org.zkforge.todo.event.EventController">

<listbox id="box" multiple="true" rows="5"

model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"

selectedItem="@{win$composer.current}">

<listhead>

<listheader label="Item" sort="auto(name)" />

<listheader label="Priority" width="80px" sort="auto(priority)" />

<listheader label="Date" width="170px" sort="auto(date)" />

</listhead>

<listitem self="@{each='event'}" value="@{event}">

<listcell label="@{event.name}" />

<listcell label="@{event.priority}" />

<listcell label="@{event.date}" />

</listitem>

</listbox>

Para más información, por favor dirígete a Associate UI Components with a Collection.

Sincronización de vistas


Una vez el usuario selecciona un ToDoEvent en el listbox, Necesitamos mostrarlo en el componente groupbox también. Sería mucho mejor si este tedioso trabajo fuera realizado de forma automáticamente. Data Binding es la respuesta! Simplemente asocia los datos con todo lo relacionado con los componentes de UI. El DataBinding se sincronizará entonces con todos los componentes de Interfaz de Usuario una vez la propiedad ha sido modificada.


  • Definir una instancia en un Controlador
  • Asociar múltiples componentes UI a la instancia

Definir una instancia "ToDoEvent" a un Controlador

Define una instancia ToDoEvent' en EventController, y define métodos getter y setter para que puedan ser accesibles desde la vista.

// org.zkforge.todo.event.EventController.java

public class EventController extends GenericForwardComposer {

private TodoEvent current = new TodoEvent();

// Omitted...

public TodoEvent getCurrent() {

return current;

}

public void setCurrent(TodoEvent current) {

this.current = current;

}

Asociando múltiples componentes UI con la instancia EventController

Primero, asocia la instancia EventController con la propiedad selectedItem del listbox. Después, asocia las propiedades del ToDoEvent con el correspondiente componente UI, incluyendo textbox, intbox, y datebox. Una vez el usuario selecciona un item en un listbox, la instancia se actualizará en relación a los componentes UI.

<listbox id="box" multiple="true" rows="5"

model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"

selectedItem="@{win$composer.current}">

<!-- Omitted -->

<groupbox>

<caption label="Event" />

Item: <textbox id="name" cols="25" value="@{win$composer.current.name}" />

Priority: <intbox id="priority" cols="1" value="@{win$composer.current.priority}" />

Date: <datebox id="date" cols="8" value="@{win$composer.current.date}" />

Sincronizando la vista con la base de datos


Además de mostrar los datos de la base de datos en la vista, nos gustaría implementar eventos para añadir, actualizar y eliminar. Esta funcionalidad requiere de tres pasos, monitorizar la actividad del usuario, interactuando con los controladores para actualizar la base de datos y actualizar la vista.


  • Registrar el evento Listener en el controlador
  • Actualizar la vista usando Databinding

Registrar el evento Listener en el Controlador

Para monitorizar la actividad del usuario, simplemente registramos un evento listener onClick' en los siguientes tres botones add, update and delete. Cuando cliqueamos en estos botones que se corresponden a los métodos definidos en EventController estos serán invocados. Estos métodos son definidos así:

public class EventController extends GenericForwardComposer {

private EventDAO eventDao = new EventDAO();

// Omitted...

public void onClick$add() {

if (current != null) {

current.setId(UUID.randomUUID().toString());

if (validate(current)) {

// insert into database

eventDao.insert(current);

}

}

}

public void onClick$update() {

if (current != null && validate(current)) {

// update database

eventDao.update(current);

}

}

public void onClick$delete() {

if (current != null && validate(current)) {

eventDao.delete(current);

}

}

}

<button id="add" label="Add" />

<button id="update" label="Update" />

<button id="delete" label="Delete" />


Actualizar la vista usando Databinding

Después de interactuar con la base de datos, el último paso es actualizar la vista. Simplemente notificar al Databinding para que actualice el modelo por ti, cuando el usuario cliqueé en cualquier botón. Intenta registrar un atributo load-after en el atributo model del listbox, y el Databinding actualizará la vista automáticamente si el evento especificado es capturado.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

<window id="win" title="To do list" width="640px" border="normal"

apply="org.zkforge.todo.event.EventController">

<listbox id="box" multiple="true" rows="5"

model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"

selectedItem="@{win$composer.current}">

<!-- Omitted... -->

<button id="add" label="Add" />

<button id="update" label="Update" />

<button id="delete" label="Delete" />

</groupbox>

</window>

Eso es todo, esperamos que le sea útil y quedamos al tanto de sus comentarios.





¿Te ha gustado este Post? Compártelo con tus amigos.

5 comentarios:

  1. Excelente articulo, lo compile y lo probe y me funciono todo ok. Me encanta cuando publican temas sobre ZK.

    ResponderEliminar
    Respuestas
    1. Muchas gracias por sus comentarios, seguirémonos esforzando para satisfacer a los usuarios del blog.`Sus aportes serán bienvenidos. Saludos

      Eliminar
  2. Muchisimas gracias, estuve días buscando como manejar consultas para una base de datos y aquí lo he encontrado. Felicitaciones por el Blog :)

    ResponderEliminar
    Respuestas
    1. Gracias por sus comentarios y esperamos sigan siendo de utilidad a la comunidad, cualquier aporte o sugerencia no dude en contactarnos.

      Eliminar
  3. No se encuentra disponible todo.rar, porfa donde lo encuentro.

    ResponderEliminar

IconIconIcon