viernes, 3 de febrero de 2012

RCP con Java Web Start (JNLP)

Las aplicaciones RCP nacieron a partir del IDE Eclipse, una aplicación standalone que parecía no tener nada que ver con Java Web Start. No obstante, muchas veces interesa poder tener una aplicación autoinstalable y autoactualizable desde la red, por lo que la utilización de la tecnología Java Web Start puede parecer ideal.

Al no ser una de las funcionalidades básicas del entorno PDE, puede resultar un poco difícil entender que se debe hacer para poder exportar aplicaciones RCP a JNLP. En esta entrada del blog os detallaré los pasos a seguir.

Tener listo nuestro producto (product)

Es importante tener un producto realizado y listo para exportar, lo ideal sería probarlo primero exportándolo como un producto Eclipse (mediante la herramienta "Export..." del IDE Eclipse).


Una vez generado, deberemos asegurarnos de que todo funciona correctamente, ya que una vez exportado a JNLP puede ser difícil saber con seguridad que es lo que está fallando.

Crear un wrapper de nuestro producto a través de una Feature

Uno de los requisitos fundamentales de Java Web Start es que todas las librerías que se descarguen dentro de un mismo producto deben estar firmadas con la misma clave (keystore). Por ello, Eclipse nos ofrece la posibilidad de firmar todos los plugins de nuestro producto con su herramienta de exportación (la misma que en el apartado anterior).
El problema que nos plantea esta herramienta es que necesitamos que nuestro producto sea una feature y no un plugin, por lo que necesitamos una pequeña transformación. Deberemos crear una feature que haga de wrapper de nuestro plugin, cosa que es realmente sencilla. Estos son los pasos a seguir:
1. Creamos un nuevo proyecto de eclipse, eligiendo la opción Plug-in Development-->Feature Project.

2. Rellenamos los atributos del proyecto. (Dicen que es importante rellenar el provider, por lo que que mejor lo rellenamos)


3. Seleccionamos el producto anteriormente creado


4. Finalizamos la creación del proyecto.
5. Una vez hecho esto tendremos que añadirle una sola feature más dentro del apartado Included Features del feature.xml de nuestro wrapper: org.eclipse.rcp


Con todo esto ya tendremos creado nuestro wrapper.

Exportar wrapper a JNLP

Para exportar a JNLP nuestra feature utilizaremos de nueva la herramienta de exportación de Eclipse, seleccionando esta vez la opción de Deployable Features. Esta opción la tenemos disponible en la esquina superior-derecha del editor del feature.xml (lo podemos observar en la imagen anterior).
 Para la exportación tenemos que asegurarnos de seguir los siguientes pasos:
1. Seleccionar un directorio de destino donde se situaran los archivos generados.
2. Seleccionar en la pestaña de opciones solamente la opción de empaquetar en archivos JAR individuales y si queremos exportarlo a diferentes plataformas (en este último caso necesitaremos el Delta Pack de Eclipse)


4. Introducir el keystore con el que se firmarán todas las librerías generadas.
5. Seleccionar la opción de generar los archivos JNLP que nos servirán de enlace con la aplicación y introducir el path desde donde se descargará (es probable que tengamos que editar este path más adelante según la distribución de directorios de nuestro servidor)
Una vez hecho todo esto finalizamos y esperamos a que se generen todos los archivos con un poco paciencia, ya que suele ser un proceso un poco largo.

Generar nuestro JNLP base
Tiene que quedar claro que no es suficiente disponer de los archivos JNLP generados por eclipse para poder lanzar nuestra aplicación. Deberemos generar un archivo JNLP parecido al siguiente que nos sirva para lanzar el jnlp adecuado según el sistema operativo del que se disponga:

<?xml version="1.0" encoding="UTF-8"?>
<jnlp
    spec="1.0+"
    codebase="http://url" href="ARCHIVO_JNLP_CREADO.jnlp">

  <information>
    <title> Product </title>
    <vendor>COMPANY</vendor>
    <homepage href="http://www.WEBSITE.es" />
    <description>DESCRIPTION</description>
    <offline-allowed/>

 <icon href="images/logo.png" kind="default"/>
    <shortcut online="true">
        <desktop/>
            <menu submenu="menu">
            <menu submenu="SUBMENU"/>
            </menu>
    </shortcut>

  </information>
  <security>
    <all-permissions/>
  </security>

  <application-desc main-class="org.eclipse.equinox.launcher.WebStartMain">
    <argument>-showsplash</argument>
  </application-desc>

