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.
Hola,
ResponderBorrarestoy 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?
Hola Carmen,
ResponderBorrarPara 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.