java - Manejando la Dependencia de OSGi Infierno
maven dependencies (5)
Si desea envolver los archivos jar que no son paquetes, sino que solo necesita que estos archivos sean paquetes como una biblioteca en el marco OSGi, puede envolverlo con la herramienta BND. Vea el enlace Cómo crear / generar paquetes OSGi a partir de jar de terceros existentes?
Pero puedo ver que usas bibliotecarias muy comunes que ya se han convertido en paquetes de osgi. Puede encontrar muchas bibliotecas convertidas en paquetes en el Repositorio de lotes de SpringSource Enterprise .
Pero si no puede encontrar ninguna biblioteca que no se convierta en un buen paquete OSGi, puede usar el protocolo WRAP de PAX-URL para instalar estas dependencias en el marco OSGi. Para usar este protocolo depende del marco OSGi que esté utilizando pero en apache karaf está instalado de manera predeterminada. Por ejemplo, para instalar una biblioteca del repositorio de maven:
root@karaf> osgi:install -s ''wrap:mvn:commons-lang/commons-lang/2.4$Bundle-SymbolicName=commons-lang&Bundle-Version=2.4''
Esta instrucción instala la biblioteca commons-lang del repositorio maven en OSGi framework y lo envuelve como paquete OSGi con los encabezados en la línea.
Para las dependencias de instalación automática como dices en la segunda edición, hay varias soluciones, pero es un poco trabajo. Existen dos soluciones principales para el aprovisionamiento automático de paquetes en OSGi framewor, los repositorios "Félix OBR" y "Felix Provisioning" y el repositorio Equinox p2. Ambos tienen comandos de consola para instalar automáticamente paquetes y características. El problema es que en realidad no puedo encontrar un buen repositorio público de paquetes. Necesita construir su propio repositorio con todos los paquetes que necesite.
Si usa maven-bundle-plugin, cuando instala artefactos en su repositorio maven local, el plugin actualiza el archivo "repository.xml" ubicado en la raíz de su repositorio para reflejar las necesidades y capacidades de sus paquetes. Este archivo es un archivo de repositorio OBR.
ACTUALIZACIÓN 2 : Como mi blog está un poco muerto, los enlaces se degradaron para que pueda ver los artículos aquí:
Tengo un proyecto maven, utilizando el famoso plugin de felix maven configurado en mi POM.XML de la siguiente manera:
<packaging>bundle</packaging>
(...)
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>jlifx.*</Export-Package>
<!-- <Embed-Dependency>*</Embed-Dependency> -->
</instructions>
</configuration>
</plugin>
Y también tengo algunas dependencias de primer grado / nivel incluidas en mi POM:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha1</version>
</dependency>
</dependencies>
Y ahora mi problema comienza ... Si instalo mvn obtendré mi paquete bien construido con su gran MANIFEST.MF y todo, pero no obtendré los otros paquetes de dependencias, lo que significa que si tomo mi paquete de archivos y colocarlo en mi instancia de OSGi framework obtendré algo como "No se puede resolver 1.0: requisito faltante [1.0] osgi.wiring.package; (& (osgi.wiring.package = etc ..."
De modo que una de las formas que he encontrado para crear los paquetes de las dependencias de primer nivel fue crear un perfil en mi POM de esta manera:
<profiles>
<!-- http://www.lucamasini.net/Home/osgi-with-felix/creating-osgi-bundles-of-your-maven-dependencies -->
<!-- -Pcreate-osgi-bundles-from-dependencies bundle:wrap -->
<profile>
<id>create-osgi-bundles-from-dependencies</id>
<build>
<directory>${basedir}/bundles</directory>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.0.1</version>
<extensions>true</extensions>
<executions>
<execution>
<id>wrap-my-dependency</id>
<goals>
<goal>wrap</goal>
</goals>
<configuration>
<wrapImportPackage>;</wrapImportPackage>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Y de esta forma cuando ejecuto mvn -Pcreate-osgi-bundles-from-dependencies bundle: wrap obtengo los bundles, bien construidos y en funcionamiento. Pero, aquí viene el verdadero negocio. Esos paquetes también tienen dependencias propias, por lo que necesitarán tener sus dependencias empaquetadas como paquetes. Según numerosas páginas web, hace mucho tiempo teníamos el objetivo mvn org.apache.felix: maven-bundle-plugin: bundleall para hacer eso por nosotros, pero lo he intentado, tiene errores y excepciones de devolución y está marcado como obsoleto , según Stuart, será eliminado en maven 2.4.1 y posteriores (ref: https://issues.apache.org/jira/browse/FELIX-4145 ).
Así que mi única solución ahora es, manualmente , verificar cada manifiesto de mis dependencias de primer nivel e ir a google para ver los frascos que contienen los paquetes necesarios, agregarlos a mi POM.XML como dependencias maven y luego ejecutar mvn -Pcrear-osgi-bundles -from-dependencies bundle: wrap para envolverlos como paquetes.
Esto es lo que se conoce como el infierno de la dependencia ...
¿Hay alguna manera de automatizar esta tarea de resolver enésimas dependencias de nivel para un proyecto maven-bundle osgi? Es decir, hacer que maven estudie cada uno de los archivos de manifiesto de mis dependencias de primer nivel, lea los paquetes de importación, busque en el repositorio central de jar''s que proporcionen dichos paquetes, descárguelos y envuélvalos como paquetes.
Nota: proporcione instrucciones detalladas sobre cómo lograr esto; no se limite a vincular esta herramienta o la que pueda resolver este problema. El principal problema con estas herramientas es su falta de ejemplos y documentación. Por ejemplo, bundleall está en desuso, pero parece que no hay ninguna herramienta para reemplazarlo, al menos en su documentación oficial del paquete maven plugin, que está obsoleto hasta el momento ... Estoy seguro de haber cruzado con herramientas capaces de hacer esto, pero la falta de documentación prohíbe que el usuario novato sepa que ...
¡Gracias!
EDIT-1:
Gracias por tus respuestas hasta el momento :) Creo que no expliqué mi situación de la manera más adecuada y tengo algunas dificultades para hacerlo solo por texto plano. O tal vez no entendí tu respuesta. Soy bastante "nuevo" en OSGi y el único conocimiento que tengo proviene de libros (OSGi en Acción y similares) y de Google.
Imagine que mi paquete importa los paquetes A y B. Sin embargo, el paquete A importa el paquete C, y el paquete B importa C también. Pero ahora C importa los paquetes D, E, F y G. Por otro lado, el paquete D importa una tonelada de otros paquetes, al igual que E, F y G.
Los únicos paquetes que tengo en mi computadora son mi propio paquete y los paquetes que proporcionan los paquetes A y B porque son mis dependencias de primer nivel. Sin embargo, no tengo ninguno de los otros paquetes necesarios, incluso si están instalados como frascos en mi carpeta de instalación JDK, no los tengo como paquetes, ni siquiera sé dónde puedo obtener los frascos para envolverlos ( en realidad lo sé, pero imaginemos que no).
Lo que esperaría que hiciera la herramienta de compilación era ejecutar un algoritmo similar al siguiente:
1) Vaya a mi paquete MANIFEST.MF y lea el campo Importar-Paquete. Enumere todos los paquetes requeridos y su resp. versiones.
2) Busque en alguna parte de Internet los archivos jar o paquetes de mis bibliotecas requeridas.
3) Descargue cada uno y compruebe si son simplemente jarras o tienen un archivo de manifiesto de Osgi válido (es decir, son un paquete)
3.1) si son un paquete , cópielos a mi paquete / carpeta.
3.2) de lo contrario, envuelva el contenedor en un paquete utilizando la herramienta para hacerlo y copie el paquete en mi paquete / carpeta.
4) Ahora, para cada nuevo paquete descargado / creado, repita los pasos 1), 2), 3) y 4).
Lo que quiero como resultado final: un paquete para cada biblioteca para el que tengo una dependencia directa o indirecta, para que pueda instalarlo sobre la marcha en mi instancia de OSGi Framework, como felix o equinox.
Lo que no quiero
1) Tengo que hacer esto manualmente, porque si trato de resolver cada dependencia de dependencia puedo pasar horas o días recolectando y envolviendo frascos.
2) Incruste todas las dependencias en un paquete ubber / mega. Esa es una mala práctica según varios libros que he leído, es más difícil mantener cada dependencia individualmente y también, corrompe la modularidad.
Nota: mi problema no es acerca de la tarea particular de empaquetar un contenedor en un paquete, sino de hacerlo recursivamente a las importaciones de cada paquete, incluso si necesitan ser descargadas de un repositorio en línea como el central de maven.
¿Hay alguna manera de hacer esto automáticamente o me falta algo muy grande sobre OSGi? ¿Tan grande que nunca necesitaría hacer esto que estoy pidiendo?
EDIT-2:
Algunas, si no todas, las dependencias del paquete de importación podrían resolverse en tiempo de ejecución. Imagine el OSGi Framework tratando de iniciar un paquete, pero en lugar de mostrar el mensaje de error de "No se puede resolver 8.0: requisito faltante [8.0] osgi.wiring.package;" buscaría ese paquete en línea, lo descargaría e instalaría sobre la marcha. La vida sería mucho más fácil.
Use el paquete condicional de maven-bundle-plugin para recursivamente alinear todos los paquetes requeridos en su paquete JAR y active la etiqueta true.
Lo que quiero como resultado final: un paquete para cada biblioteca para el que tengo una dependencia directa o indirecta, para que pueda instalarlo sobre la marcha en mi instancia de OSGi Framework, como felix o equinox.
De acuerdo, si entiendo tu pregunta correctamente, ¿quieres algo como el complemento maven-dependency-plugin?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/thridparty-libs</outputDirectory>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
<excludeGroupIds>${project.groupId}</excludeGroupIds>
<excludeArtifactIds>...</excludeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
Si enfrenta el problema, que tiene muchas dependencias sin un osgi-Manifest, debe verificar si están disponibles en el repositorio de paquetes empresariales de springsource http://ebr.springsource.com/repository/ y en los paquetes apache-servicemix en http://search.maven.org/#search|ga|1|g%3A%22org.apache.servicemix.bundles%22 (como se menciona en mi comentario)
prueba p2-maven-plugin , hace exactamente lo que has descrito del 1 al 4. realmente usa tycho para compilar el repositorio p2, pero también puedes usarlo para recopilar y agrupar tus dependencias y dependencias transitivas. No estoy escribiendo un ejemplo aquí porque en el enlace anterior cada pensamiento está bien documentado con ejemplos de una manera fácil de entender.
espero que esto ayude
Estas funciones incluyen las dependencias de los archivos jar en la carpeta jar: OSGI-INF / lib /
En build.gradle:
**
dependencies {
...dependencies
}
def bundleClassPath() {
def list = []
configurations.compile.each {
list += ''OSGI-INF/lib/'' + it.name
}
return list.join('','')
}
def includeResource() {
def list = []
configurations.compile.each {
list += ''OSGI-INF/lib/'' + it.name + "=" + it.path
}
return list.join('','')
}
bundle {
instructions << [
''Bundle-ClassPath'' : bundleClassPath(),
''-includeresource'' : includeResource()
]
}
**