guia_dwr

48
CURSO DE DIRECT WEB REMOTING (DWR) 1 Guía con Ejemplos Guía sobre DWR con Ejemplos 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 más 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 está en Java, DWR es una de las 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 artículo, 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 está basado en Servlets, en otras palabras gracias a DWR no necesitamos

Upload: jcortmx

Post on 12-Feb-2016

5 views

Category:

Documents


0 download

DESCRIPTION

Tutorial basico de uso de DWR

TRANSCRIPT

Page 1: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

1 Guía con Ejemplos

Guía sobre DWR con Ejemplos

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 más 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 está en

Java, DWR es una de las 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

artículo, 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 está basado en

Servlets, en otras palabras gracias a DWR no necesitamos

Page 2: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

2 Guía con Ejemplos

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 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 páginas Web con los resultados.

Sí, 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, además

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

ningún objeto grafico pre-hecho, pero si nos permite la

flexibilidad para hacer cualquier cosa con el HTML.

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

Esta guía cumple con lo siguiente:

Page 3: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

3 Guía con Ejemplos

Es lo más 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.

Page 4: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

4 Guía con Ejemplos

DWR en 10 Simples Pasos

1. Lo primero es bajar DWR de la dirección mostrada a

continuación: (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:

01.< ?xml version="1.0" encoding="UTF-8"?> 02.< !DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> 03.<web_app> 04. <display_name>dwrEasy</display_name> 05. <servlet> 06. <servlet_name>dwr-invoker</servlet_name> 07. <display_name>DWR Servlet</display_name> 08. <description>Direct Web Remoter Servlet</description> 09. <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>

Page 5: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

5 Guía con Ejemplos

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 tiene que ser

necesariamente un servidor J2EE.

La Clase EasyService, se muestra en la Siguiente página:

Page 6: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

6 Guía con Ejemplos

EasyService.java:

01.package com.soaagenda.services; 02. 03.import com.soaagenda.valueobjects.*; 04. 05.public class EasyService { 06.public EasyService() { 07.} 08. 09.public EasyResponse getProducts(EasyParameter parametersX){ 10.EasyResponse responseX= new EasyResponse(); 11. 12. 13.// si parametros vacios devuelve error, error if empty parameters 14.if (parametersX==null || parametersX.getClientID()==null || parametersX.getClientID().length()< =0){ 15.responseX.setErrorCode(10001); 16.responseX.setErrorDescription("Debe indicar ID Cliente. Give us Client ID"); 17.return responseX; 18.} 19. 20.//crea lista productos del cliente, fill the client product list 21.//para ejemplo en duro, for the example fixed data 22.Product[] productsListX= new Product[2]; 23. 24.Product productX= new Product(); 25.productX.setBarCode("0001"); 26.productX.setName("Tarjeta Visa, Visa Credit Card"); 27.productsListX[0]= productX; 28. 29.productX= new Product(); 30.productX.setBarCode("0002"); 31.productX.setName("Tarjeta American Express, American Express Credit Card"); 32.productsListX[1]= productX; 33. 34.//respuesta exitosa, sucessfull response 35.responseX.setErrorCode(0); 36.responseX.setErrorDescription("Consulta Banco Exitosa, Succesfull Bank Query"); 37.responseX.setProducts(productsListX); 38. 39.return responseX; 40.} 41.}

Page 7: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

7 Guía con Ejemplos

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 Créditos 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.

01.package com.soaagenda.valueobjects; 02. 03.public class EasyParameter { 04.private String clientID; 05.private String productType; 06.public EasyParameter() { 07.} 08. 09.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() { 22.return productType; 23.} 24.}

Page 8: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

8 Guía con Ejemplos

EasyResponse.java: define la estructura para los resultados

del servicio.

01.package com.soaagenda.valueobjects; 02. 03.public class EasyResponse { 04.private int errorCode; 05.private String errorDescription; 06.private Product[] products; 07. 08.public EasyResponse() { 09.} 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.}

Page 9: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

9 Guía con Ejemplos

Product.java: define la estructura de un producto.

01.package com.soaagenda.valueobjects; 02. 03.public class Product { 04.private String barCode; 05.private String name; 06.public Product() { 07.try { 08.jbInit(); 09.} 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; 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.}

Page 10: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

10 Guía con Ejemplos

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

01.< ?xml version="1.0" encoding="UTF-8"?> 02.< !DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd"> 03.<dwr> 04.<allow> 05.<!-- define la clase de servicios que se va a publicar mediante DWR --> 06.<!-- defines the service class to share across DWR --> 07.<create creator="new" javascript="EasyService"> 08.<param name="class"value="com.soaagenda.services.EasyService"/> 09.</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>

Page 11: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

11 Guía con Ejemplos

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/)

Seleccionado el servicio, nos aparece primero las librerías

javascript necesarias para implementar una página Web,

luego la lista de servicios (métodos de las clase servicio) a los

que tenemos acceso (getProducts).

Page 12: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

12 Guía con Ejemplos

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 está 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 está en el servidor, es decir,

ejecutamos desde Javascript (Browser) una clase que

está del lado del servidor, eso es Ajax y DWR!!.

Page 13: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

13 Guía con Ejemplos

7. Lo siguiente es crear nuestra página HTML que va a consultar

los resultados y mostrarlos, esta página es sumamente

simple, tiene un formulario (Html Form), en realidad solo

tiene las variables del 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.

Page 14: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

14 Guía con Ejemplos

dwrEasyPage.html

01.< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 02.<html xmlns="http://www.w3.org/1999/xhtml"> 03.<head> 04.<title>Editable Table Demo</title> 05.<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> 06.<script type='text/javascript'src='/dwrEasy/dwr/interface/EasyService.js'></script> 07.<script type='text/javascript' src='/dwrEasy/dwr/engine.js'></script> 08.<script type='text/javascript' src='/dwrEasy/dwr/util.js'> </script> 09.<script type="text/javascript" src='dwrEasyJS.js'> </script> 10.</head> 11. 12.<body> 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" size="15"/></td> 20.</tr> 21.<tr> 22.<td>Tipo Producto / Product Type</td> 23.<td><input name="formProductType" type="text"id="formProductType" size="15"/></td> 24.</tr> 25.<tr> 26.<td colspan="2" align="right"> 27.<input type="button" value="OK"onclick="javascript:submitProductsRequest()"/> 28.</td> 29.</tr> 30.</table> 31. 32.<h3>Productos / Products</h3> 33.<p>Respuesta / Response: 34.<input name="serviceResponse" type="text"id="serviceResponse" size="50"/> 35.</p>

Continúa…

.

Page 15: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

15 Guía con Ejemplos

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 función es la

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

la cual vamos a tener que construir.

Después viene la tabla que mostrará los datos

(myTable).

Page 16: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

16 Guía con Ejemplos

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 dónde colocar los datos de cada

producto, en este caso se usan tags “<span>”.

Como vemos esta página es solo Html, y Javascript, que

“hermosamente simple”, nada de JSP, ni de ASP, una

página que se puede publicar en cualquier servidor Web.

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

Page 17: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

17 Guía con Ejemplos

dwrEasyJS.js

01.function submitProductsRequest() { 02.var idX=dwr.util.getValue("formClientID"); 03.var typeX=dwr.util.getValue("formProductType"); 04. 05.var parametersX={clientID:idX,productType:typeX}; 06. 07.EasyService.getProducts(parametersX,showProducts); 08. 09.} 11. 12.function showProducts(responseX) { 13. 14.// borro filas excepto el patron, delete rows except pattern row 15.dwr.util.removeAllRows("myTable", { filter:function(tr) {return (tr.id != "myPattern");}}); 16. 17.if (responseX.errorCode!=0){ 18.alert('Error: '+responseX.errorDescription); 19.return; 20.}; 21.var productsX=responseX.products; 22.var lengthX=productsX.length; 23.var itemProductX; 24. 25.if (lengthX==0){ 26.alert('No hay productos, Cant find products'); 27.return; 28.}; 29. 30.dwr.util.setValue("serviceResponse", responseX.errorDescription); 31. 32.var id="00"; 33.for (var i=0 ; i<lengthx ; i++) { 35.temProductX= productsX[i]; 36.id="00"+i; 37.dwr.util.cloneNode("myPattern", { idSuffix:id }); 38.dwr.util.setValue("codePattern" + id, itemProductX.barCode); 39.dwr.util.setValue("namePattern" + id, itemProductX.name); 40.$("myPattern" + id).style.display = ""; 41.} 42.}

Page 18: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

18 Guía con Ejemplos

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:

.

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

Page 19: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

19 Guía con Ejemplos

OTROS EJEMPLOS

AJAX es un acrónimo que significa "Asynchonous JavaScript XML". En si, AJAX es una técnica de programación web mediante la cual una página web puede intercambiar información con el servidor en forma asincrónica, de manera tal que la página puede actualizarse sin necesidad de ser recargada. El cliente (browser con la página web) y el servidor mantienen una

comunicación asincrónica y en background. AJAX es netamente JavaScript pero en este capítulo vamos a explicar un framework que permite invocar desde JavaScript (browser, cliente) métodos remotos, en el servidor implementados en Java.

Manipulación de Objetos HTML

Como vemos, DWR resuelve de manera extremadamente

simple la invocación remota de métodos entre la página HTML

(o JSP) y la clase Java que los implementa. Por lo tanto la

mayor complejidad está dada en poder actualizar

dinámicamente el contenido HTML con la información que

llega desde el servidor.

Para esto DWR provee una librería de funciones JavaScript

llamada: util.js. Veremos algunos ejemplos de cómo

actualizar contenido dinámicamente utilizando esta librería.

Page 20: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

20 Guía con Ejemplos

Combos Dependientes

En este ejemplo veremos cómo actualizar el contenido de un

combo dependiendo de lo que el usuario selecciona en otro

combo.

Para esto programamos la siguiente clase que basicamente

proveerá dos métodos:

Collection obtenerArtistas();

Collection obtenerDiscos(String artista);

Es decir: el primer método retornará una Collection de Strings

con los nombres de los artistas "registrados en una base de

datos" y el segundo método, dado un nombre de artista

retornará todos los discos de ese artista que "tenemos

registrados".

Para simplificar, los datos los hardcodearemos en una

Hashtable.

CatalogoCD.java

1: 2:package test; 3:import java.util.*; 4: 5:public class CatalogoCD 6:{ 7: private Hashtable artistas; 8: 9: public CatalogoCD() 10: { 11: artistas=new Hashtable(); 12: _cargarInformacion(); 13: } 14:

Page 21: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

21 Guía con Ejemplos

15: // retorna una Collection de Strins con los 16: // artistas que tenemos registrados 17: public Collection obtenerArtistas() 18: { 19: Vector v=new Vector(); 20: for(Enumeration e=artistas.keys() 21: ;e.hasMoreElements();) 22: { 23: v.add(e.nextElement()); 24: } 25: return v; 26: } 27: 28: // dado un artista, retorna una Collection de 29: // Strings con los titulos de los discos del 30: // artista especificado 31: public Collection obtenerDiscos(String artista) 32: { 33: return (Collection) artistas.get(artista); 34: } 35: 36: // todo harcodeado... 37: private void _cargarInformacion() 38: { 39: Vector v1=new Vector(); 40: v1.add("Please Please Me"); 41: v1.add("Abbey Road"); 42: v1.add("Magical Mistery Tour"); 43: artistas.put("The Beatles",v1); 44: 45: Vector v2=new Vector(); 46: v2.add("Demasiado Ego"); 47: v2.add("La Hija de la Lagrima"); 48: v2.add("Say No More"); 49: v2.add("Kill Gil"); 50: artistas.put("Charly Garcia",v2); 51: 52: // sexo Ibiza Locomia...! 53: Vector v3=new Vector(); 54: v3.add("A Ibiza con Locomia"); 55: v3.add("Abanicos Por Doquier!"); 56: artistas.put("Locomia",v3); 57: } 58:} 59:

Page 22: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

22 Guía con Ejemplos

Para registrar la clase como servicio en DWR tenemos que

agregar las siguientes líneas en el archivo dwr.xml.

1: 2: <create creator="new" javascript="CatalogoCD"> 3: <param name="class" value="test.CatalogoCD"/> 4: </create> 5:

Ahora vamos a:

http://localhost:8080/[YOUR-WEBAPP]/dwr/test/CatalogoCD

Para ver los scripts que debemos incluir en la página JSP.

Y ahora veamos la página JSP:

Page 23: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

23 Guía con Ejemplos

discos.jsp 1:

2:<html>

3: <head>

4: <script

5: type='text/javascript'

6: src='/TestAjax/dwr/interface/CatalogoCD.js'>

7: </script>

8: <script

9: type='text/javascript'

10: src='/TestAjax/dwr/engine.js'>

11: </script>

12: <script

13: type='text/javascript'

14: src='/TestAjax/dwr/util.js'>

15: </script>

16:

17: <script>

18: function obtenerArtistas()

19: {

20: CatalogoCD.obtenerArtistas(function(data){

21: dwr.util.removeAllOptions("cbArtista");

22: dwr.util.addOptions("cbArtista", data);

23: obtenerDiscos();

24: });

25: }

26:

27: function obtenerDiscos()

28: {

29: var art = dwr.util.getValue("cbArtista");

30: CatalogoCD.obtenerDiscos(art,function(data)

31: {

32: dwr.util.removeAllOptions("cbDisco");

33: dwr.util.addOptions("cbDisco", data);

34: });

35: }

36: </script>

37: </head>

38:

39: <body>

40: <input type="button"

41: value="Cargar"

42: onclick="obtenerArtistas()" />

43: <select id="cbArtista"

44: onChange="obtenerDiscos()" />

45: <select id="cbDisco" />

46: </body>

47:</html>

48:

Page 24: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

24 Guía con Ejemplos

Como vemos, la página en si comienza a partir de la línea 39.

Tenemos dos select (combos), uno con id="cbArtista" y el

otro con id="idDisco" y un button.

En el evento onclick del botón invocamos a la función

obtenerArtistas, y en el evento onChange del combo de

artistas invocamos a la funciónobtenerDiscos.

Analicemos entonces la función obtenerArtistas (que se

encuentra a partir de la línea 18).

17: 18: function obtenerArtistas() 19: { 20: CatalogoCD.obtenerArtistas(function(data){ 21: dwr.util.removeAllOptions("cbArtista"); 22: dwr.util.addOptions("cbArtista", data); 23: obtenerDiscos(); 24: }); 25: } 26:

La función invoca a CatalogoCD.obtenerArtistas pasándole

una función callback en la que primero removemos todos los

items del combo y luego seteamos en el combo de artistas la

colección que retorna el método Java. Por último invocamos a

la función obtenerDiscos para cargargar los discos del artistas

que quedó seleccionado.

El código de la función obtenerDiscos está a partir de la línea

27 y lo podemos ver a continuación.

Page 25: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

25 Guía con Ejemplos

26: 27: function obtenerDiscos() 28: { 29: var art = dwr.util.getValue("cbArtista"); 30: CatalogoCD.obtenerDiscos(art,function(data) 31: { 32: dwr.util.removeAllOptions("cbDisco"); 33: dwr.util.addOptions("cbDisco", data); 34: }); 35: } 36:

En esta función tomamos el valor que se encuentra

seleccionado en el combo de artistas y lo asignamos a la

variable art. Luego invocamos a la función

CatalogoCD.obtenerDiscos pasándole art y una función

callback dentro de la cual borramos los items del combo de

discos y seteamos en dicho combo la colección que retorna el

método Java.

El resultado será:

Page 26: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

26 Guía con Ejemplos

AJAX con DWR en NetBeans 6.1

Una de las bibliotecas más fáciles que he visto para

programar en AJAX es el Direct Web Remoting - DWR.

En este capítulo veremos algunas de sus características que

nos ayudará a tener aplicaciones enriquecidas con Ajax. Para

ello usaremos:

1. NetBeans 6.1

2. DWR

Instalando DWR en NetBeans

La biblioteca DWR consta únicamente de un archivo .jar. Este

lo podemos descargar de aquí:

http://getahead.org/dwr/download.

Guardaremos el archivo en una carpeta que será destinada

para las bibliotecas de los proyectos. Yo, en Windows, lo

guardo en d:\proys\lib\DWR, y en Linux lo guardo en

~/proys/lib

Adicionalmente DWR necesita de la biblioteca

commons-logging.

Esta la puedes descargar de aquí:

http://commons.apache.org/downloads/download_logging.cgi

Page 27: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

27 Guía con Ejemplos

Descomprimamos el archivo descargado de commons-logging

en la misma carpeta lib.

Entramos a la opción Tools > Libraries:

Hacemos clic en "New Library" para crear una nueva

biblioteca, y llamaremos DWR.

Clic en OK. Ahora agregamos los archivos .jar

correspondientes.

Page 28: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

28 Guía con Ejemplos

Hacemos clic en Add Jar/Folder y seleccionamos el archivo

commons-logging-1.1.1.jar y dwr.jar

Clic en OK parar cerrar la ventana.

El proyecto Web

Ahora crearemos un aplicación web, que no usará ningún

framework. Será una aplicación totalmente "simple". La

llamaremos DwrSamples.

En las propiedades del proyecto web creado, entramos a sus

propiedades haciendo clic derecho sobre el ícono del proyecto,

y seleccionamos "Properties". En esta ventana seleccionamos

del margen izquierdo la categoría "Libraries". Luego

agregamos la biblioteca DWR haciendo clic en el botón "Add

Library". Después de esto, deberá lucir así:

Page 29: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

29 Guía con Ejemplos

Crearemos una clase a la que llamaremos Calculadora y

estará en el paquete logica. Esta clase, básicamente, tendrá

los métodos que realizarán las operaciones de manera

asíncrona.

package logica; public class Calculadora { public int sumar(int a, int b) { return a + b; } public int restar(int a, int b) { return a - b; } }

Page 30: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

30 Guía con Ejemplos

Ahora, necesitamos que esta clase sea leíble por DWR, por lo

que usaremos anotaciones para "publicar" la clase como

objeto javascript, pero sólo publicaremos el método sumar()

para que sea ajax. Usaremos la anotación de DWR

@RemoteProxy para la clase Calculadora, y @RemoteMethod

para el método sumar(). Deberá lucir así:

package logica; import org.directwebremoting.annotations.RemoteMethod; import org.directwebremoting.annotations.RemoteProxy; @RemoteProxy public class Calculadora { @RemoteMethod public int sumar(int a, int b) { return a + b; } public int restar(int a, int b) { return a - b; } }

Ahora, abrirmos el archivo web.xml (podemos presionar

Shift + Alt + O para abrir el buscador de archivos y escribir

web para que nos seleccione el archivo que estamos

buscando). En la barra superior hacemos clic en el botón

"Servlets" para visualizar los servlets de nuestra aplicación.

Una vez allí, hacemos clic en el botón "Add Servlet".

Page 31: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

31 Guía con Ejemplos

El nuevo servlet que crearemos, le pondremos el nombre

"DWR", la clase del servlet será:

"org.directwebremoting.servlet.DwrServlet", y el patrón URL

será "/dwr/*", es decir, este serlet responderá las peticiones

en la dirección "/dwr/". Deberá lucir esta ventana así:

Hacemos clic en "OK". Luego, agregaremos un parámetro de

inicio. Hacemos clic en el botón "Add.." de la sección

"Initialization Parameter".

El parámetro de inicio lo llamaremos classes, y tendrá una

clase llamada logica.Calculadora.

Page 32: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

32 Guía con Ejemplos

Clic en OK, y deberá lucir así la ventana de los servlets.

Page 33: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

33 Guía con Ejemplos

O si lo prefieres en xml, el archivo web.xml deberá lucir así.

Ahora, crearemos nuestra interfaz. Abrimos el archivo

index.jsp, le pondremos un formulario:

<h2>Calculadora</h2> <form action=""> Valor 1: <input type="text" name="valor1" id="valor1"/><br/> Valor 2: <input type="text" name="valor2" id="valor2"/><br/> <input type="button" value="Sumar" onclick="sumar()"/><br/> Resultado:<div id="suma"></div> </form>

Page 34: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

34 Guía con Ejemplos

Nota que el botón no es un submit, sino un tipo "button".

Tampoco hay que olvidar los atributos id de los tags. Estos

nos ayudarán a identificar un tag en toda la página.

Ahora, necesitamos importar las bibliotecas de DWR. Para

ello, agregamos las siguientes lineas en la cabecera del jsp.

<script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/interface/Calculadora.js"></script> <script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/engine.js"></script> <script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/util.js"></script>

Nota que estos javascript están bajo la carpeta /dwr, que es

el servlet que hemos creado párrafos arriba. Además, hay un

Calculadora.js, que tiene el mismo nombre de nuestra clase

java que hemos creado.

Crearemos la función sumar() que es llamada desde el botón

"sumar" de nuestro formulario:

function sumar(){ var valor1=dwr.util.getValue("valor1"); var valor2=dwr.util.getValue("valor2"); Calculadora.sumar(valor1,valor2,mostrarSuma); }

Page 35: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

35 Guía con Ejemplos

En las dos primeras líneas estamos obteniendo los valores de

los tag "valor1" y "valor2". Este nombre es el nombrado en

los atributos id de los input:text. Por ello es importante que

los ID identifiquen a un único tag en toda la página.

La tercera linea llama al objeto Calculadora. Este objeto es el

que DWR creó como contraparte a nuestra clase java

Calculadora.

Nota que llama al método sumar() y recibe tres parámetros.

Los dos primeros son los mismos parámetros que hemos

declarado en nuestra clase java Calculadora. Pero el tercer

parámetro, que se llama mostrarSuma, es el nombre de una

función en javascript que se encargará de recibir y manejar el

resultado que devuelto por el método sumar() de java. Así es

la convención de DWR. Notar que se le está pasando solo el

nombre, sin paréntesis.

La función javascript mostrarSuma() será la siguiente:

function mostrarSuma(resultado){ dwr.util.setValue("suma",resultado); }

Page 36: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

36 Guía con Ejemplos

Vemos que el resultado devuelto por el método de java

sumar() es el parámetro de esta función javascript. Tomamos

el valor y lo mostramos en el tag que tiene nombre "suma"

(que es un <div>).

El index.jsp completo es el siguiente:

<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> <script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/interface/Calculadora.js"></script> <script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/engine.js"></script> <script type="text/javascript" src="<%=pageContext.getServletContext().getContextPath() %>/dwr/util.js"></script> <script type="text/javascript"> function sumar(){ var valor1=dwr.util.getValue("valor1"); var valor2=dwr.util.getValue("valor2"); Calculadora.sumar(valor1,valor2,mostrarSuma); } function mostrarSuma(resultado){ dwr.util.setValue("suma",resultado); } </script> </head>

Page 37: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

37 Guía con Ejemplos

<body> <h2>Calculadora</h2> <form action=""> Valor 1: <input type="text" name="valor1" id="valor1"/><br/> Valor 2: <input type="text" name="valor2" id="valor2"/><br/> <input type="button" value="Sumar" onclick="sumar()"/><br/> Resultado:<div id="suma"></div> </form> </body> </html>

Lo corremos y probamos:

¡Magia!

Page 38: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

38 Guía con Ejemplos

Con base de datos

A esta altura verás la simpleza del DWR, y que una aplicación

con base de datos no sería de lo más difícil. Haríamos una

clase que accede la base de datos y lo muestre en la web.

Pero ¿cómo lo mostramos en una tabla?. Aquí mostraremos el

ejemplo:

Crearemos una clase llamada PersonasService y lo

guardaremos en el paquete logica. Esta clase tendrá la

anotación@RemoteProxy pero con un parámetro que

cambiará el nombre del objeto javascript. Es decir, no se

llamaráPersonasService en javascript, sino, se llamará

solamente Personas.

package logica; import org.directwebremoting.annotations.RemoteProxy; @RemoteProxy(name = "Personas") public class PersonasService { }

Page 39: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

39 Guía con Ejemplos

Ahora, crearemos un método llamado getLista() que

devolverá una lista de objetos Persona que tendrá los

registros de la base de datos. Para ello, primero crearemos la

clase beans.Persona.

package beans; import java.util.Date; public class Persona { private int id; private String nombre; private String titulo; private boolean viajeroFrecuente; private Date ultimaActualizacion; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; }

Page 40: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

40 Guía con Ejemplos

public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public Date getUltimaActualizacion() { return ultimaActualizacion; } public void setUltimaActualizacion(Date ultimaActualizacion) { this.ultimaActualizacion = ultimaActualizacion; } public boolean isViajeroFrecuente() { return viajeroFrecuente; } public void setViajeroFrecuente(boolean viajeroFrecuente) { this.viajeroFrecuente = viajeroFrecuente; } }

Por alguna razón, los beans con anotaciones no son

convertidos por DWR a objetos JavaScript. Al menos con esta

versión. He seguido la documentación que indica cómo usar

un bean con @DataTransferObject y nada. Si alguien lo puede

lograr, lo agradeceré un montón.

Pero para poder enviar beans en DWR, crearemos un archivo

llamado dwr.xml y lo guardamos dentro del directorio WEB-

INF (en la misma ubicación del archivo web.xml). En ese

archivo colocaremos lo siguiente:

Page 41: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

41 Guía con Ejemplos

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://directwebremoting.org/schema/dwr20.dtd"> <dwr> <allow> <convert converter="bean" match="beans.Persona"> </convert> </allow> </dwr>

Ahora, volvemos a la clase PersonasService. Hacemos clic

derecho sobre el fondo del código fuente, y seleccionamos

Enterprise Resource > Use Database.

Hacemos clic en el botón "Add"

Page 42: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

42 Guía con Ejemplos

Pondremos como nombre de la referencia, el valor de

travelDS. Además, hacemos clic en el botón "Add" de "Project

Data sources", escribimos el nombre del JNDI jdbc/travel y

seleccionamos de la lista el URL del JDBC referido a la base de

datos travel.

Clic en OK

Clic en OK

Page 43: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

43 Guía con Ejemplos

Clic en OK

Veremos que NetBeans nos ha creado un método llamado

getTravelDS()

private DataSource getTravelDS() throws NamingException { Context c = new InitialContext(); return (DataSource) c.lookup("java:comp/env/travelDS"); }

Pues ya con esto, podemos hacer nuestro manejo a la base

de datos.

Ahora sí, crearemos el método getLista():

Page 44: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

44 Guía con Ejemplos

@RemoteMethod public List<Persona> getLista() { try { DataSource ds = getTravelDS(); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM person"); List<Persona> lista = new ArrayList<Persona>(); while (rs.next()) { Persona p = new Persona(); p.setId(rs.getInt("PERSONID")); p.setNombre(rs.getString("NAME")); p.setTitulo(rs.getString("JOBTITLE")); p.setViajeroFrecuente(rs.getBoolean("FREQUENTFLYER")); p.setUltimaActualizacion(rs.getDate("LASTUPDATED")); lista.add(p); } return lista; } catch (SQLException ex) { Logger.getLogger(PersonasService.class.getName()).log(Level.SEVERE, null, ex); } catch (NamingException ex) { Logger.getLogger(PersonasService.class.getName()).log(Level.SEVERE, null, ex); } return null; }

La interfaz web

Ahora, para terminar, lo más importante de una aplicación: la

interfaz web.

Crearemos una tabla donde se colocarán los datos de los

registros obtenidos de la base de datos. Esta tabla será así:

Page 45: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

45 Guía con Ejemplos

<input type="button" onclick="mostrarPersonas()" value="Mostrar personas"/> <input type="button" onclick="limpiarCuadro()" value="Limpiar cuadro"/> <table border="1"> <thead> <tr> <th>ID</th> <th>Nombre</th> <th>Cargo</th> </tr> </thead> <tbody id="personas"> <tr id="pattern" style="display:none"> <td id="id"></td> <td id="nombre"></td> <td id="titulo"></td> </tr> </tbody> </table>

Nota que hay una fila que está invisible

(style="display:none"). Esta será nuestra plantilla llamada

"pattern". Cuando llenemos los datos de la base de datos, lo

que haremos será duplicar esta fila por cada registro.

Vemos también que hay un botón que se llama "Mostrar

Personas" que llama a la función JavaScript

mostrarPersonas(), que es la está aquí:

Page 46: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

46 Guía con Ejemplos

function mostrarPersonas(){ Personas.getLista(listarPersonas); }

Es decir, estamos llamando al método getLista() del objeto

JavaScript Personas que el DWR creó. El método

correspondiente en java no tiene parámetros, pero aquí

estamos pasándole un argumento. Este argumento es el

nombre de la función JavaScript que procesará el resultado

devuelto por el método java. Y la función listarPersonas() está

aquí:

function listarPersonas(data){ limpiarCuadro(); for(var i=0;i<data.length;i++){ fila=data[i]; var $id=fila.id; dwr.util.cloneNode("pattern",{idSuffix:$id}); dwr.util.setValue("id"+$id,fila.id); dwr.util.setValue("nombre"+$id,fila.nombre); dwr.util.setValue("titulo"+$id,fila.titulo); $("pattern"+$id).style.display=""; } }

Lo que primero hace es limpiar el cuadro (luego presento la

función que limpia la tabla). Vemos también que está

recibiendo un parámetro. Como vimos en el ejemplo anterior,

este es el resultado que está devolviendo el objeto java.

Lo que hacemos es recorrer todas filas de la lista, tomamos

una fila y obtenemos el ID de ese objeto.

Page 47: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

47 Guía con Ejemplos

Este ID nos permitirá identificar a esa única fila, porque

sabemos que cada ID de la tabla es única.

Luego clonamos la plantilla:

dwr.util.cloneNode("pattern",{idSuffix:$id});

Al clonarla, hacemos que el ID de la fila creada tenga como

subfijo el ID del objeto java. Es decir, al clonar una fila, toda

la fila queda idéntica al patrón, incluyendo los nombres de los

ID, que según el patrón es "pattern". Si el primero registro de

la tabla tiene el valor "1" en el campo "ID", cuando clone la

fila pondrá como nombre del ID "pattern" y terminará con el

valor "1", o sea, se llamará finalmente "pattern1", y las celdas

"nombre1", "titulo1" . Para la segunda fila será "pattern2" y

las celdas "nombre2","titulo2"... y así sucesivamente.

Ya clonamos la fila pattern, ahora colocaremos los valores a

cada celda. Como ya tenemos el ID unico de cada celda,

simplemente colocaremos el valor en ellas

dwr.util.setValue("id"+$id,fila.id); dwr.util.setValue("nombre"+$id,fila.nombre); dwr.util.setValue("titulo"+$id,fila.titulo);

Pero como también se clonó el estilo - que indica que debe

estar oculto - le indicamos que se muestre.

$("pattern"+$id).style.display="";

...y listo.

A continuación las funciones que borran el contenido de la

tabla:

Page 48: Guia_DWR

CURSO DE DIRECT WEB REMOTING (DWR)

48 Guía con Ejemplos

function limpiarCuadro(){ dwr.util.removeAllRows("personas",{filter:filtroBorrado}); } function filtroBorrado(tr){ return (tr.id!="pattern"); }

Existe la función filtroBorrado() para evitar que la fila

"pattern" sea borrada. Si no, ¿cómo hacemos la clonación?

Y el resultado es el ya esperado...

Para terminar...

Revisa la documentación de DWR, ahí encontrarás muchas

cosas muy interesantes.