viernes, 3 de febrero de 2012

Estructura de un Proyecto GWT

Prerequisitos

Antes de entrar a detallar la composición de un proyecto GWT, es conveniente saber el significado de módulo.

Módulo (Module)

Un módulo GWT es simplemente una encapsulación de funcionalidad. El concepto comparte algún parecido a un paquete Java (Java package) pero no es la misma cosa. Se nombran del mismo modo separando los nombres de los subdirectorios o subcarpetas con punto. Por ejemplo, la mayoría de los módulos estándar de GWT están subordinados a com.google.gwt. 


Modulo
Contenido
com.google.gwt.user.User
Núcleo de la funcionalidad de GWT; requerido en cada proyecto
com.google.gwt.http.HTTP
Librería de comunicaciones HTTP de bajo nivel
com.google.gwt.i18n.I18N
Soporte para internacionalización
com.google.gwt.json.JSON
Creación e interpretación de estructuras JSON
com.google.gwt.junit.JUnit
Framework para pruebas e integración JUnit
com.google.gwt.xml.XML
Creación e interpretación de documentos XML

Un módulo es definido por un archivo descriptor XML terminado con la extensión .gwt.xml. El nombre de este archivo determina el nombre del módulo. En nuestro ejemplo, creamos un proyecto llamado ejemplo1. Internamente GWT crea el descriptor src/com/gwt/ejemplo1/Ejemplo1.gwt.xml, creando a su vez el módulo com.gwt.ejemplo1. El contenido del archivo .gwt.xml especifica una lista precisa de las clases Java y otros recursos que son incluidas en el módulo GWT.

En otras palabras, un módulo GWT agrupa todas las propiedades de configuración que su proyecto necesita, entre ellas podemos destacar las siguientes:

·         Lista de módulos heredados. Por ejemplo, com.google.gwt.user.User debe estar definido en cada módulo, por ser el núcleo de GWT.
·         El nombre de la clase Java que se utilizará como punto de entrada (entry point). Esta es la clase que se instanciará al comienzo, invocando el método EntryPoint.onModuleLoad(), cuando el módulo sea cargado.
·         Ubicación de los subpaquetes fuentes a ser compilados y traducidos a JavaScript.
·         Ubicación de los subpaquetes públicos a ser compilados y traducidos a Javscript. Aquí debe incluirse el URL completo de la ubicación de estos subpaquetes.
·         Además, puede agregar propiedades adicionales para la compilación y traducción de los fuentes en Javascript.


Estructura de un Proyecto GWT

Tomando como referencia el proyecto ejemplo1 creado en el blog anterior, observamos que hay cinco grandes elementos definidos allí. Los dos primeros corresponden a carpetas de programas fuentes, los dos siguientes son contenedores de librerías y el último elemento corresponde a la carpeta que incluirá la aplicación web cuando esté lista para ser puesta en producción.

Cuando creamos este proyecto, en el asistente seleccionamos la opción Sample Code (código ejemplo), por esta razón, el proyecto contiene archivos adicionales a los que inicialmente teníamos previstos. El asistente ha creado aplicaciones tanto para el lado del cliente como del servidor. Más adelante revisaremos esta funcionalidad basada en RPC. Por ahora revisemos la estructura creada por el asistente:

Paquetes para código fuente:
Paquete
Propósito
com.gwt.ejemplo1
Paquete raíz del proyecto. Contiene el archivo descriptor XML:Ejemplo1.gwt.xml.
com.gwt.ejemplo1.client
Archivos fuentes y subpaquetes del lado del cliente: Ejemplo1.java, GreetingService.java y GreetingServiceAsync.java
com.gwt.ejemplo1.server
Archivos fuentes y subpaquetes del lado del servidor: GreetingServiceImpl.java
com.gwt.ejemplo1.shared
Recursos que pueden ser compartidos tanto del lado del cliente como del servidor

Paquete para aplicaciones de prueba:
Paquete
Propósito
com.gwt.ejemplo1
Paquete vacío en el cual podrá crear aplicaciones para probar sus aplicaciones del proyecto.

Librerías del SDK (Software Development Kit) de GWT
Librería
Propósito
gwt-user.jar
Contiene la gran mayoría de fuentes Java que componen GWT. Incluye  las clases que generalmente utilizamos en nuestro propio código. Por ejemplo todas las clases de widgets (componentes gráficos), animación, manejo de eventos, etc.
gwt-dev.jar
Contiene clases que soportan la ejecución del proyecto en modo de desarrollo (development mode)
validation-api-1.0.0.GA-sources.jar
Contiene los fuentes Java de un sistema de validación para la integración entre cliente y servidor
validation-api-1.0.0.GA.jar
Contiene las clases Java de un sistema de validación para la integración entre cliente y servidor

Librerías del sistema JRE (Java Runtime Environment)
Librería
Propósito
resources.jar
Clases JRE de propósito general para la ejecución de clases Java
rt.jar
Runtime clases Java
jsse.jar
Clases para seguridad de sockets (Java Secure Socket Extension)
jce.jar
Clases para codificación (Java Cryptography Extension)
charsets.jar
Clases para conversión de caracteres
dnsns.jar
Clases para representar direcciones IP.
dns_sd.jar
Clases para DNS auto descubrimiento (DNS Self Discovery)
localedata.jar
Clases para localización, tales como formatos de fechas, números, moneda, zona horaria, etc.
sunjce_provider.jar
Clases para codificación (Java Cryptography APIs)

Web Archive (war)
Archivo
Propósito
war/WEB-INF/lib/gwt-servlet.jar
Provee en el lado de el servidor las clases requeridas para implementar los mecanismos de GWT RPC (Remote Procedure Call)
war/WEB-INF/web.xml
Archivo de configuración de Servlets
war/Ejemplo1.css
Archivo de definición de estilos. (Cascading Style Sheets)
war/Ejemplo1.html
Archivo HTML en el cual la aplicación GWT será cargada.


Archivos del Proyecto GWT

Ejemplo1.gwt.xml

Abra este archivo en Eclipse y revise su contenido. Como ya vimos, este es el archivo descriptor, un documento XML que contiene propiedades especificas para este proyecto. Hereda paquetes GWT como com.google.gwt.user.User:

<inherits name='com.google.gwt.user.User' />

Define también las clases que se utilizarán para definir el tema de composición en CSS (Cascading Style Sheets). El asistente deja disponible la clase:

<inherits name='com.google.gwt.user.theme.clean.Clean' />

Como ejercicio puede volver esta linea un comentario y habiliar alguna de last res opciones adicionales que contiene este archivo descriptor:

    <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
    <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
    <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->

El punto de entrada (entry point), indica la clase Java que se instanciará cuando se ejecute el proyecto:

    <!-- Specify the app entry point class. -->
    <entry-point class='com.gwt.ejemplo1.client.Ejemplo1' />

El archivo descriptor también especifica la ubicación de los archivos fuentes de Java que se compilarán y se traducirán en Javascript:

      <!-- Specify the paths for translatable code -->
      <source path='client' />
      <source path='shared' />

¿Por qué no se incluye aquí los archivos Fuentes para el servidor? La respuesta es porque las aplicaciones del servidor se ejecutan como clases de Java y no como Javascript.



Ejemplo1.java

Este es el archivo principal de su proyecto. Aquí se alojarán los componentes que se desplegarán en la página web.

Contiene el método onModuleLoad() el cual es el primer método a ejecutarse cuando se instancia esta clase. Desde este punto comienza a tener vida su aplicación.


GreetingService.java

Esta interface hace parte de la implementación RPC que hará posible el diálogo entre el cliente y el servidor. Extiende RemoteService de GWT y define la lista de los métodos RPC que tendrán una implementación en el servidor.

@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
      String greetServer(String name) throws IllegalArgumentException;
}


GreetingsServiceAsync.java

Esta es una interface asincrónica del servicio creado en GreetingService y es invocada desde el lado del cliente.

public interface GreetingServiceAsync {
      void greetServer(String input, AsyncCallback<String> callback)
                  throws IllegalArgumentException;
}

Observe que esta interface contiene un método con el mismo nombre dado en GreetingService.java. La diferencia radica en los parámetros dados. El parámetro de tipo AsyncCallback nos ayudará a implementar el servicio bajo las características de AJAX. Se hace el llamado al servicio y la ejecución de la aplicación no se detiene a esperar una respuesta. La ejecución continúa y el resultado se procesa tan pronto como llegue de regreso del servidor. Por esta razón se denomina un servicio asincrónico.


GreetingServiceImpl.java

Esta clase define el servicio RPC en si. Extiende RemoteServiceServlet e implementa la interface asociada que define los servicios.  Observe que la implementación del servicio no se hace sobre la versión asincrónica de la interface:

.
.              
public String greetServer(String input) throws IllegalArgumentException {
.
.

¿Cómo determinar esto? Bueno, observe los parámetros de los métodos. La implementación del método greetServer(String input) corresponde al método definido en la interface GreetingService.java.

En realidad esta clase es un Java Servlet, que no extiende la típica clase HTTPServlet que se encarga de entablar un diálogo cliente-servidor utilizando el protocolo HTTP, sino que extiende la clase GWT RemoteServiceServlet, que realiza una serialización automática de los datos transmitidos entre el cliente y el servidor e invoca el método correspondiente en la implementación de este servicio.

Cabe destacar que esta clase residirá en el lado del cliente.


FieldVerifier.java

Esta clase hace parte del paquete com.gwt.ejemplo1.shared. Es una clase que puede ser compartida entre el cliente y el servidor. Normalmente aquí se crean clases que se utilizarán como herramientas o utilitarios para soportar el proceso general del proyecto. Rutinas de validación, rutinas para realizar cálculos, para manipular cadenas de caracteres, etc., son  implementadas aquí.


Ejemplo1.css

Define  los estilos utilizados para personalizar los componentes de la página web. Aquí puede definir  estilos propios  dando rienda suelta a su creatividad si tiene buenos conocimientos de CSS.


Ejemplo1.html

Esta es la página principal del proyecto. Es la página que se invoca cuando se ejecuta su aplicación.  Ya hemos visto como modificar este archivo  en el blog anterior Ejecutando una Aplicación GWT.


2 comentarios:

  1. Hola,
    estoy empezando con GWT y respecto a la estructura de mi proyecto no termino de verlo. En mi caso cuento con una portada completamente estática que tiene tres enlaces a tres páginas con partes comunes(cabecera, pestañas) y una parte central dinámica que puede ser variable. Mi problema es que asocio el punto de entrada a la portada y no sé como gestionar la navegacionb a las "subpáginas". Otra cosa que había pensado es tratarlas como módulos independientes, con su XML y su punto de entrada cada una, pero no termino de verlo. ¿Me podeis ayudar?

    ResponderBorrar
  2. Hola Carmen,

    Para este tipo de aplicaciones, el equipo de desarrollo de GWT provee el framework MVP (Module View Presenter) el cual te ofrece una forma dinámica para manejar eventos y la transición entre páginas.

    Hay información disponible en inglés en el siguiente enlace: http://www.gwtproject.org/articles/mvp-architecture.html

    Revisa esta información y coméntame si te funciona en tu aplicación.

    Perdona que no te haya respondido antes, pero no me habia dado cuenta de tu mensaje.

    ResponderBorrar

Autor de El Efecto Margarita