Weblets y como servir recursos que están en el CLASSPATH

3
8456

Creación: 01-12-2008

índice de contenidos

1.Introducción
2. Entorno
3.Configuración de Maven
4.Configuración de Weblets en el proyecto web
5.Configurando de Weblets en el módulo
6.Invocando los recursos en nuestras páginas
7.Conclusiones
8.Sobre el autor

1. Introducción

A menudo nos planteamos el realizar componentes web (llamaremos componente a una pequeña pieza visual que queremos reutilizar en varios sitios o proyectos, como una tabla con paginación incluida, un menú desplegable a «nuestra manera», un campo de entrada con validaciones automáticas incorporadas, …). Esto lo podemos llegar a realizar desde simples inclusiones de JSP, o realizando librerías de etiquetas, hasta la realización de componentes propios con JSF o Facelets.

El problema que nos encontramos a menudo en cualquier de estos casos es que junto al componente necesitamos algunos recursos adicionales, como imágenes, hojas de estilo (CSS), o ficheros JavaScript; y que para poder «servir» al cliente todos estos recursos, necesitamos situarlos en el directorio donde están el resto de nuestros HTML. Esto es un problema si queremos reutilizar estos componentes entre proyectos, ya que no podemos empaquetarlos en un JAR y redistribuirlos como cualquier otra librería, ya que tenemos que hacer «copy/paste» de todos esos recursos adicionales.

Weblets (https://weblets.dev.java.net/) es un proyecto que pretende solucionar este problema, y la verdad es que lo hace bastante bien, de manera que puede convertirse en un estándar.

Ya existen otras soluciones, como hacernos un Servlet para servir recursos que se encuentren dentro del CLASSPATH. Una solución de este estilo la propone Roger Keays en
http://www.ilikespam.com/blog/packaging-your-facelets-in-jars (por cierto, en este artículo es especialmente interesante el ResourceResolver de Facelets para buscar también las
plantillas de Facelets en el CLASSPATH).

También se supone que JSF 2 tendrá soporte para hacer este tipo de cosas.

Lo bueno que tiene Weblets sobre estas dos aproximaciones:

  • Weblets funciona usemos o no usemos JSF. Además JSF 2 todavía no ha salido 😉
  • Weblets ya está hecho, así que no nos tenemos que hacer y mantener nosotros el Servlet.
  • Weblets da soporte para servir recursos que estén dentro del JAR, o accesibles desde una URL o incluso en la propia aplicación web, y todo esto es tema de configuración. Es decir Weblets proporciona una interfaz y varias implementaciones. La más interesante puede resultar la que busca los recursos en el CLASSPATH, pero podríamos hacernos incluso nuestras propias implementaciones.
  • Weblets puede servir recursos de módulos diferentes. Esto se consigue dando nombres diferentes a cada módulo.
  • Weblets hace especial hincapié en que el navegador cachee los recursos servidos, de esta forma no se tendrán que servir en sucesivas peticiones. Además esto se puede controlar, de forma que en desarrollo siempre se devuelva el recurso, o incluso se puede especificar un timeout concreto para la cache.
  • Weblets se encuentra en el repositorio de Maven de java.net
    (http://mvnrepository.com/artifact/net.java.dev.weblets)
    de forma que es muy cómodo integrarlo en nuestros proyectos como una dependencia.


2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Asus G1 (Core 2 Duo a 2.1 GHz, 2048 MB RAM, 120 GB HD).
  • Nvidia GEFORCE GO 7700
  • Sistema Operativo: GNU / Linux, Debian (unstable), Kernel 2.6.26, KDE 3.5
  • Java Sun 1.6.0_10
  • Maven 2.0.9
  • Weblets 1.1


3. Configuración de Maven

Para poder usar Weblets, tendremos que añadir al pom.xml de nuestro proyecto:

<repositories>
    <repository>
        <id>maven2-repository.dev.java.net</id>
        <name>Java.net Repository for Maven</name>
        <url>http://download.java.net/maven/2/</url>
        <layout>default</layout>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>net.java.dev.weblets</groupId>
        <artifactId>weblets-api</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>net.java.dev.weblets</groupId>
        <artifactId>weblets-impl</artifactId>
        <version>1.1</version>
    </dependency>
</dependencies>

 

Podemos ver como damos de alta el repositorio de java.net.

Atención !!! esta configuración sólo es necesaria en el proyecto web. Es decir supongamos que tenemos un proyecto web autentia-weblets-web y un proyecto jar autentia-weblets-module. Esta configuración sólo estará en autentia-weblets-web que es el que sirve los recursos, aunque los recursos que se están sirviendo estarán dentro del jar generado por el proyecto autentia-weblets-module.


4. Configuración de Weblets en el proyecto web

En el ejemplo estamos usando Weblets con JSF. Para este caso tendremos que añadir lo siguiente en el fichero web.xml:

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>

Si os fijáis esta es simplemente la configuración habitual de JSF, y es posible que ya la tengáis en el proyecto, así que no tendréis que hacer nada más, ya que Weblets se integra con el ciclo de vida de JSF.

Cosas a tener en cuanta:

  • Lo importante aquí es el url-pattern, es muy importante que sea en base a un directorio. Es decir, un patrón del estilo *.jsf no sería válido. Esto es una limitación
    de Weblets, así que habrá que aprender a vivir con ello 😉 Lo que si podemos hacer es tener más de un url-pattern: uno para Weblets y otro para nuestras «cositas» con el
    *.jsf).
  • También tenemos que tener presente que si estamos usando, por ejemplo, ICEfaces, tendremos dado de alta el Servlet de ICEfaces, y puede que no tengamos añadido el Servlet estándar de JSF. En este caso, si será necesario añadir la configuración que hemos puesto arriba. Es decir Weblets se «engancha» al Servlet estandar de JSF, pero no al de ICEfaces.

