Soporte para lanzar eventos desde JavaScript con Ajax en un componente de Apache Tapestry

Escrito por el .
java javascript planeta-codigo programacion tapestry
Enlace permanente Comentarios

Apache Tapestry

Java

Para desarrollar aplicaciones web con el lenguaje de programación Java hay gran cantidad de frameworks que proponen un marco de trabajo para proporcionar la mayor parte de la funcionalidad de infraestructura necesaria para una aplicación. La mayoría basados en acciones y unos pocos basados en componentes. Una aplicación web no solo consta de la parte del servidor y desde hace tiempo la parte de cliente ha cobrado gran importancia.

Algunos frameworks proporcionan cierto soporte para JavaScript y recursos CSS en otros es muy escaso o inexistente. En el caso del framework Apache Tapestry en la categoría de los basados en componentes proporciona un gran soporte no solo en la parte del servidor sino también para la parte cliente.

Una de estas funcionalidades que proporciona Tapestry es poder lanzar eventos desde el cliente mediante una petición Ajax para que sean procesados en el servidor y obtener la respuesta que se devuelva desde el servidor normalmente en formato Json. Hay que definir un manejador de evento en el servidor siguiendo la convención on[Event] y en caso de querer lanzar un evento desde el cliente anotándolo con @PublishEvent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package io.github.picodotdev.plugintapestry.components;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.PublishEvent;
import org.apache.tapestry5.corelib.components.Any;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

/**
 * @tapestrydoc
 */
public class Event {

	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String selector;

	@Component
	private Any span;

	@Environmental
	private JavaScriptSupport support;

	@PublishEvent
	Object onGetColores() {
		return new JSONArray("Rojo", "Verde", "Azul", "Negro");
	}

	protected void afterRender(MarkupWriter writer) {
		JSONObject spec = new JSONObject();
		spec.put("selector", span.getClientId());

		support.require("app/event").invoke("init").with(spec);
	}
}
Event.java
1
2
3
4
<!DOCTYPE html>
<t:container xmlns="http://www.w3.org/1999/xhtml" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd" xmlns:p="tapestry:parameter">
    Colores: <span t:type="any" t:id="span">Cargando...</span> (Event/Json)
</t:container>
Event.tml

El uso del componente en una plantilla de una página.

1
2
3
4
5
...
<p>
  <t:event/>
</p>
...
Index.tml

En el código JavaScript asociado a una página o componente hay que hacer uso del módulo que ofrece el soporte para Ajax y los eventos desde el cliente, con RequireJS se obtiene una referencia a él. Solo es necesario indicar como parámetro el nombre del evento a lanzar, los parámetros si los hubiese y los manejadores de respuesta, tanto en el caso de ser correcta que recibirá los datos devueltos en el servidor como incorrecta. En el archivo ajax.coffee están documentados todos los parámetros que posee la función ajax del módulo t5/core/ajax.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
define("app/event", ["t5/core/ajax", "jquery"], function(ajax, $) {
	function Colores(spec) {
		var _this = this;
		
		this.spec = spec;

		setTimeout(function() {
			_this.getColores();
		}, 2000);
	}

	Colores.prototype.getColores = function() {
		var _this = this;
		
		ajax('getColores', {
			element: $(_this.spec.selector),
			success: function(response) {
				var c = response.json.join();
				$(_this.spec.selector).html(c);
			}
		});
	}

	function init(spec) {
		new Colores(spec);
	}
	
	return {
		init: init
	}
});
event.js

En el primer elemento del HTML se añade un atributo data-componenent-events que contiene la URL necesaria para cada evento que haya sido declarado como lanzable. A partir del elemento indicado en la opción element se busca la URL en el atributo data-componenent-events siguiendo un orden empezando por el propio elemento, en los previos al mismo nivel jerárquicamente empezando por el más cercano desde abajo hacia arriba, en los padres y finalmente en el elemento body.

Petición Ajax del evento Atributo con la URL del evento

Petición Ajax y atributo con la URL del evento

Esta funcionalidad se incorporó en Apache Tapestry 5.2 donde hasta entonces era necesario construir la URL del evento en el servidor con ComponentResources.createEventLink() y enviarlo al componente haciendo uso de JavaScriptSupport como se muestra en el componente Ajax que no hace uso de esta funcionalidad de eventos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package io.github.picodotdev.plugintapestry.components;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

/**
 * @tapestrydoc
 */
public class Ajax {

	@Parameter(defaultPrefix = BindingConstants.LITERAL)
	private String selector;

	@Environmental
	private JavaScriptSupport support;

	@Inject
	private ComponentResources componentResources;

	Object onGetColores() {
		return new JSONArray("Rojo", "Verde", "Azul", "Negro");
	}

	protected void afterRender(MarkupWriter writer) {
		String link = componentResources.createEventLink("getColores").toAbsoluteURI();

		JSONObject spec = new JSONObject();
		spec.put("selector", selector);
		spec.put("link", link);

		support.require("app/ajax").invoke("init").with(spec);
	}
}
Ajax.java

Con este soporte es algo más fácil enviar eventos y realizar peticiones Ajax desde el cliente para obtener datos.

Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./gradlew run

Portada libro: PlugIn Tapestry

Libro PlugIn Tapestry

Si te interesa Apache Tapestry descarga gratis el libro de más de 300 páginas que he escrito sobre este framework en el formato que prefieras, PlugIn Tapestry: Desarrollo de aplicaciones y páginas web con Apache Tapestry, y el código de ejemplo asociado. En el libro comento detalladamente muchos aspectos que son necesarios en una aplicación web como persistencia, pruebas unitarias y de integración, inicio rápido, seguridad, formularios, internacionalización (i18n) y localización (l10n), AJAX, ... y como abordarlos usando Apache Tapestry.



Comparte el artículo: