Etiqueta: java

Plugtest de XAdES – Firmas electrónicas avanzadas para documentos en formato XML

26 mar 2012

Como anunciábamos en el post de PAdES, el ETSI (Instituto Europeo para la Normalización de las Telecomunicaciones – European Telecommunications Standards Institute) ha organizado un nuevo evento “Plugtest” para firmas con formato XAdES (firma avanzada para ficheros XML) el cual está en activo desde el 14 de Marzo y finalizará el 28 de este mismo mes.

Este evento tiene como objetivo la validacióna distancia según los test propuestos por ETSI en las firmas XAdEs ( TS 101 903) y el perfil de referencia XAdES (TS 103 171).
Estas pruebas proveerán una cobertura completa de las dos especificaciones citadas incluyendo la prueba de la evolución de las firmas, simulando situaciones reales.

El evento “Plugtest” permitirá a los participantes realizar 4 tipos de tests (interoperabilidad y conformidad):

  • Tests de generación y verficación cruzada (positivo)
  • Tests de solo verificación (negativo)
  • Tests de actualización de firma.
  • Test de conformidad en el perfil de referencia de firma en XAdES.


Plugtest XAdES

El propósito del evento es:

  • Permitir a los participantes asegurar el nivel de interoperabilidad de XAdES.
  • Identificar temas adicionales que deberían tenerse en cuenta en futuras actividades de estandarización de XAdES.
  • Mejorar la calidad de las especificaciones XAdES.
  • Facilitar la introducción de las firmas XAdES, proveyendo los medios para solucionar los problemas de interoperabilidad antes del lanzar el despliegue…

Se puede obtener mayor información del evento en el portal de plugtests para firma electrónica:  http://xades-portal.etsi.org/pub/index.shtml

Al igual que en nuestra web, podemos dar una pequeña descripción de los perfiles según el nivel de protección ofrecido. Cada perfil incluye y extiende al previo:

  • XAdES-BES, forma básica que simplemente cumple los requisitos legales de la Directiva para firma electrónica avanzada.
  • XAdES-EPES, forma básica a la que se la ha añadido información sobre la política de firma.
  • XAdES-T (timestamp), añade un campo de sellado de tiempo para proteger contra el repudio.
  • XAdES-C (complete), añade referencias a datos de verificación (certificados y listas de revocación) a los documentos firmados para permitir verificación y validación off-line en el futuro (pero no almacena los datos en sí mismos).
  • XAdES-X (extended), añade sellos de tiempo a las referencias introducidas por XAdES-C para evitar que pueda verse comprometida en el futuro una cadena de certificados.
  • XAdES-X-L (extended long-term), añade los propios certificados y listas de revocación a los documentos firmados para permitir la verificación en el futuro incluso si las fuentes originales (de consulta de certificados o de las listas de revocación) no estuvieran ya disponibles.
  • XAdES-A (archivado), añade la posibilidad de timestamping periódico (por ej. cada año) de documentos archivados para prevenir que puedan ser comprometidos debido a la debilidad de la firma durante un periodo largo de almacenamiento.

Para aquel que esté interesado, hay disponible una serie de kit’s de integración de descarga gratuita para java, .NET y php en nuestro portal para desarrolladores  developers.viafirma.com para firmar electrónicamente en formato XAdES.

PAdES – Firmas electrónicas avanzadas para documentos en formato PDF

14 mar 2012

El pasado mes de Noviembre, Viafirma participó en el PAdES Remote plugtest Event organizado por el Instituto Europeo de Estándares de Telecomunicaciones (ETSI). Estos eventos son realizados de forma remota y tienen como objetivo la realización de pruebas de interoperabilidad e interpretación del estándar definido por ETSI para las firmas electrónicas avanzadas como XAdES,  CAdES, PAdES y ASIC.

La norma define una serie de perfiles para PAdES – firmas electrónicas avanzadas para documentos en formato PDF que cumplan con los requisitos que la Directiva Europea establece para un marco comunitario de firma electrónica (Directiva 1999/93/CE).

En concreto, los test fueron llevado a cabo sobre el estándar PAdES (ETSI TS 102 778 – PDF Advanced Electronic Signature) que permite firmar electrónicamente documentos en formato PDF.

Definiremos brevemente los perfiles definidos por PAdES (ETSI TS 102 778):

  • PAdES Basic – Profile based on ISO 32000-1. Perfil básico qie cumple con los requisitos especificados en la norma ISO 32000-1.
  • PAdES Enhanced – PAdES-BES profile. Este perfil especifica una firma PDF avanzada basada en CAdES-bes e incorpora opción de incluir en la firma un sello de tiempo (CADES-T).
  • PAdES Enhanced – PAdES-EPES profile. Este perfil especifica una firma PDF avanzada basada en CAdES-EPES. Este perfil es el PAdES-BES Profile añadiendole un identificador de política de firma y, opcionalmente, una referencia al tipo de compromiso adquirido.
  • Long Term – PAdES-LTV Profile. Es el formato de firma longeva. Este perfil permite prorrogar por tiempo indefinido la validez de las firmas en formato PDF. Puede ser usado en conjunción con el PAdES-CMS, PAdES-BES o perfiles PADES-EPES. Este perfil es utilizado para garantizar la validación tras muchos años después de la realización de la firma. Es decir, garantiza la validación a largo plazo.

En nuestro portal para desarrolladores developers.viafirma.com tenéis disponibles para su descarga  kit’s de integración para java y .NET con métodos para firmar electrónicamente en formato PAdES. Próximamente también estará disponible en PHP.

Hoy comienza el XAdES 2012 Plugtests en el que también participamos y que tiene como objetivo llevar a cabo casos de prueba para el estándar XAdES (TS 101 903), incluyendo el XAdES (TS 103 171).

Os mantendremos informados sobre nuestros avances ;)

JBoss Seam: renderizar un xhtml externo

02 dic 2011

Todos sabemos las ventajas que tiene trabajar con plantillas xhtml a la hora de generar la capa de presentación o incluso para generar emails o pdfs a través de seam.

El problema viene cuando utilizamos una gran cantidad de plantillas xhtml personalizadas y necesitamos gestionarlas de manera externa a la aplicación y almacenarlas por ejemplo en un repositorio externo: BD, gestor documental, ftp, en disco, etc.

Por defecto, el render de Seam permite generar renderizados de vistas (views) que están contenidas dentro de la propia aplicación. Un ejemplo:

renderer.render("/pdf/templatePdf.xhtml");

La anterior linea intentará generar el renderizado a partir de un resource en la propia aplicación, es decir, el archivo templatePdf.xhtml debe estar físicamente en el webapps de la aplicación.

¿Y qué ocurre si tenemos un templatePdf.xhtml externo, quizás en un repositorio o lo queremos generar dinámicamente?

Lo que tenemos que hacer es implementar un cargador de resources que controle cuándo queremos renderizar una vista normal o una vista en un repositorio externo.

Esta distinción se hará a nivel de URL, es decir, cuando queramos renderizar una vista normal nos bastaría con:

renderer.render("/pdf/templatePdf.xhtml")

mientras que para renderizar vistas externas podríamos poner algo como:

renderer.render("CUSTOM-/pdf/templatePdf.xhtml")

es decir, anteponemos un prefijo, por ejemplo “CUSTOM-”.

Ahora nos toca decirle al cargador de resources que cuando se solicite un recurso con el prefijo “CUSTOM-” lo trate de manera especial, cargándolo por ejemplo de un repositorio de plantillas, de un FTP, generándolas nosotros dinámicamente o lo que necesitéis. Aquí os pongo la implementación de la clase:


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.ServletLifecycle;
import org.jboss.seam.core.ResourceLoader;
import org.jboss.seam.util.Resources;

@Name("org.jboss.seam.core.resourceLoader")
@Scope(ScopeType.STATELESS)
public class CustomResourceLoader extends ResourceLoader {

    public static final String TEMPLATE_PREFIX = "CUSTOM-";

    @Override
    public URL getResource(final String resource) {
        URL url = null;
        if (resource.startsWith(TEMPLATE_PREFIX)) {
            final String uriViewId = resource.substring(TEMPLATE_PREFIX.length());
            try {
                url = new URL("internal", "", 0, uriViewId, getHandler(uriViewId));
            } catch (final MalformedURLException e) {
                if (log.isErrorEnabled()) {
                    log.error("Unable to build the URL", e);
                }
            }
        } else {
            url = Resources.getResource(resource, ServletLifecycle.getServletContext());
        }
        return url;
    }

    // @return Our own implementation of an URLStreamHandler to get the template
    //         from the content repository.
    private static URLStreamHandler getHandler(final String uriViewId) {
        return new URLStreamHandler() {
            private final String uuid = uriViewId;

            @Override
            protected URLConnection openConnection(final URL url) throws IOException {
                return new URLConnection(url) {

                    @Override
                    public void connect() throws IOException {
                        // Gets not called in this case
                    }

                    @Override
                    public InputStream getInputStream() throws IOException {
                        initHandler();
                        try {
                            // Cargamos el contenido de la plantilla .xhtml
                            byte [] content = ....... ;
                            final InputStream input = new ByteArrayInputStream(content);
                            return input;
                        } catch (final Exception e) {
                            throw new IOException(e.getMessage(), e);
                        }
                    }

                    private void initHandler() {
                        log.debug("Init Handler");
                    }
                };
            }
        };
    }

    /**
     * Sistema de Logs
    */
    protected static transient Log log = LogFactory.getFactory().getInstance(CustomResourceLoader.class);

}

Quizás el equipo de desarrollo de Seam Framework propongo otro tipo de soluciones en el futuro para estos casos, pero por ahora, tenemos que hacer un poco de magia.

Plataforma de autenticación y firma digital sobre WebLogic

18 jun 2010

La nueva versión de Viafirma, coincidiendo con su instalación en dos importantes entidades bancarias,  ofrece soporte oficial para Oracle WebLogic 11. De esta forma, junto con las plataformas ya soportadas por Viafirma (Tomcat 5, Tomcat 6, Websphere, etc…), ahora se incluye:

El proceso de instalación es muy sencillo,  por lo que siguiendo los pasos del manual de instalación de Viafirma para Weblogic podremos disponer de sus servicios de autenticación (DNIe o cualquier otro certificado digital) y firma digital (XAdES, PAdES, CMS, CAdES, facturae, firma en lotes,…) desplegados sobre Weblogic .

XWiki: autenticando con Viafirma

18 may 2010

Es de todos conocidos los grandes beneficios de usar una Wiki, para tener organizado y actualizado una gran cantidad de información y contenido, de forma que pueda ser rápidamente consultada y actualizada. Sin ninguna razón especial más allá de la simple curiosidad, vamos a poner como ejemplo en este caso una “implementación” wiki basada en Java (XWiki) y vamos a conseguir de forma sencilla que los usuarios puedan logarse con su Certificado Digital o DNI electrónico (DNIe).

Como no podría ser de otra forma, vamos a hacer uso del servicio de autenticación de la plataforma Viafirma, sirviéndonos de su cliente de autenticación, apoyándonos en su espectacular matriz de compatibilidad, además mantendremos el acceso por usuario/contraseña habitual de XWiki. Para realizar esta integración nos hemos basado principalmente en la documentación que podemos encontrar en las páginas oficiales de ambas plataformas, por un lado tenemos a Viafirma y por otro lado la web para desarrolladores de XWiki Development Zone

Primero una idea de lo que queremos hacer:

Dentro del formulario de login de XWiki, pondremos un enlace a una url dentro del propio XWiki que sea de la forma:
http://xwikiserver/.../viafirma.login

Esta URL será capturada dentro de la XWiki por un Filter que enviará al usuario automáticamente a Viafirma, que será el encargado de pedir el certificado digital al usuario y analizarlo (validarlo), tras esto enviará al usuario nuevamente a la XWiki (Viafirma coloca en la Session de esta petición el resultado de la validación del Certificado y será XWiki el encargado de tratar ese resultado) con una url con la forma:

http://xwikiserver/.../viafirmaAuthentication

El Request de esta URL será capturado por un Servlet que extiende al ViafirmaClientServlet, que nos proporciona el cliente de Viafirma, capturando de sesión el UsuarioGenericoViafirma que se ha obtenido. Este usuario aún no es un “usuario XWiki”. Este mismo Servlet se encargará de capturar la dirección a la que el usuario inicialmente quería acceder en XWiki y lo redirigirá allí de nuevo, siempre y cuando los resultados de Viafirma hayan sido válidos.

Por otro lado, extenderemos la clase XWikiAuthServiceImpl que implementa el servicio básico de autenticación de XWiki, introduciendo la posibilidad de realizar el Login en XWiki a partir de un UsuarioGenericoViafirma que tenemos en Sesión, para esto usaremos el API nativo de XWiki.

Por simplicidad para este ejemplo he adoptado la siguiente política de logado: dada una persona con NIF 12345678Z, su “Usuario XWiki” correspondiente será XWiki.12345678Z, es decir, debe existir un usuario dado de alta en XWiki cuyo Login coincida con el DNI de la persona. Cuando tengamos un UsuarioGenericoViafirma, consultamos su NIF y le preguntamos la XWiki a través de su API si existe usuario con ese Login. ¿Podría hacerse de forma más elaborada? Por supuesto, en vez de buscar un usuario con Login igual al Nif, podríamos haber definido una propiedad nueva para los Usuarios XWiki y para usarlo con este propósito, cuando lo hagáis no dudéis en poner vuestros comentarios al final de este post.

La secuencia de llamadas entre todos estos componentes lo podemos ver aquí:

Vamos a ir explicando paso a paso cómo hacer todo esto:
Paso 1.- Modificación del formulario de Login

Debemos editar el fichero templates/login.vm e introduciremos la redirección al servlet. Os propongo dos opciones, un enlace dentro de formulario ya existente y un formulario nuevo (para nuestro ejemplo funcionarán los dos):

...
<form>
...
#template("viafirmaLink.vm") <-Hiperenlace: opcion A
...
</form>
#template("viafirmaForm.vm") <- Formulario: opción B
...

Posteriormente copiaremos los ficheros viafirmaLink.vm y viafirmaForm.vm dentro del directorio templates.
Contenido de viafirmaLink.vm:

<div style="margin: 1em;">
 <a href="viafirma.login">ACCESO CON CERTIFICADO DIGITAL</a>
 <br/>
</div>

Contenido de viafirmaForm.vm:

<form id="loginFormViafirma" action="viafirma.login" method="post">
 <div>
 <fieldset>
 <legend>Certificado Digital</legend>
 <div><span><input type="submit" value="VIAFIRMA"/></span></div>
 </div>
</form>

Vemos que las dos opciones propuesta envian al usuario a la URL http://xwikiserver/…/viafirma.login .

Paso 2.- Implementación de un Filter, que será el encargado de capturar las peticiones a …/viafirma.login y enviar al usuario hacia Viafirma para que se autentique:

package org.viafirma.xwiki;
public class AuthenticationFilter implements Filter { ... }

Paso 3.- Implementación de un Servlet que recogerá de vuelta el resultado ofrecido por parte de Viafirma tras el análisis del certificado, capturando las peticiones a …/viafirmaAuthentication y coloque en sesión al usuario UsuarioGenericoViafirma:

package org.viafirma.xwiki;
public class AuthenticationServlet extends ViafirmaClientServlet implements Serializable { ... }

Paso 4.- Implementaremos un mecanismo usando otro Filter, para que Viafirma use una CSS definida por nosotros mismos. Viafirma “pide” por defecto una CSS llamada viafirmaStyle.css. En este ejemplo hemos optado por que XWiki sirva el CSS que usará Viafirma, aunque quizás lo más conveniente sea colocar este CSS en un servidor externo, por ejemplo un Apache, pero de todos modos vamos a hacerdo a modo de ejemplo. Bastaría con colocar una regla en Apache (por ejemplo) para que las peticiones al archivo viafirmaStyle.css no pasen a la XWiki, esto os lo dejo a vosotros.

Paso5.- Extenderemos el Servicio de Autenticación de XWiki, que sustituirá a la que tiene por defecto esta plataforma:

package org.viafirma.xwiki;
public class ViafirmaAuthImpl extends XWikiAuthServiceImpl implements  Serializable { ... }

Posteriormente, deberemos modificar el fichero xwiki.cfg de XWiki añadiendo o modificando:

xwiki.authentication.authclass=org.viafirma.xwiki.ViafirmaAuthImpl

Paso 6.- Configuraremos el web.xml de XWiki para dar de alta estos Filters y Servlets que hemos creado, adaptando los valores de los parámetros a nuestro entorno (url de Viafirma y ruta al css):

...
 <filter>
 <filter-name>ViafirmaLoginFilter</filter-name>
 <filter-class>org.viafirma.xwiki.AuthenticationFilter</filter-class>
 <init-param>
 <param-name>VIAFIRMA_URL</param-name>
 <param-value>http://viafirma.viavansi.com/viafirma</param-value>
 </init-param>
 <init-param>
 <param-name>VIAFIRMA_WS</param-name>
 <param-value>http://viafirma.viavansi.com/viafirma</param-value>
 </init-param>
 </filter>
 <filter>
 <filter-name>ViafirmaStyleFilter</filter-name>
 <filter-class>org.viafirma.xwiki.ViafirmaStyleFilter</filter-class>
 <init-param>
 <param-name>PATH_CSS</param-name>
 <param-value>D:/xwiki/skins/colibri/colibri.css</param-value>
 </init-param>
 </filter>

 <filter-mapping>
 <filter-name>ViafirmaLoginFilter</filter-name>
 <url-pattern>*.login</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>ViafirmaStyleFilter</filter-name>
 <url-pattern>*.css</url-pattern>
 </filter-mapping>
 ...
 <!-- Servlet de Autenticación de Viafirma-->
 <servlet>
 <servlet-name>viafirmaAuthentication</servlet-name>
 <servlet-class>org.viafirma.xwiki.AuthenticationServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>viafirmaAuthentication</servlet-name>
 <url-pattern>/viafirmaAuthentication/*</url-pattern>
 </servlet-mapping>

Finalmente tendremos esto:

Teneis el proyecto mavenizado y todos los fuentes usados en este ejemplo aquí:

Descarga de fuentes aquí

Para integrar este ejemplo en XWiki, sólo es necesario:

  1. Empaquetar las clases generadas en un .jar y copiarlo en el WEB-INF/lib de XWiki, también deberá copiar en esa carpeta todas las librerías dependientes.
  2. Realizar las modificaciones anteriormente indicadas en el formulario de Login.
  3. Copiar los archivos .vm a la ruta indicada anteriormente.
  4. Modificar y configurar el web.xml de XWiki.

Aquí os dejo unas capturas de pantalla para demostraros que todo esto funciona correctamente :)

Formulario para logarnos:

Finalmente, vemos que XWiki nos ha logado correctamente:

Selección del Certificado Digital en Viafirma, vereis que tiene el CSS que queremos (obviamente ese CSS se puede mejorar) :

Finalmente veremos que ya estamos logados en XWiki (enhorabuena !!) :

Esto nos da por pensar en próximos capítulos: ¿publicación de contenidos firmados digitalmente? Quién sabe…

Un Saludo.

Creando una aplicación web basada en OSGI con Eclipse

29 abr 2010

A continuación se describen los pasos básicos a dar para crear una aplicación web  que en lugar de ser desplegada sobre la típica pila JEE, sea desplegada como un componente más dentro de un contenedor OSGi.

Jee tradicional vs OSGi

Para ello se mostrará como construir con Eclipse un bundle OSGi que haciendo uso de Jetty nos permita correr un servlet sobre Equinox.

  • Crear el proyecto base

En primer lugar, necesitaremos crear un plugin, indicando que es de tipo OSGI (implementación Equinox).

Crear un proyecto OSGi en Eclipse

  • Definición de las dependencias

Una vez que tengamos el proyecto creado, necesitaremos declarar las dependencias que necesitará nuestro módulo para poder funcionar como un servidor de aplicaciones. Las dependencias serán como mínimo:

  • javax.servlet
  • org.eclipse.equinox.http.jetty
  • org.eclipse.equinox.http.servlet
  • org.mortbay.jetty.server
  • org.eclipse.equinox.http.registry

Dependencias Eclipse OSGI Jetty

  • Construcción del servlet de ejemplo

Una vez tengamos declaradas los módulos dependientes, Eclipse se encarga de actualizar nuestro classpath y ya podremos programar nuestro primer servlet sin problemas de compilación.

/** * Osgi Example Servlet. * */
public class HolaMundoOsgiServlet extends HttpServlet{
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Petición al Servlet OSGi");
 	resp.getWriter().append("Respuesta desde un Servlet Osgi");
 }}

Como podemos ver, se trata de un servlet normal, que debería ser mapeado en el web.xml y desplegado dentro de un contenedor de servlets.

  • Activación del servlet

A diferencia del modelo tradicional (definido por la especificación JEE), la activación del servlet no requiere ningún web.xml. En su lugar, definiremos (al igual que cualquier otro servicio OSGI) un nuevo punto de extensión de nuestra aplicación. Para ello accederemos a la pestaña “Extension” y añadiremos la extensión “org.eclipse.equinox.http.registry.servlet” a nuestro módulo. Con esto le hemos indicado a OSGi que nuestro módulo hace uso del contenedor de Servlet.

Añadir extension point para definir un servicio de tipo servlet

El siguiente paso será indicar la clase que implementa el nuevo servlet y el mapeo, para ello simplemente definiremos la propiedad alias y class del nuevo servlet asociado a la extensión creada previamente.

Configurar extensiones OSGi

Con esto ya tenemos nuestra primera aplicación web OSGi.

  • Probando nuestra aplicación.

Para probar la aplicación sólo es necesario ejecutar el proyecto (Run As…>OSGi Framework) y acceder con el navegador a http://localhost:8080/exampleSi todo ha funcionado correctamente, en consola deberemos ver algo como lo siguiente:

Persistence bundle started.
Activado módulo OSGi: Ejemplo OSGI!!
Activado Servlet OSGiProviderTracker: New service detected...
ProviderTracker: Added service org.eclipse.persistence.jpa.osgi.PersistenceProviderOSGi
Petición al Servlet OSGi

Aunque aquí sólo se muestra un ejemplo muy básico, OSGI ya nos ha demostrado ser de mucha utilidad en proyectos reales muy complejos.

Ampliando nuestra matriz de compatibilidad. Internet Explorer 9

19 mar 2010

En Viafirma, continuando con el compromiso de soporte universal de navegadores, nos hemos adelantado al  lanzamiento del futuro  Internet Explorer 9 y hemos realizado una completa batería de pruebas.

Los resultados han sido muy buenos; las pruebas se realizaron sobre la versión preview de Internet Explorer 9 (1.9.7745.6019) usando un usuario sin permisos de administración sobre diferentes versiones de Windows 7. Gracias a estas pruebas podemos garantizar que, salvo cambios radicales en la versión final, los usuarios de Internet Explorer y Windows 7 podrán seguir firmando (con su DNIe o cualquier otro certificado) en el futuro.

Viafirma IE 9 Windows 7

Si quieres probarlo por ti mismo, te invitamos a que pruebes http://viafirma.viavansi.com/viafirma

Augi@s, sistema de gestión de residuos pionero en hablar E3L

22 feb 2010

E3L son las siglas de Environmental Electronic Exchange Language y nace ante la necesidad de establecer un formato estándar de intercambio de datos ambientales entre las distintas comunidades autónomas. Se trata de un proyecto colaborativo, en el que las AA PP implicadas consensúan los flujos de información y los plasman en un lenguaje común con unas reglas definidas y aceptadas por todos. E3L proporciona no sólo las reglas para comunicar plataformas tecnológicas, sino que conforma el primer diccionario electrónico de datos ambientales (metadatos). E3L cubre por ejemplo la presentación telemática de la Memoria Anual de Gestores de residuos, la Declaración Anual de Productores de residuos, los Documentos de Control y Seguimiento de residuos, etc. Para más información sobre este proyecto se pueden visitar los portales del proyecto:

La Consejería de Medio Ambiente de la Junta de Andalucía ha apostado fuerte por la iniciativa y como resultado de ello confió en VIAVANSI para construir Augi@s, un sistema integral de gestión de residuos pionero al hablar E3L. Augi@s permite completar el ciclo de un documento desde su creación hasta su presentación y firma. El sistema ha sido diseñado para hablar en lenguaje E3L; por ello, el equipo de proyecto, constituido por personal de la Consejería de Medio Ambiente y de VIAVANSI, ha participado en la definición del estándar durante su desarrollo. Esto supone al fin una garantía de futuro para el formato de los datos manejados por Augi@s.La aplicación está diseñada con la máxima flexibilidad posible, externalizando en un API independiente la gestión del formato E3L, permitiendo adaptarse a los cambios del mismo en poco tiempo, o integrar nuevos elementos como los servicios publicados en E3S, que ya se encuentran en fase de pruebas en Augias.Considerando la aceptación del formato E3L a nivel estatal y la posibilidad de exportar dicho formato a otros países de la UE, podemos decir que la plataforma Augi@s se encuentra en una posición privilegiada de cara al futuro y vuelve a demostrar que, en contra de lo que se supone en varios círculos de opinión, Andalucía suele liderar a nivel nacional la innovación en muchos proyectos tecnológicos.

Por fin un estándar con el que entretejer nuestras aplicaciones.

25 oct 2009

Recientemente se ha liberado la primera versión estable de Weld, la implementación de referencia de Web Beans (Java Context and Dependenty Injection - JSR 299). Y aunque puede parecer una liberación cualquiera, en este caso estamos ante un evento realmente importante para el mundillo Java.

¿Por qué es importante esta liberación?

  • Por fin tenemos un estándar Java para la inyección, publicación, localización y búsqueda de componentes.
  • Promete una mejor orquestación entre componentes JEE, evitando los típicos problemas de interoperabilidad entre Beans Spring, componentes Seam, Wicket, JSF, EL, etc..)
  • Un remplazo estándar a las diferentes soluciones de inyección e IoC como Spring IoC, el prometedor Google Guice o el muy utilizado por nosotros Jboss Seam annotations.
  • Fin del infierno XML, definiendo un mecanismo estándar independiente de ficheros de definición XML, que junto con JSF 2.0, Servlet 3.0, JPA, Jax-ws, etc… simplifican el desarrollo JEE.

¿Consecuencias para la industria a medio plazo?

  • Es demasiado pronto para saberlo, pero…
    ¿Quizás el fin de la guerra de frameworks se inyección?…. (Google Guice vs Spring vs Jboss Seam). Consiguiendo un efecto similar al que consiguió JPA/JDO estandarizando el acceso a datos.
  • Por fin una especificación JEE con la que construir aplicaciones complejas de forma sencilla.
  • En un momento en el que muchas organizaciones están intentando estandarizar sus desarrollos, llegando incluso a restringir o imponer las tecnologías utilizadas, la preselección de implementaciones como Spring IoC o Seam carecerá de sentido. Siendo mucho más coherente la recomendación de estándares en lugar de restringir la evolución natural de la tecnología y la sana competición entre sus diferentes implementaciones.

¿Consecuencia para nosotros?

  • Ninguna…. Gracias a nuestra apuesta por Jboss Seam (desde hace ya unos años), esta especificación se encontraba ya en nuestra hoja de ruta antes incluso de que fuese un Draft, por lo que para nosotros será suficiente con una mínima adaptación al estándar.
  • La implementación es estable, la especificación muy bien pensada, y en las pruebas que hemos realizado con la beta, ha demostrado que consigue simplificar los desarrollos y hacer más comprensible el “oscuro arte de la inyección de componentes”.
  • En breve empezaremos a usarla en algún proyecto piloto (que pueda asumir el riesgo de I+D asociado), analizaremos en detalle los posibles problemas que puedan surgir, y si todo se comporta como promete a mediados de 2010 empezaremos a usar la nueva especificación en nuestros proyectos Java.

¿Defectos?

  • Llega demasiado tarde. Otros frameworks llevan, aunque de una forma mucho menos limpia,  ofreciendo algo similar desde hace ya mucho tiempo.
  • Todavía no conocemos sus defectos. Y eso es un gran problema ya que hasta que no conozcamos sus problemáticas asociadas no será seguro su uso en proyectos de envergadura.
  • Esperemos que en la huida del infierno de los ficheros de configuración XML, no nos metamos en  las tinieblas del uso de inyección e IoC para todo. Ya que una aplicación con una gran cantidad de componentes, comportamientos o atributos que dependen de la inyección hace muy complicada la comprensión de su funcionamiento.

En definitiva, todo indica que estamos antes una de las piezas clave del próximo JEE 6.

Guía de migración de proyectos Java a Maven

16 oct 2009

Objetivos

El objetivo de este artículo es servir de guía básica para la migración manual de proyectos Java no Maven a entorno Maven. Pensado y dirigido especialmente a personas con poca  experiencia previa en Maven, pero con algún conocimiento previo.

Preparación del proyecto

Como es obvio, para migrar un proyecto Java a Maven, deberemos disponer de sus fuentes y todas las librerías dependientes.

Ya que vamos a realizar modificación estructurales importantes en el proyecto, conviene asegurarnos de que los fuentes no están conectados a ningún sistema de control de versiones como Subversion. Para realizar esto, podemos o bien eliminar manualmente todos los directorios .svn de nuestro proyecto o bien desde Eclipse desconectar el proyecto.

Si lo vamos a realizar de forma manual, debemos asegurarnos de eliminar todos los directorios .svn (o .CVS si el proyecto a migrar estuviese conectado a un CVS) A modo de ejemplo, en Linux podemos ejecutar el siguiente comando desde el directorio del proyecto para eliminar todas las referencias a carpetas ‘.svn’:

 

rm -rf `find . -type d -name .svn`

Será mucho más sencillo hacerlo de forma automática desde Eclipse. Para desconectar el proyecto, teniéndolo seleccionado pulsaremos sobre el botón derecho del ratón: Team -> Disconnect.

Desconectar SVN desde Eclipse

Adaptación del proyecto

Aunque la estructura por defecto Maven puede ser modificada, es muy recomendable adaptar la organización del proyecto a migrar a la estructura por defecto más generalizada:

estructura Maven

Para hacer esta modificación de la estructura hay que tener especial cuidado en algunos aspecto o convenciones Maven:

  • Los ficheros de recursos: Maven hace una distinción entre los ficheros de clases java y los ficheros de recursos .properties y XML’s y, de hecho, salvo que le digamos lo contrario, no hará ningún tratamiento de los ficheros no java que se encuentren en el directorio src/main/java. Por este motivo, tendremos que localizar todos los ficheros de recursos (properties, XML’s) que se encuentran en el directorio java y moverlos al directorio resources (src/main/resources).
  • Eliminar la carpeta classes. Es muy común que proyectos no Maven tengan en su carpeta WEB-INF/classes los compilados del proyecto. Esta situación no sólo no es recomendable sino que puede producir problemas, por lo que los eliminaremos confiando en Maven para su generación cuando sea necesario.

Definir el pom.xml del proyecto

Una vez que la estructura del proyecto se ha adaptado a la filosofía Maven, el siguiente paso es definir el pom.xml del proyecto.

Partiremos de un fichero pom.xml básico. Este fichero de origen no tiene dependencias; durante el proceso lo adaptaremos y posteriormente iremos refinando la configuración hasta alcanzar una “mavenización” completa del proyecto.

Una vez colocado el pom.xml en el raíz de la aplicación, lo modificamos indicando el nombre del proyecto y la información básica relativa a los desarrolladores, organización y repositorio de dependencias utilizado.

Antes de continuar y añadir las dependencias, podemos hacer una comprobación previa y verificar que efectivamente nuestro IDE, en este caso Eclipse, reconoce correctamente la nueva estructura del proyecto.

Para ello nos vamos a la consola y en el directorio en el que se encuentra nuestro proyecto ejecutamos la siguiente orden:

mvn clean eclipse:eclipse

(Requiere disponer de Maven correctamente instalado en la máquina).

Si la configuración del entorno es correcta, obtendremos una salida similar a esta:

 

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'eclipse'.
[INFO] ------------------------------------------------------------------------
[INFO] Building ejemplo
[INFO]    task-segment: [clean, eclipse:eclipse]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting file set: /home/felix/workspaces/ejemplo/target (included: [**], excluded: [])
[INFO] Preparing eclipse:eclipse
[INFO] No goals needed for project - skipping
[INFO] [eclipse:eclipse]
[INFO] Adding support for WTP version 1.5.
[INFO] Using source status cache: /home/felix/workspaces/ejemplo/target/mvn-eclipse-cache.properties
[INFO] File /home/felix/workspaces/ejemplo/.project already exists.
       Additional settings will be preserved, run mvn eclipse:clean if you want old settings to be removed.
[INFO] Wrote Eclipse project for "ejemplo" to /home/felix/workspaces/ejemplo.
[INFO]
       Sources for some artifacts are not available.
       Please run the same goal with the -DdownloadSources=true parameter in order to check remote repositories for sources.
       List of artifacts without a source archive:
         o javax.servlet:servlet-api:2.4
         o javax.servlet.jsp:jsp-api:2.1
         o junit:junit:3.8.1

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Sep 3 11:54:28 CET 2008
[INFO] Final Memory: 10M/80M
[INFO] ------------------------------------------------------------------------

Nos vamos a Eclipse, refrescamos el proyecto (F5 teniendo seleccionado el proyecto) y comprobamos que la nueva estructura es correcta.

Ahora que hemos comprobado que eclipse ha reconocido la nueva estructura, el siguiente paso es definir en nuestro pom.xml las dependencias. Para hacer esto eliminamos todos los .jar que se encuentran en el directorio /WEB-INF/lib y nos quedamos con una copia de ellos para posteriormente ir resolviendo las dependencias del proyecto original. Una recomendación es cortar la carpeta /WEB-INF/lib a otra ruta de nuestro disco.

Resolución de dependencias

Esta es la fase más delicada del proceso, ya que debemos asegurarnos de que todas las dependencias del proyecto quedan correctamente declaradas en el fichero pom.xml. Para realizar esta tarea es recomendadle utilizar alguna aplicación web que nos ayude a la localización de las librerías, como por ejemplo MvnRepository o MvnBrowser (recomendada), en la que podremos buscar cada uno de nuestros jar y encontrar la definición en el pom.xml que debemos utilizar.

Migración de proyectos maven con mvnBrowser

Gracias a esta web, una vez que tengamos localizada la dependencia, solo tendremos que copiar el bloque POM Dependency a nuestro fichero pom.xml.

Iremos repitiendo este proceso de forma iterativa para todos nuestras librerías .jar y añadiendo la definición de la dependencia a nuestra zona de dependencies, con ciertas salvedades y consideraciones que introducimos a continuación.

Consideraciones especiales

Hay ocasiones en las que determinar la definición de la dependencia en nuestro pom.xml puede no ser una tarea trivial. Se comentan a continuación los mecanismos de actuación recomendados según diversas casuísticas:

  • No se indica la versión de la librería en el nombre del fichero.

Por ejemplo, podemos encontrarnos una librería llamada axis-ant.jar, por lo que tendremos que averiguar previamente la versión de la librería de cara a definir la dependencia en el fichero pom.xml. Para esto suele ser muy efectivo descomprimir la librería y consultar el fichero /META-INF/MANIFEST.MF. A modo de ejemplo, en dicha librería mencionada observaríamos una linea similar a la siguiente: “Implementation-Version: 1.2.1 2243 June 14 2005″. Una vez que conozcamos la versión podremos realizar la búsqueda de la forma usual. , 1.1.1.1. Sabemos que la librería fue generada por maven, pero no conocemos su definición.

No conocemos el groupId, artifactId, etc. Podemos descomprimir el .jar y acceder al fichero pom.xml que se encuentra en /META-INF/maven para comprobar el groupId, artifactId y versión de la dependencia.

  • Dependencias especiales JEE.

Algunos jars, como por ejemplo servlet.jar, son aportados por el contenedor de aplicaciones, por lo que tendremos que definirlas marcándolas como provided. Esto le indica a Maven que estas librerías pueden ser utilizadas en tiempo de compilación, pero no serán agregadas al empaquetado final. Para declarar una dependencia de esta forma incorporaremos en nuestro pom.xml un código como este:

 

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.4</version>
      <scope>provided</scope>
</dependency>
  • Librerías ya consideradas en las dependencias transitivas

Muchas de las dependencias dependen a su vez de otras librerías, por lo que Maven añadirá de forma transitiva nuevas librerías a nuestro proyecto. En estos casos no necesitamos definir estas nuevas dependencias transitivas en nuestro pom.xml. Como ejemplo, supongamos que un proyecto depende de estas librerías:

  • xalan-2-6.0.jar
  • xercesImpl
  • xml-apis

Al buscar la librería xalan-2-6.0.jar, observamos que la librería depende a su vez de las otras dos librerías. Por ello, para este ejemplo bastaría con declarar la dependencia a xalan-2-6.0.jar en nuestro pom.xml. Dependencias transitivas.

  • Conflictos entre librerías

En ocasiones nos podemos encontrar con que dos librerías tengan en sus dependencias a una misma tercera librería, pero de distinta versión. Ello haría que maven incluyese en nuestro Classpath 2 versiones de una misma librería, originando conflictos por duplicado de clases. En ese caso debe declararse en la dependencia de una de ellas una directiva para excluir la descarga de la librería conflictiva.

Por ejemplo, en un proyecto deseamos utilizar la librería siguiente:

 

<artifactId>jaxws-api</artifactId>
<groupId>javax.xml.ws</groupId>
<version>2.1-1</version>

Y tenemos dependencia a com.sun.xml.ws / jaxws-rt, esta librería se trae como dependencia transitiva otra versión de la librería mencionada anteriormente. Declaramos una exclusión para evitarlo:

 

<dependency>
  <groupId>com.sun.xml.ws</groupId>
  <artifactId>jaxws-rt</artifactId>
  <version>2.1.4</version>
  <exclusions>
    <exclusion>
      <artifactId>jaxws-api</artifactId>
      <groupId>javax.xml.ws</groupId>
    </exclusion>
  </exclusions>
</dependency>
  • Tenemos una librería que se encuentra en los repositorios, pero no hemos podido averiguar el número de versión.

En esta situación, si la librería no parece problemática, podríamos optar por elegir la última versión de la dependencia. En el caso de que consideremos que la versión que utiliza el proyecto puede originar problemas, lo mejor es añadir esta librería manualmente a nuestro repositorio (como si fuese una librería específica del proyecto), según se explica en el próximo punto.

  • La librería es específica del proyecto.

En estos casos tendremos que subir la dependencia a nuestro repositorio de librerías y, para evitar conflictos posteriores, se recomienda que sea subida con el mismo groupId de nuestro proyecto. Supongamos que migrando un proyecto nos topamos con librería example1.jar que no se encuentra en ningún repositorio público. En este caso la subimos a nuestro repositorio por ejemplo con la siguiente definición:

 

<dependency>
    <groupId>com.viavansi.examples</groupId>
    <artifactId>example1</artifactId>
    <version>0.0.1</version>
</dependency>

En la siguiente figura vemos cómo desplegamos una librería a Artifactory:

Artifactory

Comprobación de dependencias

Una vez que hayamos finalizado este proceso de definición de todas las dependencias en nuestro pom.xml, ejecutaremos en consola mvn dependency:tree (situados en el directorio donde se encuentre el fichero pom.xml del proyecto) para comprobar que las dependencias que se han incorporado al proyecto son las correctas. Este paso de verificación es muy importante en las migraciones de este tipo de proyectos, ya que es muy posible que alguna dependencia transitiva genere problemas. Como ejemplo, podemos observar la siguiente salida en la que comprobamos que no hay dependencias transitivas que entren en conflicto con alguna de nuestras librerías:

 

[INFO] [dependency:tree]
[INFO] com.viavansi.examples.examples1:war:0.0.1
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] +- javax.servlet.jsp:jsp-api:jar:2.1:provided
[INFO] +- javax.servlet:servlet-api:jar:2.4:provided (scope not updated to compile)
[INFO] +- javax.activation:activation:jar:1.1:compile
[INFO] +- avalon-framework:avalon-framework-impl:jar:4.1.5:compile
[INFO] +- axis:axis-ant:jar:1.2.1:compile
[INFO] +- axis:axis:jar:1.2.1:compile
[INFO] +- javax.mail:mail:jar:1.3.1:compile
[INFO] +- commons-beanutils:commons-beanutils:jar:1.6:compile
[INFO] +- commons-codec:commons-codec:jar:1.3:compile
[INFO] +- commons-collections:commons-collections:jar:3.2:compile
[INFO] +- commons-dbcp:commons-dbcp:jar:1.2.2:compile
[INFO] +- commons-digester:commons-digester:jar:1.6:compile
[INFO] |  - xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] +- commons-discovery:commons-discovery:jar:0.2:compile
[INFO] +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] +- commons-io:commons-io:jar:1.3.1:compile
[INFO] +- commons-lang:commons-lang:jar:2.2:compile
[INFO] +- commons-logging:commons-logging:jar:1.1:compile
[INFO] |  +- logkit:logkit:jar:1.0.1:compile
[INFO] |  - avalon-framework:avalon-framework:jar:4.1.3:compile
[INFO] +- commons-pool:commons-pool:jar:1.3:compile
[INFO] +- displaytag:displaytag:jar:1.1:compile
[INFO] +- displaytag:displaytag-export-poi:jar:1.1:compile
[INFO] +- dom4j:dom4j:jar:1.6.1:compile
[INFO] +- org.extremecomponents:extremecomponents:jar:1.0.1:compile
[INFO] +- com.lowagie:itext:jar:1.4.8:compile
[INFO] +- oro:oro:jar:2.0.7:compile
[INFO] +- javax.xml:jaxrpc-api:jar:1.1:compile
[INFO] +- javax.servlet:jstl:jar:1.1.2:compile
[INFO] +- log4j:log4j:jar:1.2.8:compile
[INFO] +- com.oracle:ojdbc14:jar:9.0.2.0.0:compile
[INFO] +- poi:poi:jar:2.5.1-final-20040804:compile
[INFO] +- javax.xml.soap:saaj-api:jar:1.2:compile
[INFO] +- org.springframework:spring:jar:2.0.5:compile
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- struts:struts:jar:1.2.9:compile
[INFO] |  +- commons-fileupload:commons-fileupload:jar:1.0:compile
[INFO] |  +- commons-validator:commons-validator:jar:1.1.4:compile
[INFO] |  - antlr:antlr:jar:2.7.2:compile
[INFO] +- wsdl4j:wsdl4j:jar:1.5.1:compile
[INFO] +- wss4j:wss4j:jar:1.5.0:compile
[INFO] +- xalan:xalan:jar:2.6.0:compile
[INFO] +- org.apache.xmlgraphics:xmlgraphics-commons:jar:1.2:compile
[INFO] +- xml-security:xmlsec:jar:1.2.1:compile
[INFO] +- org.directwebremoting:dwr:jar:2.0.3:compile
[INFO] +- com.viavansi:plantilla-client:jar:0.0.13:compile
[INFO] +- net.sourceforge.barbecue:barbecue:jar:1.5-beta1:compile

En caso de detectar librerías duplicadas a causa de las dependencias transitivas, deberemos proceder a definir las exclusiones necesarias en las dependencias afectadas, según se indicó anteriormente.