Gestion De La Dépendance À OSGi Hell

UPDATE 2: comme mon blog est un peu mort, les liens se sont dégradés pour que vous puissiez voir les articles ici:

https://www.dropbox.com/s/xvobgzqnl43kcda/Managing_OSGi_Transitive_Dependencies__Part_1____CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/0bdooux4yhrf8lf/Managing%20OSGi%20Transitive%20Dependencies%20%28...pdf?dl=0

https://www.dropbox.com/s/km3mxqah6oy23iq/Why%20using%20Require-Bundle%20is%20a%20bad%20pract...pdf?dl=0

https://www.dropbox.com/s/mtenchtjopcrmr8/How%20many%20ways%20can%20we%20import%20bundles%20in%20OSGi_%20_%20CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/sldxynx3fl8vn61/Managing%20OSGi%20Transitive%20Dependencies%20%282...pdf?dl=0

j'ai un projet maven, en utilisant le très célèbre plugin Felix maven bundle configuré dans my POM.XML de la façon suivante:

<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>

puis-je avoir une certaine 1er degré/niveau de dépendances inclus dans mon POM ainsi:

<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>

Et maintenant, mon problème commence... Si je fais mvn install je vais avoir mon paquet bien construit avec son très grand manifeste.MF et tout, mais je n'obtiendrai pas les autres paquets de dépendances, ce qui signifie que si je prends mon fichier bundle et que je le laisse tomber sur mon instance OSGi framework je vais obtenir quelque chose comme "Impossible de résoudre 1.0: manque d'exigence [1.0] osgi.câblage.package; (&(osgi.câblage.package= etc..."

donc une façon que j'ai trouvée pour créer mes paquets de dépendances de premier niveau était de créer un profil dans mon POM comme ceci:

<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>

Et de cette façon, lorsque j'execute mvn -Pcreate-osgi-faisceaux-de-dépendances bundle:wrap je vais chercher les paquets, bien construits et qui fonctionnent. Mais voilà le vrai problème. Ces bundles aussi ont des dépendances sur leur propre, ainsi ils auront besoin d'avoir leurs dépendances enveloppées autour comme des faisceaux. Selon de nombreuses pages web, il y a longtemps que nous avions le mvn org.Apache.felix: maven-bundle-plugin: bundleall but de faire cela pour nous, mais j'ai essayé, c'est buggy et Return exceptions et il est marqué comme étant déprécié, selon Stuart il sera supprimé dans maven 2.4.1 et plus tard (réf: https://issues.apache.org/jira/browse/FELIX-4145).

Donc, mon la seule solution maintenant est de, manuellement, vérifiez chaque manifeste de mes dépendances de premier niveau et allez sur google pour les bocaux contenant les paquets requis, ajoutez-les à mon POM.XML comme les dépendances maven, puis exécutez mvn -Pcreate-osgi-faisceaux-de-dépendances bundle:wrap pour les envelopper en paquets.

C'est ce qu'on appelle l'enfer de la dépendance...

Est-il possible d'automatiser cette tâche de résoudre nième les dépendances de niveau pour un projet Maven-bundle osgi? C'est-à-dire: faire étudier par maven chacun des fichiers du Manifeste de mes dépendances de premier niveau, lire les paquets d'importation, chercher dans le fichier central les pots qui fournissent de tels paquets, les télécharger et les emballer sous forme de paquets?

Remarque: veuillez fournir des instructions détaillées sur la façon d'y parvenir, ne vous contentez pas de créer un lien vers cet outil ou vers l'outil qui pourrait résoudre ce problème. Le problème majeur avec ces outils est leur manque d'exemples et de documentation. Exemple bundleall est déprécié, mais il ne semble pas y avoir d'outil pour le remplacer, du moins dans leur documentation officielle de plugin Maven bundle, qui est déprécié jusqu'à présent... Je suis certain d'avoir croisé des outils capables de le faire, mais le manque de documentation interdit à l'internaute novice de le savoir...

Merci!





EDIT-1:

Merci pour vos réponses :) Je pense que je n'ai pas expliqué ma situation de la manière la plus appropriée et je ressens des difficultés à le faire simplement par le texte. Ou peut-être que j'din comprends pas votre réponse. Je suis tout à fait" fresh-new " À OSGi et la seule connaissance que j'ai vient de livres (OSGi en action et semblables) et de Google.

Imaginez que mon paquet importe des paquets A et B. Cependant, emballez un paquet d'importations C, et un paquet d'importations B C aussi. Mais maintenant C importe les paquets D, E, F et G. d'autre part hand package d IMPORTE une tonne d'autres paquets ainsi que E, F et G.

les seuls paquets que j'ai dans mon ordinateur sont mon propre paquet et les paquets qui fournissent les paquets A et B parce qu'ils sont mes dépendances de premier niveau. Cependant, je n'ai aucun des autres faisceaux requis, même s'ils sont installés comme des pots dans mon dossier d'installation JDK, Je ne les ai pas comme des faisceaux, ni même ne sais-je Où puis-je obtenir les pots pour les envelopper (en fait je sais mais laisse imaginer que je ne le faites pas).

Je m'attendais à ce que l'outil de compilation exécute un algorithme similaire à celui-ci:

1) allez à mon manifeste.MF et de lire l'Import-Package champ. Énumérer tous les paquets nécessaires et leur reee. version.

2) cherchez quelque part sur Internet les pots ou les paquets des bibliothèques dont j'ai besoin.

3) téléchargez chacun d'eux et vérifiez s'ils ne sont que des pots ordinaires ou ont un fichier manifeste osgi valide (c'est à dire qu'il s'agit d'un paquet)

3.1)si ils sont un bundle, copiez - les dans mes paquets/ dossiers.

3.2) else envelopper le pot dans un paquet en utilisant n'importe quel outil pour faire cela et copier le paquet dans mon paquet/ dossier.

4) maintenant, pour chaque nouveau paquet téléchargé/créé, répétez les étapes 1),2), 3) et 4).

Ce que je veux comme résultat final: Un paquet pour chaque bibliothèque à laquelle j'ai une dépendance directe ou indirecte, de sorte que je puisse les installer à la volée dans mon instance OSGi Framework, comme felix ou equinox.

Ce que je ne veux pas:

1) je dois le faire manuellement, parce que si j'essaie de résoudre chaque dépendance de dépendance, je pourrais passer des heures ou des jours à collecter et emballer des pots.

2) intégration de toutes les dépendances dans un pack ubber / mega. C'est une mauvaise pratiquer selon plusieurs livres que j'ai lus, il est plus difficile de maintenir chaque dépendance individuellement et aussi, il corrompt la modularité.

Remarque: mon problème ne concerne pas la tâche particulière d'emballer un pot dans un paquet, mais de le faire récursivement sur les importations de chaque paquet, même si elles doivent être téléchargées à partir d'un dépôt en ligne tel que maven's central.

y a-t-il un moyen de le faire automatiquement ou je rate quelque chose de très important à propos D'OSGi? Si grand que je n'aurais jamais besoin de faire ça que je demande?

EDIT-2:

certaines, sinon toutes les dépendances Import-Package pourraient être résolues au moment de l'exécution. Imaginez le cadre OSGi essayer de lancer un paquet, mais au lieu de montrer le message d'erreur de "Impossible de résoudre 8.0: exigence manquante [8.0] osgi.câblage.package;" il serait à la recherche de ce paquet en ligne, le télécharger et l'installer à la volée. La vie serait tellement plus facile.

17
demandé sur PedroD 2014-05-19 15:59:25

5 réponses

utilisez Conditional-Package de maven-bundle-plugin pour mettre en ligne de façon récursive tous les paquets requis dans votre pack JAR et activer l'étiquette true.

3
répondu 2014-10-24 16:06:47

si vous voulez envelopper des bocaux qui ne sont pas des paquets mais qui doivent juste être des paquets comme un librarys dans OSGi framework, vous pouvez l'envelopper avec l'outil BND. Voir le lien comment créer/générer des paquets OSGi à partir de pots tiers existants?

mais je peux voir que vous utilisez des libaires très courantes qui ont déjà été converties en paquets osgi. Vous pouvez trouver beaucoup de bibliothèques converties en paquets dans le SpringSource Enterprise Bundle Référentiel.

mais si vous ne trouvez aucune bibliothèque qui n'est pas convertie en un bon paquet OSGi, vous pouvez utiliser le protocole WRAP de PAX-URL pour installer ces dépendances dans le framework OSGi. L'utilisation de ces protocoles dépend du framework OSGi que vous utilisez, mais dans apache karaf est installé par défaut. Par exemple, pour installer une bibliothèque à partir du dépôt maven:

root@karaf> osgi:install -s 'wrap:mvn:commons-lang/commons-lang/2.4$Bundle-SymbolicName=commons-lang&Bundle-Version=2.4'

cette instruction installe la bibliothèque commons-lang à partir du dépôt maven dans OSGi framework et l'envelopper comme OSGi faisceau avec les en-têtes apparaissent dans la ligne.

pour les dépendances d'installation automatique comme vous le dites dans la seconde édition, il y a plusieurs solutions mais c'est un peu de travail. Il existe deux solutions principales pour fournir automatiquement des faisceaux à OSGi framework, les faisceaux "Felix OBR" et "Felix Provisioning" et le dépôt Equinox p2. Tous deux ont des commandes de console pour installer automatiquement des paquets et des fonctionnalités. Le problème, c'est qu'en fait, je ne trouve pas bon dépôt public de faisceaux. Vous devez construire votre propre dépôt avec tous les paquets dont vous avez besoin.

si vous utilisez maven-bundle-plugin, lorsque vous installez des artéfacts dans votre dépôt maven local, le plugin met à jour le fichier "repository.xml " situé dans la racine de votre dépôt pour refléter les exigences et les capacités de vos faisceaux. Ce fichier est un fichier de dépôt OBR.

5
répondu Fernando Rincon 2014-05-20 20:47:41

ce que je veux comme résultat final: un paquet pour chaque bibliothèque à laquelle je avoir une dépendance directe ou indirecte, pour que je puisse les installer à la volée dans mon instance OSGi Framework, comme felix ou equinox.

Ok, si je comprends bien votre question, vous voulez quelque chose comme le 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 vous rencontrez le problème, que vous avez beaucoup de dépendances sans osgi-Manifeste, vous devez vérifier si elles sont disponible dans le dépôt SpringSource enterprise bundlehttp://ebr.springsource.com/repository/ et les paquets apache-servicemix à http://search.maven.org/#search/ga/1/g%3A%22org.apache.servicemix.bundles%22 (as mentioned in my comment)

3
répondu Martin Baumgartner 2015-05-27 17:00:42

p2-maven-plugin c'est exactement ce que vous avez décrit de 1 à 4. il utilise en fait tycho pour construire le dépôt p2, mais vous pouvez aussi l'utiliser pour collecter et regrouper vos dépendances et vos dépendances transitives. Je n'écris pas d'exemple ici parce que dans le lien ci-dessus chaque pensée est bien documentée avec des exemples d'une manière facile à comprendre.

espérons que cette aide

0
répondu Hisham Khalil 2016-05-03 11:14:29

ces fonctions incluent vos dépendances jars dans jar on folder: OSGI-INF/lib/

Dans la construction.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()
  ]
}

**

0
répondu Josiel Novaes 2017-02-08 12:41:35