Usar Apache Tapestry en una aplicación «standalone»

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

Apache Tapestry

Apache Tapestry es un framework de desarrollo para aplicaciones o páginas web en el que habitualmente se emplea el lenguaje Java y se despliega en un servidor de aplicaciones como entorno de ejecución. Pero Tapestry es una pieza de software que se compone de diferentes partes algunas de las cuales pueden ser utilizadas fuera del contexto de una aplicación web. Este es el caso del contenedor de dependencias que proporciona IoC (IoC, «Inversion of Control») en Tapestry, podemos usarlo en una aplicación «standalone», es decir, en un programa que se inicia con el típico «public static void main(String[] args)» de las aplicaciones Java.

El contenedor de dependencias de Tapestry tiene algunas propiedades interesantes como que dos servicios pueden ser mutuamente dependientes y que se puede contribuir configuración a cualquier servicio para cambiar en cierta medida su comportamiento además de otras características que explico más en detalle en el libro PlugIn Tapestry. Para usarlo en una un programa que se ejecuta de la linea de comandos usando el main de una clase Java primeramente deberemos incluir en el proyecto la dependencia sobre tapestry-ioc, si usamos Gradle de la siguiente manera:

1
2
compile 'org.apache.tapestry:tapestry-core:5.4-beta-3'
compile 'org.apache.tapestry:tapestry-ioc5.4-beta-3'
build-1.gradle

Una vez que tenemos la dependencia en el programa deberemos iniciar el contenedor IoC e indicarle los diferentes módulos que contendrán la definición de los servicios.

1
2
3
4
5
6
RegistryBuilder builder = new RegistryBuilder();
builder.add(TapestryModule.class, HibernateCoreModule.class, HibernateModule.class, BeanValidatorModule.class, TapestryOfflineModule.class, GeneratorModule.class);
builder.add(new SpringModuleDef("applicationContext.xml"));

Registry registry = builder.build();
registry.performRegistryStartup();
Main-1.java

En este caso he usado Spring para la transaccionalidad e Hibernate para la persistencia. Después de esto tenemos la referencia al registro de servicios, podemos obtener cualquiera en base a la interfaz que implementa, en este caso el servicio que implementa la interfaz MainService.

1
2
registry.getService(MainService.class);

Main-2.java

Al final de la aplicación deberemos llamar al método shutdown del registro.

1
2
registry.shutdown();

Main-3.java

Otra cosa que nos puede interesar es poder generar contenido html usando el sistema de plantillas y componentes de Tapestry, ya sea en una aplicación «standalone» o en una aplicación web para enviar el contenido en un correo electrónico o quizá guardarlo en un archivo. Hay muchos sistemas de plantillas, cada framework suele tener uno propio o usar una solución específica como Thymeleaf pero la mayoría usa un modelo push en vez de un modelo pull, en el caso de Tapestry se emplea el modelo pull que tiene algunas ventajas como explico en el artículo anterior. Si usamos una aplicación Tapestry usándolo también para generar el contenido de los correos o cierto contenido estático evitamos tener que aprender una segunda tecnología además de aprovechar todo el código reutilizable que posiblemente hemos desarrollado en algunos componentes. Para generar el contenido estático que generaría una página en Tapestry tenemos el módulo Tapestry Offline. Como no está en los repositorio de maven debemos descargarnos el jar e incluir la dependencia como un archivo.

1
2
compile files('misc/libs/tapestry-offline.jar')

build-2.gradle

Para generar una página de Tapestry fuera de una petición web y de un servidor de aplicaciones debemos usar el servicio OfflineComponentRenderer. Su uso sería el siguiente:

 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
@Override
public File generatePage(String page, Object[] context, Map<String, String> params) throws IOException {
	File file = new File(to, getToPage(page, context, params).getPath());
	logger.info("Generating page «{}» ({}, {})...", page, file, params.toString());

	file.getParentFile().mkdirs();

	Writer w = new FileWriter(file);
	render(page, context, params, Globals.LOCALE, w);
	w.close();

	return file;
}

private void render(String page, Object[] context, Map<String, String> params, Locale locale, Writer writer) throws IOException {
	TypeCoercer coercer = Globals.registry.getService(TypeCoercer.class);
	OfflineComponentRenderer renderer = Globals.registry.getService("BlogStackOfflineComponentRenderer", OfflineComponentRenderer.class);

	EventContext activationContext = new ArrayEventContext(coercer, context);
	PageRenderRequestParameters requestParams = new PageRenderRequestParameters(page, activationContext, false);
	DefaultOfflineRequestContext requestContext = new DefaultOfflineRequestContext();
	for (Map.Entry<String, String> param : params.entrySet()) {
		requestContext.setParameter(param.getKey(), param.getValue());
	}
	requestContext.setLocale(locale);

	renderer.renderPage(writer, requestContext, requestParams);
}
GeneratorServiceImpl.java

Tengo que decir que al generar la página fuera de una petición web tendremos alguna limitación como solo poder usar assets con el prefijo context. Pero esto por lo menos como he explicado en el caso de Blog Stack no me ha supuesto ningún problema.

Esto quizá no sea lo habitual pero en Blog Stack ambas posibilidades me han resultado de gran utilidad al desarrollar el proyecto. Las posibilidades son muchas por ejemplo podríamos usar alguna combinación de esto mismo con el microframework Spark si nuestra aplicación estuviese más orientada a una API aunque también podríamos usarlo junto con RESTEasy.

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: