viernes, 14 de junio de 2013

Desarrollo de una aplicación web MVC en JAVA con ZK, Spring e Hibernate.

Ya en otras entradas hemos visto los temas introductorios a ZK como framework JAVA para el desarrollo de la capa de presentación y también hemos visto el uso de Spring e Hibernate para el desarrollo de la capa de negocio y de persistencia.

En esta entrada veremos a través de un ejemplo práctico como combinar estos frameworks para implementar un CRUD (Patrón de caso de uso con las funcionalidades de añadir, modificar, eliminar, listar).

El proyecto será una aplicación web en Maven por lo que comenzaremos por el fichero pom.xml donde pondremos los repositorios que usaremos y las dependencias a incluir en el proyecto. De esta forma Maven las gestionará por nosotros.

El pom lo pueden ver aquí.

<pre class="brush:xml;">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GestUsuariosZK</groupId>
<artifactId>GestUsuariosZK</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>GestUsuariosZK</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>3.2.0.RELEASE</org.springframework.version>
<zk.version>6.5.0</zk.version>
<zkel.version>1.1.0</zkel.version>
</properties>

<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>


<!-- dependencias de ZK -->

<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zk</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zul</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zhtml</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.common</groupId>
<artifactId>zcommon</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zkforge.el</groupId>
<artifactId>zcommons-el</artifactId>
<version>${zkel.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.common</groupId>
<artifactId>zweb</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkplus</artifactId>
<version>${zk.version}</version>
</dependency>


<!-- dependencias comunes -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>



<!-- dependencias de Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<!-- dependencias para el acceso a datos -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.9.Final</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>zk repository</id>
<url>http://mavensync.zkoss.org/maven2</url>
</repository>
</repositories>
</project>
</pre>

Básicamente la aplicación es una implementación del patrón de arquitectura MVC o Modelo Vista Controlador.

· Tendremos las vistas que serán las páginas .zul.

· Tendremos los modelos que serán las clases encargadas del modelado de las entidades de nuestro sistema, tal y como vimos en las entradas relacionadas con la persistencia.

· Tendremos los controladores que son las clases que se encargan de coordinar las acciones entre las vistas y los modelos. Básicamente recibe eventos de las vistas y actualiza los modelos así como obtienen datos de los modelos y cambian la representación de dichos datos en las vistas.

De esta manera se logra una separación de responsabilidades eficiente. La idea general la pueden ver en la siguiente imagen.

clip_image001

La estructura del proyecto es la siguiente:

clip_image002

En el paquete org.desarrollo.ejemplo1.web se tiene la clase controladora.

En el paquete org.desarrollo.ejemplo1.servicio se tiene la interfaz que me enlaza con el modelo y su implementación así como un localizador del servicio que se encarga de obtener una sesión y cargar el bean de la implementación del modelo.

En el paquete org.desarrollo.ejemplo1.modelo se tiene la clase modelo con su mapeo a hibernate en este caso usando un fichero de configuración y no anotaciones como habíamos visto hasta ahora.

En el paquete org.desarrollo.ejemplo1.dao tengo la implementación del DAO genérico con todo el código de acceso a los datos que puede ser reutilizable.

La interfaz de la aplicación refleja las acciones de caso de uso típico CRUD:

clip_image004

Pueden usar el editor gráfico de ZK como se explica en esta entrada para que puedan visualizar la UI.

Como pueden ver tiene operaciones para:

· adicionar una persona,

· actualizar los datos a partir de la selección de la persona en el listado,

· buscar una persona a partir de uno de sus datos,

· borrar una persona previa selección de la misma en el listado.

La interfaz se diseña en un XML que es el formato usado por ZK para representar sus componentes UI (user interface) o Interfaz de Usuario en español.

La pueden ver aquí:

<pre class="brush:xml;">

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<window id="win" apply="org.desarrollo.ejemplo1.web.PersonasController" width="1024px" title="gestion de datos" border="normal">

<groupbox>
<caption label="Operaciones CRUD:" width="580px" />
<label id="label1" value="sdsd"/>
<grid>
<columns sizable="true">
<column width="100px"/>
<column width="370px"/>
</columns>
<rows>
<row>
<label value="Nombre:"/>
<textbox id="nombre" value="@{win$composer.current.nombre}" width="350px"/>
</row>
<row>
<label value="1er Apellido:"/>
<textbox id="apellido1" value="@{win$composer.current.apellido1}" width="350px"/>
</row>
<row>
<label value="2do Apellido:"/>
<textbox id="apellido2" value="@{win$composer.current.apellido2}" width="350px"/>
</row>
</rows>
</grid>
<button id="add" label="Adicionar" />
<button id="update" label="Actualizar" />
<button id="search" label="Buscar" />
<button id="delete" label="Borrar" />
</groupbox>
<listbox id="box" multiple="true" selectedItem="@{win$composer.current}" emptyMessage="No hay personas a mostrar">
<listhead>
<listheader label="Nombre:"/>
<listheader label="1er Apellido:"/>
<listheader label="2do Apellido:"/>
</listhead>
<template name="model">
<listitem width="680px">
<listcell label="${each.nombre}" />
<listcell label="${each.apellido1}" />
<listcell label="${each.apellido2}" />
</listitem>
</template>
</listbox>
</window>
</pre>

Como pueden observar lo primero es definir un grupo donde pondré varios componentes, para eso uso el componente “groupbox”.

Dentro de este componente pongo un “grid” que me permite tal como si usara un listbox ubicar columnas (columns) y filas (rows) para mostrar la primera parte de la UI.

Luego pongo una serie de botones usando el componente “button”.

Al salir del “groupbox” utilizo otro componente para mostrar el listado de las personas, que representan las tuplas en la BD, se trata de “listbox” lo más importante de este componente es el uso de otro componente dentro que se llama “template” y es el que me permite visualizar automáticamente los resultados en función de las acciones sobre la vista y la respuesta de la controladora.

NOTA: es importante que se fijen que todos los componentes tienen un id que me permite referenciarlos en la clase controladora.

Los principales atributos de la clase controladora reflejan los componentes en la UI, como pueden ver en la siguiente imagen.

clip_image005

Como ven uso una anotación Wire para obtener los componentes con esos nombres en la UI.

Igual uso la anotación @Listen para los métodos que se enlazan con los botones de la UI.

clip_image007

Vean como utilizo el evento onClick sobre el componente para relacionarlo con la operación en la clase controladora. Es como si dijera: cada vez que se genere el evento onClick sobre el componente “update” se debe llamar al método update.

Lo demás es muy típico del trabajo con Spring e Hibernate así que les dejo el código fuente  del proyecto para que lo compilen con Maven y lo desplieguen en el servidor de su preferencia.

La tabla que se usó es realmente sencilla y este es su DDL:

CREATE TABLE public.persona (

id BIGINT NOT NULL,

nombre VARCHAR NOT NULL,

apellido1 VARCHAR NOT NULL,

apellido2 VARCHAR NOT NULL

) WITHOUT OIDS;

Para crear el .war de esta aplicación deben pararse en la raíz del proyecto, suponiendo que tengan Maven ya instalado y configurado.

Bastan con ejecutar este comando “mvn clean package”, verán cómo se descargan todas las dependencias del proyecto, se compila, se ejecutan las pruebas, en este caso no hay, y en la carpeta target del proyecto se les creará un .war que deben desplegar en un servidor como tomcat y listo.



.

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

4 comentarios:

  1. Muy buen tutorial, quisiera saber si se puede implementar sin Maven?

    Saludos desde Colombia.

    ResponderEliminar
    Respuestas
    1. Usted puede integrar ZK con Spring, sin necesidad de usar Maven. Puede
      incluir las bibliotecas necesarias de ZK y las de Spring en un IDE
      como Eclipse o Netbeans y compilar el proyecto.
      No obstante nosotros recomendamos el uso de Maven por las ventajas que
      tiene para la gestión y construcción de proyectos. Maven utiliza un
      Project Object Model (POM) para describir el proyecto de software a
      construir, sus dependencias de otros módulos y componentes externos, y
      el orden de construcción de los elementos. Facilita la compilación del
      código y su empaquetado.

      Eliminar
  2. buen tutorial, podrías subir los archivos completos?

    ResponderEliminar
  3. pura basura zk no hay nada de docuemntacion

    ResponderEliminar

IconIconIcon