5.Configurando de Weblets en el módulo

El módulo es el proyecto que genera el JAR donde dentro están los recursos que se tienen que servir.

En el jar tendremos que tener el ficheroMETA-INF/weblets-config.xml (podemos tener más de un fichero de configuración siempre y cuando weblets-config sea parta del nombre del fichero). Este fichero tendrá el siguiente aspecto:

<?xml version="1.0" encoding="UTF-8" ?>
<weblets-config xmlns="http://weblets.dev.java.net/config">
    <weblet>
        <weblet-name>com.autentia.tutorial</weblet-name>
        <weblet-class>net.java.dev.weblets.packaged.PackagedWeblet</weblet-class>
        <weblet-version>1.0-SNAPSHOT</weblet-version>
        <init-param>
            <param-name>package</param-name>
            <param-value>resources</param-value>
        </init-param>
    </weblet>
    <weblet-mapping>
        <weblet-name>com.autentia.tutorial</weblet-name>
        <url-pattern>/tutorial/*</url-pattern>
    </weblet-mapping>
</weblets-config>

 

Examinemos cada uno de los elementos del fichero de configuración:

  • weblet-name (línea 4): es nombre del «modulo», cuando queramos acceder a recursos dentro de este JAR tendremos que usar este identificador.
  • weblet-class (línea 5): clase que buscará el recuro solicitado. En este caso la clase PackageWeblet buscará el recurso en el CLASSPATH.
  • weblet-version (línea 6): indica la versión de los recursos. Este valor tiene especial importancia a la hora de que el navegador cachee los recursos servidos por Weblets. Si no existe el elemento, o si su valor contiene la cadena «SNAPSHOT«, el recurso no se cacheará por el navegador. Esto está pensado para usar durante el desarrollo donde
    es posible que el recurso cambie frecuentemente. Si no se cumple ninguna de estas condiciones (el valor es una cadena del estilo «1.0«), el recurso será cacheado por el
    navegador, de forma que sólo se servirá la primera vez, con el ahorro de ancho de banda que esto supone. Weblets volverá a servir el recurso si ve que este valor ha cambiado.
  • init-param (líneas de la 7 a la 10): esto son parámetros de la clase definida con weblet-class. En este caso estamos indicando el nombre del paquete donde están
    los recursos que tiene que servir (otro ejemplo podría ser «com.autentia.resources.html«). Esto sirve como medida de seguridad ya que nos garantiza que sólo se servirán los recursos que se encuentran dentro de ese paquete (así nunca se servirá un .class o cualquier otro recurso que no nos
    interese).
    Evidentemente tendremos que haber colocado nuestros recursos (png, css, js, …) dentro de este paquete.
  • weblet-mapping (líneas de la 12 a la 15): tenemos que indicar el id del weblet (el que se definió con el elemento weblet-name) y el patrón de URL que hará que se intente servir recursos con este módulo. Weblets se encargará de generar estas URLs, como veremos un poco más adelante.

En un mismo fichero podemos definir más de un elemento weblet. También podemos indicar los MIME-TYPES, e incluso indicar que tipos de recursos son lo que se pueden servir (esto sería una medida de seguridad adicional). Para ver más sobre estas configuraciones acudir a la página de Weblets.


6. Invocando los recursos en nuestras páginas

Ya esta todo configurado, ahora sólo queda «usar» esos recursos que se encuentran dentro del JAR. Para ello en nuestras páginas (JSP, JSPX, …) podemos poner (acordaros que estamos viendo un ejemplo para JSF + Facelets + ICEfaces, para ver más posibilidades acudir a la página de Weblets):

#{weblet.resource['nombre_del_weblet']['ruta_del_recurso']}

#{weblet.url['nombre_del_weblet']['ruta_del_recurso']}

La diferencia entre resource y url es que el primero genera una URL relativa al contexto donde estamos, mientras que el segundo genera una URL absoluta.

Veamos una pagina de ejemplo:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core"
    xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:weblet="http://weblets.dev.java.net/tags_jsp2">

<ice:outputDeclaration doctypeRoot="HTML" doctypePublic="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctypeSystem="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <ice:outputStyle href="/xmlhttp/css/rime/rime.css" />
    <ice:outputStyle href="#{weblet.resource['com.autentia.tutorial']['/css/application.css']}" />
    <title>Tutorial Weblets</title>
</head>
<body>
    <ice:panelGrid columns="2">
        <ice:outputText value="Adictos al Trabajo" />
        <ice:graphicImage value="#{weblet.resource['com.autentia.tutorial']['/img/logoAdictosAlTrabajo.png']}" />

        <ice:outputText value="Powered by Autentia" />
        <ice:graphicImage value="#{weblet.resource['com.autentia.tutorial']['/img/poweredByAutentia_100x30x72dpi.png']}" />
    </ice:panelGrid>
</body>
</html>

Se ve como en las líneas 11, 17 y 20 se usa weblet.resource, indicando que queremos sacar el recurso del módulo «com.autentia.tutorial» (es el nombre que indicábamos en la línea 4 del ejemplo del punto 5) y a continuación el nombre del recurso.

Esto nos generará URL del estilo:

/autentia-weblets-web/faces/weblets/tutorial$1.0-SNAPSHOT/css/application.css

/autentia-weblets-web/faces/weblets/tutorial$1.0-SNAPSHOT/img/logoAdictosAlTrabajo.png

/autentia-weblets-web/faces/weblets/tutorial$1.0-SNAPSHOT/img/poweredByAutentia_100x30x72dpi.png

En las URL generadas podemos ver como aparece «/faces/» de forma que lo procesará el Servlet estándar de JSF. También vemos como aparece «tutorial$1.0-SNAPSHOT» que es lo que habíamos configurado en el punto 5, y a continuación vemos la ruta al recurso.

Obtendremos algo del estilo:

Donde tanto la css como las dos imágenes se están sacando del JAR del proyecto autentia-weblets-module.

7. Conclusiones

Es importante estar atentos a las nuevas librerías y estándares (sean de facto o de ley) ya que nos pueden ahorrar trabajo y facilitar la vida. En esta ocasión hemos visto como podemos llegar a crear componentes web con recursos adicionales. Empaquetar estos componentes en un JAR y distribuirlos como cualquier otra librería.

Aquí os dejo todo el proyecto de Maven para que podáis ver el código completo y podáis jugar con él.

8. Sobre el autor

Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software)

Socio fundador de Autentia (Formación, Consultoría, Desarrollo de sistemas transaccionales)

mailto:alejandropg@autentia.com

Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»

http://www.autentia.com

 

Alejandro Pérez García
Alejandro es socio fundador de Autentia y nuestro experto en Java EE, Linux y optimización de aplicaciones empresariales. Ingeniero en Informática y Certified ScrumMaster. Seguir @alejandropgarci Si te gusta lo que ves, puedes contratarle para darte ayuda con soporte experto, impartir cursos presenciales en tu empresa o para que realicemos tus proyectos como factoría (Madrid). Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.

3 COMENTARIOS

  1. Muy buen tutorial. No es muy utilizada y es muy útil para poder tener los recursos centralizados. Sol ome surge una duda intentando servir otro tipo de recursos que no aparecen en el tutorial.
    Con los jsp, intento hacer un jsp:include para meter zonas comunes en Tiles desde un weblet y no me encuentra el recurso ni con url, ni con resource. Sin embargo, hago un y si que me enlaza con el jsp poniendole el url.
    ¿Hay algo con el jsp:include ? ¿Alguna otra manera se os ocurre de hacer esto?
    Estoy en un entorno con Spring sin JSF.
    Muchas gracias y enhorabuena otra vez por el tuto.

  2. Me ha cogido el a href y me lo ha puesto como link. Perdón. Simplemente aclarar que delante de «y si que me enlaza» hago referencia a un a href.

  3. Hola, tengo la misma duda que planteó en el comentario anterior aleks, como puedo hacer el jsp:include?? weblets no tiene alguna forma para incluir jsp?? Espero me sepan contestar, saludos!

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad