Maven y proyectos war de osgi

De ChuWiki

Hay contenedores OSGI, como apache Karaf, que soportan ficheros WAB. Un fichero WAB es una aplicación web como los ficheros WAR tradicionales, pero que lleva un fichero META-INF/MANIFEST.MF con entradas de OSGI. Esto hace que el contenedor apache Karaf lo despliegue como una aplicación web, pero a su vez sus clases interacciones con OSGI y otros módulos OSGI tradicionales desplegado en el mismo contendor, exportando servicios a ellos o importándolos de ellos.

Veamos aquí como configurar maven para conseguir un proyecto de este tipo.

El pom.xml[editar]

El fichero pom.xml completo es el siguiente

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.chuidiang.examples</groupId>
        <artifactId>OSGIRestEventBus</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.chuidiang.examples</groupId>
    <artifactId>simplewar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>simplewar Maven OSGI Webapp</name>
    <url>http://chuwiki.chuidiang.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>simplewar</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifestFile>./src/main/webapp/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>3.3.0</version>
                <extensions>true</extensions>
                <executions> 
                    <execution>
                        <id>bundle-manifest</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>manifest</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <supportedProjectTypes>
                        <supportedProjectType>war</supportedProjectType>
                    </supportedProjectTypes>
                    <manifestLocation>./src/main/webapp/META-INF</manifestLocation>
                    <exportScr>true</exportScr>
                    <scrLocation>./src/main/webapp</scrLocation>
                    <instructions>
                        <Implementation-Version>1.0</Implementation-Version>
                        <Bundle-Name>simplewar</Bundle-Name>
                        <Bundle-Activator>com.chuidiang.examples.wab.Activator</Bundle-Activator>
                        <Bundle-SymbolicName>simplewar</Bundle-SymbolicName>
                        <Bundle-ClassPath>.,WEB-INF/classes,{maven-dependencies}</Bundle-ClassPath>
                        <Web-ContextPath>/simplewar</Web-ContextPath>
                        <Embed-Dependency>*;scope=compile;inline=false</Embed-Dependency>
                        <Embed-Directory>WEB-INF/lib</Embed-Directory>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Veamos los detalles interesantes de este pom.xml

Detalles del pom.xml del proyecto wab[editar]

El packaging de nuestro proyecto es war, es decir, un proyecto war normal. Y lleva el maven-war-plugin para construcción del fichero war normal. Hasta aquí nada distinto de un war normal en maven.

Añadimos el plugin maven-bundle-plugin que es el que generará el fichero de manifiesto adecuado para nuestro proyecto wab. Aquí tenemos un par de trucos. Como el packaging no es bundle, que es el que espera maven-bundle-plugin, debemos:

  • Añadir un executions para que genere el fichero de MANIFEST.MF. Esto no es necesario si el packaging el bundle.
  • En la configuración debemos añadir supportedProjectType el packagin war. No es necesario si el packaging es bundle o jar, pero sí lo necesitamos para war.

Ahora debemos poner de acuerdo a ambos plugins maven-war-plugin y maven-bundle-plugin en donde está el fichero MANIFEST.MF. maven-bundle-plugin lo genera, y maven-war-pluging lo empaquetará dentro del war en el sitio adecuado. En maven-war-plugin ponemos en configuración manifestFile indicando donde está el MANIFEST.MF, y en maven-bundle-plugin ponemos manifestLocation para indicar dónde lo va a generar.

En maven-bundle-plugin ponemos también dónde se van a encontrar las clases y las dependencias dentro del fichero war (wab). Las clases deben estar en WEB-INF/classes y las librerías en WEB-INF/lib. Los tags Bundle-Classpath y Embed-Directory configuran esto correctamente.

El tag Web-ContextPath es obligatorio en un fichero wab (war de osgi). Indica al contenedor, cuando lo despliegue, en que contexto se encuentra. En nuestro ejemplo y con apache karaf, se desplegaría en http://localhost:8181/simplewar.

Finalmente un pequeño detalle. Los tags exportScr y scrLocation sólo son necesarios si usamos anotaciones en nuestras clases para instanciar nuestros servicios OSGI. Estas anotaciones son del conjunto de este estilo

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;

maven-bundle-plugin, cuando el packaging es bundle y encuentra esta anotaciones, genera un fichero OSGI-INF/nuestra-clase.xml donde se indica a OSGI que hay un componente o servicio disponible, si debe instanciarlo en el arranque, si necesita otros servicios externos, etc. OSGI no lee las anotaciones, sino que lee los ficheros xml. maven-bundle-plugin genera estos ficheros por nosotros a partir de anotaciones en las clases. Pero sólo lo hace si el packaging es bundle. Así que como nuestro packaging es war, debemos decirle que lo genere con exportScr a true, y decirle dónde generarlo con scrLocation, que debe ser un sitio que luego vaya dentro del war.

Aquí https://github.com/chuidiang/chuidiang-ejemplos/tree/master/OSGI/OSGIRestEventBus/simplewar tienes el ejemplo completo.