JSON-RPC-Java: comunicaciones Ajax transparentes. Tutorial completo y ejemplos

Tras publicar dos artículos sobre el tema y dado el interés que despierta esta tecnología en la comunidad, hemos decidido realizar un tutorial exhaustivo que examine las posibilidades de JSON-RPC-Java con las explicaciones, snippets y ejemplos para que podáis incorporarla a vuestros proyectos.

JSON-RPC-Java es una tecnología que permite realizar comunicaciones Ajax entre el cliente y el servidor J2EE, hacer llamadas a funciones de clases Java desde JavaScript, con capacidad para serializar objetos Java y convertirlos en objetos JavaScript y todo ello, de forma transparente al programador.

Funcionamiento básico

Para comprender el funcionamiento de JSON-RPC-Java se debe comprender tanto el funcionamiento de la parte de servidor como del cliente JavaScript.

Desde el punto de vista del servidor Java lo primero es desarrollar las clases que serán accesibles desde el cliente. Para hacer públicos sus métodos y funciones debemos registrar una instancia de nuestra clase en un objeto JSONRPCBridge que previamente habremos creado y guardado en la sesión HTTP. Este objeto es el encargado, junto a un Servlet que más adelante aprenderemos a instalar, de comunicar a JavaScript la estructura de nuestras clases y de gestionar la comunicación entre ambas partes.

Desde el punto de vista del cliente solo es necesario incluir el cliente para JavaScript de JSON-RPC, crear una instancia de la classe JSON-RPC (que recibe como parametro la dirección del Servlet mencionado anteriormente) y llamar a nuestra función Java desde JavaScript.

Desarrollando clases para la interacción

Las clases que sirven para comunicar no deben cumplir ningún requisito especial. Así podemos utilizar cualquier clase que ya hayamos desarrollado o alguna desarrollada específicamente para la interacción con el cliente Web. Recomiendo que las clases que se hagan accesibles estén específicamente diseñadas para JSON-RPC-Java. Estas clases permitirán ejecutar las acciones y obtener los datos necesarios en cada caso con el mínimo numero de comunicaciones HTTP, mejorando así la eficiencia. Además, al estar específicamente diseñadas, no permitirán ejecutar funciones de negocio que comprometan la seguridad del sistema.

Nosotros utilizaremos para nuestros ejemplos una clase especialmente diseñada lo suficientemente sencilla como para mostrar el funcionamiento del framework sin intromisiones. Más tarde añadiremos más funciones, para nuestro primer ejemplo en Devolviendo tipos simples su implementación es la siguiente:

public class Foo {
  public int getInteger() {
    return 2;
  }
  public boolean getBoolean() {
    return true;
  }
  public String getString(){
    return "Hola, mundo!";
  }
}

Instalación

La instalación del sistema es muy sencilla. Primero debéis descargar la distribución. Para los ejemplos contenidos en este tutorial utilizaremos la versión 1.0.1 que podéis descargar aquí. Que descomprimiremos en nuestro disco duro.

De la distribución nos interesan dos archivos: la librería Java y el cliente JavaScript. El primero lo encontraremos en la raíz del directorio donde descomprimimos la distribución con el nombre jsonrpc-1.0.jar y lo debemos copiar en el directorio /WEB-INF/lib de nuestra aplicación. El segundo lo encontraremos en /webapps/jsonrpc/jsonrpc.js y lo deberemos copiar en un directorio para que pueda enlazarse en las páginas HTML, como por ejemplo en /js.

Debemos configurar un Servlet que será el encargado de comunicar al código JavaScript la estructura de nuestras clases compartidas. Para ello debemos incluir en nuestro archivo /WEB-INF/web.xml:

<servlet>
  <servlet-name>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-name>
  <servlet-class>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-name>
  <url-pattern><strong>/JSON-RPC</strong></url-pattern>
</servlet-mapping>

Es importante recordar la URL que hemos asignado a este Servlet, pues más tarde, para inicializar el cliente JavaScript, nos será necesaria.

El siguiente paso es informar al Servlet de cuales son nuestras clases. Solo es necesario registrar las clases una vez en cada sesión. Aunque existen formas de registrar clases desde un JSP, nosotros recomendamos, por claridad en el código, hacerlo desde un Servlet. Para ello utilizamos la clase JSONRPCBridge. Mantendremos una instancia de JSONRPCBridge por cada sesión, con el código:

HttpSession session = request.getSession();
JSONRPCBridge json_bridge = null;
json_bridge = (JSONRPCBridge) session.getAttribute("JSONRPCBridge");
if(json_bridge == null) {
  json_bridge = new JSONRPCBridge();
  session.setAttribute("JSONRPCBridge", json_bridge);
}

Una vez hecho esto, por cada instácia de clase que queramos hacer accesible desde JavaScript ejecutamos la siguiente instrucción:

json_bridge.registerObject("foo", new Foo());

Mediante esta instrucción asignamos un nombre a la instancia, que será el que usaremos más tarde para acceder a ella desde JavaScript

Devolviendo tipos simples

Una vez lo hemos instalado y hemos registrado las instancias de nuestras clases en el objeto JSONRPCBridge podemos acceder a sus funciones desde JavaScript. Para ello debemos enlazar, en nuestro HTML, con el cliente de JSON-RPC, de la siguente forma:

 

Hecho esto, ya es posible acceder a las funciones de la instancia de Foo desde nuestro JavasCript. Para ello, primero crearemos una instancia del cliente JSON-RPC, de la siguiente forma:

jsonrpc = new JSONRpcClient("//JSON-RPC");

Hecho esto podemos acceder a las funciones de la instancia de Foo registrada con el nombre "foo". Existen dos formas de acceder a ellas: de forma síncrona o asíncrona

De forma síncrona el cliente JavaScript bloqeará el navegador hasta que optenga respuesta del servidor. Esta forma de acceso no es recomendable, menoes en el caso de que estemos trabajando en entornos muy controlados, donde podamos garantizar la respuesta del servidor en un tiempo determinado. Para acceder de esta forma, solo es necesario llamar a las funciones como si de funciones JavaScript se tratara, así:

jsonrpc.foo.getInteger();
jsonrpc.foo.getBoolean();
jsonrpc.foo.getString();

De forma asíncrona el cliente no bloqueará el navegador y la ejecución seguirá. Deveromos crear una función que será la que se llamará al recibir la respuesta desde el servidor, así:

jsonrpc.foo.getInteger(handler);

La función que capturará el resultado tendrá dos parametros:

  • El resultado de la ejecución, en caso de que la función retorne algún resultado
  • Una excepción, que tendrá valor en caso de que en el código Java se produzca alguna excepción

Por ejemplo:

function handler(result, exception) {
  if (!exception) {
    alert(result);
  }
}

Devolviendo objetos

JSON-RPC-Java tiene la capacidad de serializar los objetos Java retornados por las funciones y desserializarlos como objetos JavaScript. Mostraremos esta característica con un ejemplo. Crearemos una nueva clase que será devuelta desde una funcion de Foo, esta clase es:

public class Bar {
  private String string; 
  private int integer;
  private boolean bool;

  public Bar() {
  }

  public Bar(String string, int integer, boolean bool) {
    this.string = string;
    this.integer = integer;
    this.bool = bool;
  }

  public String getString() {
    return this.string;
  }
  ...

  public void setString(String string) {
    this.string = string;
  }
  ...
}

 

Y añadiremos una función en Foo que devuelva un objeto de este tipo:

public Bar getBar() {
  return new Bar("bar", 2, false);
}

Es posible ejecutar esta función de la misma forma que las anteriores y acceder a sus atributos, así:

var bar = jsonrpc.foo.getBar();

bar.string;
bar.integer;
bar.bool;

Devolviendo colecciones de objetos

Además de serializar nuestros propios objetos, JSON-RPC-Java puede serializar colecciones de objetos de clases que implementen las interfaces Map, Set o List.

Para nuestro ejemplo, crearemos tres nuevas funciones, una para cada interfaz, en la clase Foo:

public class Foo {
  ...

  public List getList() {
    List list = new ArrayList();
    list.add("valor 1");
    list.add("valor 2");
    list.add("valor 3");
    return list;
  }

  public Map getMap() {
    Map map = new HashMap();
    map.put("key 1","valor 1");
    map.put("key 2","valor 2");
    map.put("key 3","valor 3");
    return map;
  }

  public Set getSet() {
    Set set = new HashSet();
    set.add("valor 1");
    set.add("valor 2");
    set.add("valor 3");
    return set;
  }
},>,>,>

Al llamar a estas funciones recibiremos un objeto JavaScript con la collección de objetos, a la que podremos acceder así:

var list = jsonrpc.foo.getList();

// Accedemos a dos objetos de la lista
list.list[0];
list.list[3];

var set = jsonrpc.foo.getSet();

// Accedemos a dos objetos del set
set.set["valor 1"];
set.set["valor 2"];

var map = jsonrpc.foo.getMap();

// Accedemos a dos objetos del Map;

map.map["key 1"];
map.map["key 2"];

Es posible devolver colecciones de objetos como los descritos en el punto anterior

Conclusiones

JSON-RPC-Java es una potente herramienta para el desarrollo de aplicaciones Ajax con Java. Nos permite ejecutar funciones Java desde JavaScript sin preocuparnos por la conexión o el objeto XmlHttpRequest.

Actualmente esta libreria está en evolución constante. Se esta realizando una unión con otro proyecto del mismo tipo, llamado jabsorb, que permite devolver objetos con referencias circulares o incluso, referencias a objetos (permitiendo ejecutar funciones de objetos devueltos).

Enlaces relacionados

Contacto

¿Te interesan nuestros servicios?

Contáctanos