El Mejor Ejemplo DWR

18
El Mejor Ejemplo DWR, o El Mejor Tutorial DWR Java Add comments DWR (Direct Web Remoting)es una librería Javascript que permite el uso de Ajax (Asynchronous JavaScript and XML) de forma mucho más simple (Este artículo asume que se entiende los conceptos de Ajax, y de Java). DWR es una librería mas orientada a apoyar la integración, que a apoyar la parte gráfica, de hecho si se buscan Widgets (objetos gráficos) esta no es la librería, pero por otro lado lo fuerte de DWR es que permite “publicar” fácilmente funcionalidad de clases Java para accederlas vía Javascript. Luego si nuestra funcionalidad o lógica de negocio esta en Java, DWR es una de la mejores opciones para aprovecharla, ya que usar una clase Java que tenemos en un servidor de aplicaciones vía Javascript es tan fácil como definir un archivo de configuración en el servidor. Ahora si se requiere además darle una interfaz más rica (rich interface) a los usuarios, es bueno combinar DWR con otras librerías Ajax como YUI (Yahoo User Interface), JQuery, Prototype, Scriptaculous, Dojo, o Spry. Con Ajax se terminan las paginas JSP, o ASP (o deberían terminarse), porque Ajax solo necesita Javascript y HTML

Transcript of El Mejor Ejemplo DWR

Page 1: El Mejor Ejemplo DWR

El Mejor Ejemplo DWR, o El Mejor Tutorial DWR

Java Add comments         

DWR (Direct Web Remoting)es una librería Javascript que permite el uso de Ajax

(Asynchronous JavaScript and XML) de forma mucho más simple (Este artículo asume

que se entiende los conceptos de Ajax, y de Java).

DWR es una librería mas orientada a apoyar la integración, que a apoyar la parte

gráfica, de hecho si se buscan Widgets (objetos gráficos) esta no es la librería, pero por

otro lado lo fuerte de DWR es que permite “publicar” fácilmente funcionalidad de

clases Java para accederlas vía Javascript.

Luego si nuestra funcionalidad o lógica de negocio esta en Java, DWR es una de la

mejores opciones para aprovecharla, ya que usar una clase Java que tenemos en un

servidor de aplicaciones vía Javascript es tan fácil como definir un archivo de

configuración en el servidor.

Ahora si se requiere además darle una interfaz más rica (rich interface) a los usuarios, es

bueno combinar DWR con otras librerías Ajax como YUI (Yahoo User Interface),

JQuery, Prototype, Scriptaculous, Dojo, o Spry.

Con Ajax se terminan las paginas JSP, o ASP (o deberían terminarse), porque Ajax solo

necesita Javascript y HTML para la parte de presentación, esto lo explicaremos mejor

en otro articulo, pero por ahora créannos. Y con DWR ni siquiera son necesarios los

Servlets, esto en el sentido de que no se necesitan desarrollar servlets para implementar

la lógica de negocio, porque DWR si internamente esta basado en Servlets, en otras

palabras gracias a DWR no necesitamos implementar nuestros servlets sino solo

necesitamos clases Java (POJO).

Si se conoce la tecnología Axis, que permite publicar clases Java como Webservices,

este es el símil para publicar clases Java como objetos Ajax (objetos Javascripts), de

hecho es muy fácil publicar con DWR un servicio realizado para Axis. Incluso las

buenas prácticas o blueprints de Axis para publicar clases como Webservices se aplican

Page 2: El Mejor Ejemplo DWR

totalmente para publicar clases para Ajax., ya que hay que tener los mismos cuidados en

cuanto a seguridad y manejo de desempeño (performance).

La definición oficial de DWR es:

DWR permite a Javascript (en un Browser) interactuar con las clases Java en

un Servidor, y ayuda a manipular las paginas Web con los resultados.

Si, porque otra característica importante de DWR es que ofrece funcionalidades

Javascript que permiten fácilmente manipular el HTML de la página: como obtener los

datos de un formulario (HTML Form), o de cualquier otro tag HTML, o setear

fácilmente los valores de los tags HTML, ademas aporta facilidades para clonar tags, lo

que permite por ejemplo crear nuevas filas (rows) en una tabla (HTML Table), muy útil

para mostrar una consulta. DWR no nos provee ningun objeto grafico prehecho, pero si

nos permite la flexibilidad para hacer cualquier cosa con el HTML.

Bueno basta de conceptos y vamos directo al código.

Hemos llamado a este tutorial “el Mejor”, solo para llamar su atención, pero la verdad

es que es bastante bueno, por lo siguiente:

Es lo mas simple posible, tiene lo justo y necesario para entender el concepto principal de DWR,

y como funciona.

Esta actualizado, otros ejemplos están basados en versiones anteriores de DWR.

Esta completo, otros ejemplo ponen solo parte del código.

Usa clases y colecciones de clases (Collection) como parámetros de entrada y parámetros de

salida, que es lo que típicamente se va a usar en un sistema real, otros ejemplos usan datos más básicos.

De esta forma también se muestra como se manejan las colecciones y las clases en Javascript.

Tutorial DWR en 10 Simples Pasos

1. Lo primero es bajar DWR (http://getahead.org/dwr/download), basta bajar solo la librería

(dwr.jar).

2. Luego hay que modificar el archivo “web.xml”, este se encuentra bajo el directorio “WEB-INF”,

ejemplo: ”\dwrEasy\WEB-INF”, se debe incluir las definiciones de los servlets que atienden los

requerimientos DWR-AJAX.

Web.xml:

Page 3: El Mejor Ejemplo DWR

view plaincopy to clipboardprint?

1. < ?xml version="1.0" encoding="UTF-8"?>  2. < !DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Applicati

on 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">  3. <web_app>  4.   <display_name>dwrEasy</display_name>  5.   <servlet>  6.     <servlet_name>dwr-invoker</servlet_name>  7.     <display_name>DWR Servlet</display_name>  8.     <description>Direct Web Remoter Servlet</description>  9.     <servlet_class>org.directwebremoting.servlet.DwrServlet</

servlet_class>  10.     <init_param>  11.       <param_name>debug</param_name>  12.       <param_value>true</param_value>  13.     </init_param>  14.   </servlet>  15.   <servlet_mapping>  16.     <servlet_name>dwr-invoker</servlet_name>  17.     <url_pattern>/dwr/*</url_pattern>  18.   </servlet_mapping>  19. </web_app> 

3. A continuación se debe implementar la clase Java que va a ofrecer los servicios, esta basta que

sea un clase Java simple (POJO), con un constructor sin parámetros, y donde cada método de la clase es

un “potencial” servicio Ajax.

Esta clase va a estar del lado del servidor de aplicaciones (ejemplo: Tomcat,

JBoss, o Websphere) no necesariamente tiene que ser un servidor J2EE.

EasyService.java:

view plaincopy to clipboardprint?

1. package com.soaagenda.services;   2.   3. import com.soaagenda.valueobjects.*;   4.   5. public class EasyService {   6.     public EasyService() {   7.     }   8.   9.     public EasyResponse getProducts(EasyParameter parametersX){   10.         EasyResponse responseX= new EasyResponse();   11.   12.         // si parametros vacios devuelve error, error if empty paramete

rs   13.         if (parametersX==null || parametersX.getClientID()==null || par

ametersX.getClientID().length()< =0){   14.             responseX.setErrorCode(10001);   15.             responseX.setErrorDescription("Debe indicar ID Cliente. Giv

e us Client ID");   16.             return responseX;   17.         }   18.   19.         //crea lista productos del cliente, fill the client product lis

t   20.         //para ejemplo en duro, for the example fixed data   21.         Product[] productsListX= new Product[2];   22.  

Page 4: El Mejor Ejemplo DWR

23.         Product productX= new Product();   24.         productX.setBarCode("0001");   25.         productX.setName("Tarjeta Visa, Visa Credit Card");   26.         productsListX[0]= productX;   27.   28.         productX= new Product();   29.         productX.setBarCode("0002");   30.         productX.setName("Tarjeta American Express, American Express Cr

edit Card");   31.         productsListX[1]= productX;   32.   33.         //respuesta exitosa, sucessfull response   34.         responseX.setErrorCode(0);   35.         responseX.setErrorDescription("Consulta Banco Exitosa, Succesfu

ll Bank Query");   36.         responseX.setProducts(productsListX);   37.   38.         return responseX;   39.     }   40. } 

Este ejemplo simula una consulta de los productos bancarios de un cliente como

Tarjetas de Crédito (VISA, Master Card, Dinners, American Express), Cuentas

Corrientes, o Creditos de Consumo, para esto se le pasa como parámetro un

objeto que tiene el ID del cliente, y el tipo de producto a consultar, el servicio (o

método) devuelve otra clase con el código de error, mensaje de error, y la lista

de productos (un arreglo de clases producto).

4. También hay que definir las clases de datos (Value Objects) que va a utilizar el servicio, esta

clases deben ser javabeans (atributo privados, con getters y setters):

EasyParameter.java: define los parámetros de entrada del servicio.

view plaincopy to clipboardprint?

1. package com.soaagenda.valueobjects;   2.   3. public class EasyParameter {   4.     private String clientID;   5.     private String productType;   6.     public EasyParameter() {   7.     }   8.   9.     public void setClientID(String clientID) {   10.         this.clientID = clientID;   11.     }   12.   13.     public void setProductType(String productType) {   14.         this.productType = productType;   15.     }   16.   17.     public String getClientID() {   18.         return clientID;   19.     }   20.   21.     public String getProductType() {  

Page 5: El Mejor Ejemplo DWR

22.         return productType;   23.     }   24. } 

EasyResponse.java: define la estructura para los resultados del servicio.

view plaincopy to clipboardprint?

1. package com.soaagenda.valueobjects;   2.   3. public class EasyResponse {   4.     private int errorCode;   5.     private String errorDescription;   6.     private Product[] products;   7.   8.     public EasyResponse() {   9.     }   10.   11.     public void setErrorCode(int errorCode) {   12.         this.errorCode = errorCode;   13.     }   14.   15.     public void setErrorDescription(String errorDescription) {   16.         this.errorDescription = errorDescription;   17.     }   18.   19.     public void setProducts(Product[] products) {   20.         this.products = products;   21.     }   22.   23.     public int getErrorCode() {   24.         return errorCode;   25.     }   26.   27.     public String getErrorDescription() {   28.         return errorDescription;   29.     }   30.   31.     public Product[] getProducts() {   32.         return products;   33.     }   34. } 

Product.java: define la estructura de un producto.

view plaincopy to clipboardprint?

1. package com.soaagenda.valueobjects;   2.   3. public class Product {   4.     private String barCode;   5.     private String name;   6.     public Product() {   7.         try {   8.             jbInit();   9.         } catch (Exception ex) {   10.             ex.printStackTrace();   11.         }   12.     }   13.   14.     private void jbInit() throws Exception {   15.     }   16.   17.     public void setBarCode(String barCode) {   18.         this.barCode = barCode;  

Page 6: El Mejor Ejemplo DWR

19.     }   20.   21.     public void setName(String name) {   22.         this.name = name;   23.     }   24.   25.     public String getBarCode() {   26.         return barCode;   27.     }   28.   29.     public String getName() {   30.         return name;   31.     }   32. } 

5. Vamos a indicarle a DWR que clases vamos a publicar para Javascript (Ajax), esto se hace en el

archivo “dwr.xml”, y también corresponde a un esquema de seguridad porque podemos llegar a

especificar solo que métodos de una clase queremos exponer, y que atributos.

Para nuestro ejemplo vamos a publicar toda la clase servicio

(com.soaagenda.services.EasyService), es decir todos sus métodos, y todas las

clases de datos (com.soaagenda.valueobjects.*).

dwr.xml

view plaincopy to clipboardprint?

1. < ?xml version="1.0" encoding="UTF-8"?>  2. < !DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0

//EN" "http://getahead.org/dwr/dwr20.dtd">  3. <dwr>  4.   <allow>  5.     <!-- define la clase de servicios que se va a publicar mediante DWR 

-->  6.     <!-- defines the service class to share across DWR -->  7.     <create creator="new" javascript="EasyService">  8.       <param name="class" value="com.soaagenda.services.EasyService"/>  9.     </create>  10.     <!-- define las clases de datos que utiliza el servicio -->  11.     <!-- defines the data classes to share across DWR -->  12.     <convert converter="bean" match="com.soaagenda.valueobjects.*"/>  13.     </allow>  14. </dwr> 

6. Ahora si compilamos las clases, y publicamos nuestro ejemplo Web (deploy), DWR nos presta

una utilidad para probar que todo anda bien, esta se accede desde un Browser, en el path “/dwr/”, dentro

de nuestro sitio (ejemplo: http://localhost:8028/dwrEasy/dwr/)

Page 7: El Mejor Ejemplo DWR

Seleccionado el servicio, nos aparece primero las librerías javascript necesarias para

implementar una pagina Web, luego la lista de servicios (métodos de las clase servicio)

a los que tenemos acceso (getProducts).

Page 8: El Mejor Ejemplo DWR

Como no restringimos los métodos de la clase, incluso nos aparecen los métodos

que hereda por ser una clase Java (como hashCode, getClass).

Si presionamos el botón “Execute”, ejecuta el servicio, y para el caso de nuestro

ejemplo este retorna un error “Debe indicar ID Cliente”, lo que esta bien porque

no le hemos indicado parámetros de entrada, con esto sabemos que todo anda

bien, porque esa respuesta la da nuestra clase que esta en el servidor, es decir,

ejecutamos desde Javascript (Browser) una clase que esta del lado del servidor,

eso es Ajax y DWR!!.

7. Lo siguiente es crear nuestra pagina HTML que va a consultar los resultados y mostrarlos, esta

pagina es sumamente simple, tiene un formulario (Html Form), en realidad solo tiene las variables del

Page 9: El Mejor Ejemplo DWR

form, porque ya no es necesario el tag “<form>” (recuerden que con Ajax la forma de hacer request al

Server cambia, ahora es asíncrona), y tiene una tabla (html table) para mostrar el resultado.

dwrEasyPage.html

view plaincopy to clipboardprint?

1. < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

2. <html xmlns="http://www.w3.org/1999/xhtml">  3. <head>  4.   <title>Editable Table Demo</title>  5.   <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" 

/>  6.   <script type='text/javascript' src='/dwrEasy/dwr/interface/

EasyService.js'></script>  7.   <script type='text/javascript' src='/dwrEasy/dwr/engine.js'></script> 

8.   <script type='text/javascript' src='/dwrEasy/dwr/util.js'> </script>  9.   <script type="text/javascript" src='dwrEasyJS.js'> </script>  10. </head>  11.   12. <body> 

Page 10: El Mejor Ejemplo DWR

13. <h1>Easy DRW Demo</h1>  14.     <h3>Buscar / Search</h3>  15.   16.    <table>  17.       <tr>  18.         <td>ID Cliente / Client ID:</td>  19.         <td><input name="formClientID" type="text" id="formClientID" si

ze="15"/></td>  20.       </tr>  21.       <tr>  22.         <td>Tipo Producto / Product Type</td>  23.         <td><input name="formProductType" type="text" id="formProductTy

pe" size="15"/></td>  24.       </tr>  25.       <tr>  26.         <td colspan="2" align="right">  27.           <input type="button" value="OK" onclick="javascript:submitPro

ductsRequest()"/>  28.         </td>  29.       </tr>  30.     </table>  31.   32.     <h3>Productos / Products</h3>  33.     <p>Respuesta / Response:   34.       <input name="serviceResponse" type="text" id="serviceResponse" si

ze="50"/>  35.     </p>  36.   37.     <table border="1">  38.       <thead>  39.         <tr>  40.           <th>Codigo / BarCode</th>  41.           <th>Nombre / Name</th>  42.         </tr>  43.       </thead>  44.       <tbody id="myTable">  45.         <tr id="myPattern" style="display:none">  46.           <td>  47.             <span id="codePattern">code example</span></td>  48.           <td>  49.             <span id="namePattern">name example</span></td>  50.         </tr>  51.       </tbody>  52.     </table>  53. </body>  54. </html> 

Si analizamos el código, lo primero es la referencia a las librerías Javascript

(“EasyService.js”, “engine.js”, “util.js”), estas fueron generadas por DWR, luego

aparece la librería (“dwrEasyJS.js”) que ya es propietaria (custom), y que

debemos construir para realizar la lógica de interacción (esta redescribe a

continuación).

Luego aparecen las variables del formulario a solicitar (formClientID,

formProductType), y el botón que define la acción de consulta, ejecuta la

función Javascript “javascript: submitProductsRequest()”, esta funcion es la que

Page 11: El Mejor Ejemplo DWR

se encuentra definida en la librería (“dwrEasyJS.js), la cual vamos a tener que

contruir.

Después viene la tabla que mostrará los datos (myTable).

Podemos ver que hay ciertas características especiales en el código Html, estas

le van a servir a DWR para encontrar donde obtener, o donde mostrar los datos:

Los “Id” de los tags html le sirven a DWR para manejar los datos:

· Los id “formClientID”, “formProductType” le permiten encontrar loas

parámetros de entrada.

· El id “myTable”, le servirá para saber que tabla limpiar.

· El id “myPattern”, le indicará a DWR que filas (rows) debe “clonar” para

mostrar cada registro de producto de la lista, como es un “patrón” en

principio va oculto (style=”display:none”).

· Los id “codePattern”, “namePattern” servirán para qeu DWR sepa donde

colocar los datos de cada producto, en este caso se usan tags “<span>”.

Como vemos esta pagina es solo Html, y Javascript, que “hermosamente

simple”, nada de JSP, ni de ASP, una pagina que se puede publicar en cualquier

servidor Web.

8. Lo que sigue es la librería Javascript propia.

dwrEasyJS.js

view plaincopy to clipboardprint?

1. function submitProductsRequest() {   2.   var idX=dwr.util.getValue("formClientID");   3.   var typeX=dwr.util.getValue("formProductType");   4.   5.   var parametersX={clientID:idX,productType:typeX};   6.   7.   EasyService.getProducts(parametersX,showProducts);   8.   9.  }   10.   11. function showProducts(responseX) {  

Page 12: El Mejor Ejemplo DWR

12.   13. // borro filas excepto el patron, delete rows except pattern row   14.         dwr.util.removeAllRows("myTable", { filter:function(tr) { retur

n (tr.id != "myPattern");}});   15.   16.     if (responseX.errorCode!=0){   17.       alert('Error: '+responseX.errorDescription);   18.       return;   19.     };   20.     var productsX=responseX.products;   21.     var lengthX=productsX.length;   22.     var itemProductX;   23.   24.     if (lengthX==0){   25.       alert('No hay productos, Cant find products');   26.       return;   27.     };   28.   29.     dwr.util.setValue("serviceResponse", responseX.errorDescription);   30.   31.     var id="00";   32.     for (var i=0 ; i<lengthx ; i++)   33.         {   34.            temProductX= productsX[i];   35.            id="00"+i;   36.            dwr.util.cloneNode("myPattern", { idSuffix:id });   37.            dwr.util.setValue("codePattern" + id, itemProductX.barCode); 38.            dwr.util.setValue("namePattern" + id, itemProductX.name);   39.            $("myPattern" + id).style.display = "";   40.         }   41. } 

9. Esta librería tiene dos funciones: “submitProductsRequest” la que obtiene los parámetros de

entrada y ejecuta el servicio correspondiente (clase Java EasyService.getProducts() vía DWR), y la

función que muestra los datos (showProducts).

Finalmente hay que subir las páginas (Deploy) en el sitio Web, quedando el

proyecto con la siguiente estructura:

.

Page 13: El Mejor Ejemplo DWR

Ejecutamos la pagina de prueba “dwrEasyPage” en nuestro Browser (ejemplo

“http://localhost:8028/dwrEasy/dwrEasyPage.html”), ponemos un dato en “ID

Cliente”, presionamos “OK”, y listo!, nuestra primera aplicación Ajax-DWR.

10. The End

*******************************************************************

Ajax Facilito en Java - DWR

 Wednesday, December 24, 2008 at 2:38am

Volviendo otra vez al proyecto actual en el que estamos asignados Dani Gonzalez y yo, nos hemos encontrado con que las versiones de Portlet y de JSF utilizadas no permiten el uso de componentes con comportamiento AJAX. En versiones posteriores estos problemas tienen solución e incluso existen librerías de componentes JSF muy potentes en este sentido (ICE Faces, RichFaces, Oracle ADF) pero como todos os imagináis a los dueños de una aplicación no suele gustarles que les digas que vas a invertir un tiempecito migrando a una nueva versión de algo que no conocen y que además para utilizarla es necesario cambiar la versión del servidor de aplicaciones en producción… así que hemos tenido que “invertar” alguna cosa, para dar ese comportamiento dinámico que nos requería el usuario final. Concretamente la primera petición de nuestros usuarios vino para recuperar la irradiación (cantidad de sol recibido por un punto de la superficie terrestre) a partir de las coordeandas seleccionadas por el usuario en un mapa (en este caso generado con Google Maps) sin necesidad de realizar un submit y recargar toda la página…

Estuvimos viendo distintas alternativas como dojo (aunque se caracteriza más por su librería de componentes gráficos javascript también tiene funcionalidad para realizar llamadas ajax), prototype, el uso del objeto XMLHttpRequest, y otros aunque finalmente nos decidimos por DWR dada la facilidad con la que se puede utilizar en un entorno Java. En realidad, después de un poco de tiempo trabajando con DWR coincido bastante con la forma en que ellos se definen en su site: “DWR es una librería java que permite al código java ejecutado en un servidor de aplicaciones y al código Javascript ejecutado en un navegador interactuar entre ambos de la manera más simple posible” y su eslogan es: “DWR is Easy Ajax for Java”

Bueno, a grandes rasgos nos encontramos con dos piezas que son necesarias para que esto funcione:

Un servlet java ejecutándose en el servidor que procesa las peticiones Ajax recibidas y devuelve la respuesta al navegador

Una librería javascript en el navegador utilizada para enviar peticiones al servidor y recibe las respuestas desde éste para actualizar la página que se muestra

Page 14: El Mejor Ejemplo DWR

Vale y como funciona realmente?

DWR genera dinámicamente el código javascript para que cada una de las clases java de servidor expuestas como servicios AJAX puedan ser accedidas desde javascript. Es decir el javascript generado por DWR crea un objeto javascript que puede ser referenciado desde cualquier parte de nuestro código js en el navegador.

El objeto creado se encarga de abstraernos de la comunicación con el servidor. Cuando se invoca a alguno de los métodos javascript ofrecidos se desencadena una llamada al servidor en la que DWR se encarga del envío y recepción (marshalling / unmarshalling) de los parámetros de forma transparente.

Y aquí tenemos un diagrama sencillo de como funciona.

Si queréis ver un ejemplo muy sencillo de lo que hay que hacer para poner esto a funcionar podéis ir a un tutorial en la página oficial de DWR

A partir de la versión 2 (la actual es la 3) ofrece una funcionalidad que ellos llaman “reverse ajax” que permite realizar acciones “push” al estilo comet… También ofrecen dentro de la librería javascript un conjunto de funciones de utilidad para manejar los objetos HTML / JS en cliente / navegador. Y parece que también están trabajando en integrarse con algunos frameworks de componentes de interfaz de usuario como Dojo o Yahoo YUI .

En mi opinión hay otros frameworks / especificaciones que ofrecen una solución completa cubriendo el ciclo de peticiones en servidor (como por ejemplo JSF), pero para algo rápido, sencillo y fácil merece la pena… y si finalmente se integran con alguno de los frameworks de componentes gráficos que hemos dicho antes no habría que perderles la pista…