<resources>
<property
        name="eclipse.product"
        value="es.company.product"/>
<jar href="plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar"/>
<property name="osgi.instance.area" value="@user.home"/>
<property name="osgi.install.area" value="@user.home/osgi"/>
<property name="osgi.configuration.area" value="@user.home"/>
<property name="osgi.sharedConfiguration.area" value="@user.home/configuration"/>
<property name="osgi.splashPath" value="platform:/base/plugins/PLUGIN_DONDE_SE_ENCUENTRA_EL_SPLASH"/>
</resources>
<resources os="Linux" arch="x86">
        <property name="osgi.ws" value="gtk"/>
 <extension
        name="Product"
        href="features/product.gtk.x86.jnlp"/>
  </resources>

<resources os="Linux" arch="x86_64">
        <property name="osgi.ws" value="gtk"/>
 <extension
        name="Product"
        href="features/product.gtk.x86_64.jnlp"/>
  </resources>
<resources os="Mac" arch="ppc">
  <extension
        name="Product"
        href="features/product.cocoa.ppc.jnlp"/>
  </resources>
  </resources>
<resources os="Mac" arch="x86">
<extension
        name="Product"
        href="features/product.cocoa.x86.jnlp"/>
  </resources>
  </resources>

<resources os="Mac" arch="x86_64">
 <extension
        name="Product"
        href="features/product.cocoa.x86_64.jnlp"/>
  </resources>

  <resources os="Windows" arch="x86">
    <extension
        name="Product"
        href="features/product.win32.x86.jnlp"/>
<property name="osgi.instance.area" value="@user.home/Application Data"/>
        <property name="osgi.configuration.area" value="@user.home/Application Data"/>
  </resources>

<resources os="Windows" arch="x86_64">
    <extension
        name="Product"
        href="features/product.win32.x86_64.jnlp"/>
<property name="osgi.instance.area" value="@user.home/Application Data"/>
        <property name="osgi.configuration.area" value="@user.home/Application Data"/>

  </resources>

</jnlp>
Este archivo es un ejemplo y no es común para todas las aplicaciones, simplemente os puede ayudar a la hora de generar vuestro script. Para más información sobre cómo generar este tipo de scripts podéis ir aquí.
NOTA: Las propiedades introducidas son necesarias para el correcto funcionamiento de las aplicaciones RCP, es probable que si no se pone alguna de ellas, pueda dejar de funcionar

Problemas encontrados al exportar en multiplataforma
Existen una serie de problemas exportando a un producto RCP a un jnlp multiplataforma, como mínimo en mi caso particular (exportando con Windows7 y Eclipse Indigo).

El error tipo es el siguiente:
org.osgi.framework.BundleException: The activator org.eclipse.ui.internal.WorkbenchPlugin for bundle org.eclipse.ui.workbench is invalid
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleActivator(AbstractBundle.java:171)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:679)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:299)
    at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:440)
    at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:268)
    at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)

En mi caso particular he observado como dentro de los jnlps para Linux y para Mac Os X se incluían enlaces a librerías de Windows. Es por ello que para solucionarlo deberemos firmar los archivos correctos. Este sería el workaround:

1. Firmar los plugins del Delta Pack para subirlos a nuestra carpeta plugins del servidor
2. Modificar los archivos JNLP de cada plataforma para que no se enlacen con los plugins nativos de Windows.

Subir los archivos a nuestro servidor de aplicaciones Java
Por último, solamente falta subir los archivos al servidor y disfrutar de nuestra aplicación en nuestro sistema operativo preferido. Espero que os haya servido de ayuda.

Referencias 
1.http://thomaswabner.wordpress.com/2011/03/28/run-eclipse-rcp-application-via-webstart/ 
2.http://www.toedter.com/blog/?p=650 
3.http://www.techjava.de/topics/2010/02/launching-rcp-via-jws/ 

No hay comentarios:

Publicar un comentario