Vous pouvez trouver ce billet sur mon nouveau blog avec les informations mises a jour.
Dans le billet précédant [step4] nous avons utilisé le registre de services OSGi pour consommer/fournir le service UserService. Nous avons montré que l'utilisation du registre de services OSGI, permettait de rendre opérationnel le lancement/arrêt du bundle org.akrogen.gestcv.services qui fournit le service UserService :
Dans ce billet je vais expliquer 2 "bonnes pratiques" à suivre dans les Bundle OSGi :
Voici un schéma de ce que nous allons effectuer dans ce billet :

Ce schéma montre que :
Ici nous allons décrire un scénario classique de livraison d'une application. L'application livrée est installée et tous les utilisateurs se connectent dessus. Malheureusement le distribuable contient un service qui est buggé.
Dans le cas de JEE, un distribuable est sous forme de WAR et EAR, et ceci pose les problèmes suivants :
Dans le cas de OSGi, un distribuable est sous forme de un ou plusieurs JAR par Bundle OSGi :
Un Bundle OSGi est identifié par son ID (Bundle-SymbolicName) et sa version (Bundle-Version). Le "patch" à livrer consiste à créer un bundle qui corrige le bug (du service) en incrémentant sa version. Il est ensuite possible de lancer un même Bundle (même ID Bundle-SymbolicName) avec des versions différentes. C'est que je souhaite montrer dans cette section.
Nous allons simuler une erreur dans le service UserServiceImpl du Bundle org.akrogen.gestcv.services de version 1.0.0.qualified et créer un nouveau bundle "patch" org.akrogen.gestcv.services de version 1.0.1.qualified qui corrige le problème. Nous verrons qu'avec notre architecture, note bundle "patch" ne fonctionnera pas, car nous devons scinder le Bundle org.akrogen.gestcv.services en 2 bundles services API et Implémentation.
Vous pouvez télécharger l'ensemble des projets expliqués dans cette section sur org.akrogen.gestcv_step5-patch.zip. Nous allons partir des projets du billet précédant org.akrogen.gestcv_step4-servicetracker.zip.
Ici nous allons créer le bundle "patch" org.akrogen.gestcv.services de version 1.0.1. Pour cela :
Bundle-Version: 1.0.1.qualifierIci nous allons modifier le bundle org.akrogen.gestcv.services de version 1.0.0 pour simuler un bug dans la classe org.akrogen.gestcv.services.impl.UserServiceImpl. Pour cela, modifiez cette dernière comme suit :
public Collection<User> findAllUsers() {
throw new RuntimeException("Error into findAllUsers method.");
}Relancez (via GestCV OSGi ) Equinox et la console OSGi affiche :
osgi> Start Bundle [org.akrogen.gestcv.domain]
Start Bundle [org.akrogen.gestcv.services]
Start Bundle [org.akrogen.gestcv.services]
Start Bundle [org.akrogen.gestcv.simpleosgiclient]
--- Get UserService from OSGi services registry with ServiceTracker ---
User [login=angelo, password=]
User [login=djo, password=]
User [login=keulkeul, password=]
User [login=pascal, password=]Cette trace montre que les 2 bundles org.akrogen.gestcv.services de version différente ont été lancée. Elle montre que le service UserService est consommée, ce qui signifie que c'est le bundle de version 1.0.1 qui a pris la main.
Tappez ss pour afficher la liste des bundles et leur ID :
...
38 ACTIVE org.akrogen.gestcv.services_1.0.1.qualifier
39 ACTIVE org.akrogen.gestcv.services_1.0.0.qualifierNous allons maintenant arrêter le bundle org.akrogen.gestcv.services de version 1.0.1. Pour cela tapez dans la console OSGi stop 38 :
Stop Bundle [org.akrogen.gestcv.services]
osgi> --- Get UserService from OSGi services registry with ServiceTracker ---
Cannot get UserService=> UserService is null!Cette trace montre que le service UserService n'est plus disponible. Le bundle org.akrogen.gestcv.services de version 1.0.1 étant stoppé, il ne fournit plus le service UserService. Cependant le bundle (avec le bug) org.akrogen.gestcv.services de version 1.0.0 est activé et on s'attend à ce que le service soit fournit par ce bundle. Mais ceci ne fonctionne pas? Je pense que le problème vient du fait que l'interface UserService est contenu dans les 2 versions des bundles org.akrogen.gestcv.services, ce qui au passage n'est pas très propre. Pour résoudre le problème, nous allons scinder le bundle org.akrogen.gestcv.services en 2 bundles services API et Implémentation.
Jusqu'a maintenant le bundle org.akrogen.gestcv.services contient :
A ce stade l'API et l'implémentation de services sont stockés dans le même bundle et ce choix de conception est contraignant :
En règle général, il est conseillé de séparer l'API Services et son Implémentation en 2 bundles distincts. Nous allons dans notre cas
Voici un schéma de ce que nous allons effectuer dans cette section :

Ce schéma met en évidence les 2 bundles Services API org.akrogen.gestcv.services et Implémentation.
Vous pouvez télécharger org.akrogen.gestcv_step5-api-services-bundle.zip qui contient le code expliqué ci-dessous. Nous allons partir des projets du billet précédant org.akrogen.gestcv_step4-servicetracker.zip.
org.akrogen.gestcv.services.impl .
Ici nous allons créer le bundle org.akrogen.gestcv.services.impl, bundle d'implémentation de services. Pour cela :
Bundle-SymbolicName: org.akrogen.gestcv.services.implExport-Package: org.akrogen.gestcv.servicesRequire-Bundle: org.akrogen.gestcv.domain;bundle-version="1.0.0",
org.akrogen.gestcv.services;bundle-version="1.0.0"Ici nous allons modifier le bundle org.akrogen.gestcv.services, bundle d'API de services. Pour cela :
Supprimer l'enregistrement du service dans l'Activator ce qui donne :
package org.akrogen.gestcv.services.internal;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Start Bundle ["
+ context.getBundle().getSymbolicName() + "]");
}
public void stop(BundleContext context) throws Exception {
System.out.println("Stop Bundle ["
+ context.getBundle().getSymbolicName() + "]");
}
}Relancez (via GestCV OSGi ) Equinox et la console OSGi affiche :
osgi> Start Bundle [org.akrogen.gestcv.domain]
Start Bundle [org.akrogen.gestcv.services]
Start Bundle [org.akrogen.gestcv.services.impl]
Start Bundle [org.akrogen.gestcv.simpleosgiclient]
--- Get UserService from OSGi services registry with ServiceTracker ---
User [login=angelo, password=]
User [login=djo, password=]
User [login=keulkeul, password=]
User [login=pascal, password=]Cette trace montre que les 4 bundles sont lances dont les bundles API et Implémentation services. La consommation du service UserService s'effectue ensuite correctement par le bundle client.
Maintenant que nous avons 2 bundles services API et Implémentation, nous allons recommencer notre test avec nos bundles services buggués et patchés en repartant des projets org.akrogen.gestcv_step5-api-services-bundle.zip. Vous pouvez télécharger org.akrogen.gestcv_step5-api-services-bundle-patch.zip qui contient le code expliqué ci-dessous.
Bundle-Version: 1.0.1.qualifierModifiez la classe UserServiceImpl comme ceci :
public Collection<User> findAllUsers() {
throw new RuntimeException("Error into findAllUsers method.");
}Relancez (via GestCV OSGi ) Equinox et la console OSGi affiche une exception toutes les 5 sec en appelant UserService :
--- Get UserService from OSGi services registry with ServiceTracker---
java.lang.RuntimeException: Error into findAllUsers method.
at org.akrogen.gestcv.services.impl.UserServiceImpl.findAllUsers(UserServiceImpl.java:22)
at org.akrogen.gestcv.simpleosgiclient.internal.FindAllUsersThread.displayUsers(FindAllUsersThread.java:74)
at org.akrogen.gestcv.simpleosgiclient.internal.FindAllUsersThread.run(FindAllUsersThread.java:40)Ceci permet d'affirmer que le bundle (qui est buggé) de version 1.0.0.qualifier est utilisé.
Tappez ss :
...
39 ACTIVE org.akrogen.gestcv.services.impl_1.0.0.qualifier
40 ACTIVE org.akrogen.gestcv.services.impl_1.0.1.qualifier
...Ceci montre que les 2 bundles services sont lancés en même temps et qu'il est possible de faire cohabiter plusieurs versions de bundles. Le bundle de version 1.0.0.qualifier est utilisé car il est lancé avant celui de version 1.0.1.qualifier. L'ordre de lancement des bundles est important. Le conteneur OSGi n'utilise pas l'information "version" pour savoir quel bundle doit être utilisé en priorité.
Arrêter le bundle de version 1.0.0.qualifier avec la commande (dans mon cas) stop 39. La console OSGi affiche :
--- Get UserService from OSGi services registry with ServiceTracker ---
User [login=angelo, password=]
User [login=djo, password=]
User [login=keulkeul, password=]
User [login=pascal, password=]Cette trace permet d'affirmer que le bundle services patch (version 1.0.1) est maintenant utilisé. Ce scénario permet de montrer comment il est facile de fournir un livrable unitaire (bundle) et de l'installer sans perturber les utilisateurs connectés à l'application. L'arrêt/stop de bundles est extrêmement intéresant :
Il existe plusieurs manières de gérer les dépendances entre les bundles OSGi dont :
OSGi préconnise d'utiliser Import Package pour ne pas lier fortement les bundles entre eux. Ce type de dépendance permet ensuite de scinder un bundle A en plusieurs bundles (A1, A2, etc) sans que les autres bundles qui étaient lié à A soient impactés. Il existe cependant 2 inconvéniants avec Import Package par rapport à Require Bundle :
Pour éviter les 2 problèmes avec Import Package, les Plugin Eclipse utilisent Require Bundle car il n'y a aucune maîtrise des plugins qui sont lancés (on peut ajouter ses propres plugins avec n'importe quel package). Nous avons utilisé jusqu'à maintenant le type de dépendance Require Bundle que nous allons supprimer pour utiliser Import Package (nous maitrisons le choix des bundles à lancer). Vous pouvez télécharger org.akrogen.gestcv_step5-import-package.zip qui contient le code expliqué ci-dessous :
Import-Package: org.akrogen.gestcv.domain,
org.osgi.framework;version="1.3.0"Import-Package: org.akrogen.gestcv.domain,
org.akrogen.gestcv.services,
org.osgi.framework;version="1.3.0"Import-Package: org.akrogen.gestcv.domain,
org.akrogen.gestcv.services,
org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.4.2"Dans ce billet nous avons mis en évidence et montrer l'interêt d'utiliser le registre de services OSGi (pour arrêter/stopper les bundles). Dans le prochain billet nous montrerons l'interêt d'utiliser Spring et plus particulièrement Spring DM pour pouvoir déclarer les services que l'on souhaite fournir/consommer via le registre de services OSGi.
Cet article n'a pas de Commentaires/Pingbacks pour le moment...
Vous devez être identifié pour poster un commentaire.
| Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 |
Copyright © 2000-2012 - www.developpez.com