ougf - nouveautés osgi core 4.3
TRANSCRIPT
Zenika © 2011 1
Nouveautés OSGi Core 4.3
OSGi Users’ Group France Jeudi 24 novembre 2011
François Fornaciari - [email protected]
Zenika © 2011 2
Historique
OSGi Specifications
Core (v4.3): plateforme minimale
Compendium (v4.2) : services additionnels
Enterprise (v4.2) : services orientés « entreprise »
OSGi Core 4.3 : mars 2011
Implémentations open-source
Eclipse Equinox 3.7 (Indigo) Première livraison stable mars 2011
C’est la RI !
Apache Felix 4 Première livraison stable fin septembre 2011
Zenika © 2011 3
<Generics> Introduction
Meilleure lisibilité du code
Meilleur typage des objets
Compatibilité avec le JRE 1.4
Utilisation de l’option de compilation -target jsr14
N’est pas une solution au code contenant des annotations dont la RetentionPolicy est à RUNTIME
Configuration Maven <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>jsr14</target> </configuration> </plugin>
Zenika © 2011 4
<Generics> Enregistrement de service
Avant OSGi 4.3
OSGi 4.3
Comptabilité
PrintService service = new PrintServiceImpl(); Properties props = new Properties(); props.put("color", "true"); bundleContext.registerService(PrintService.class.getName(), service, props);
bundleContext.registerService(PrintService.class, service, props);
Zenika © 2011 5
<Generics> Recherche de service
Avant OSGi 4.3
OSGi 4.3
Comptabilité
ServiceReference reference = bundleContext.getServiceReference(PrintService.class.getName()); PrintService service = (PrintService) bundleContext.getService(reference);
ServiceReference<PrintService> reference = bundleContext.getServiceReference(PrintService.class); PrintService service = bundleContext.getService(reference);
Zenika © 2011 6
<Generics> ServiceTracker (1/2)
Avant OSGi 4.3
ServiceTracker serviceTracker = new ServiceTracker(bundleContext, PrintService.class.getName(), null) { public Object addingService(ServiceReference ref) { // Méthode appelée lors de l'ajout au tracker d'un service satisfaisant le filtre // Avantage : appelée à l'ouverture du tracker pour chaque service déjà enregistré // Retourne un objet associé au service tracké (généralement le service détecté)
return super.addingService(reference); } public void modifiedService(ServiceReference ref, Object service) { // Méthode appelée lors de la modification des propriétés d'un service tracké
} public void removedService(ServiceReference ref, Object service) { // Méthode appelée lors du retrait d'un service tracké // Avantage : appelée à la fermeture du tracker pour chaque service tracké
} }; serviceTracker.open(); PrintService service = (PrintService) serviceTracker.getService();
Zenika © 2011 7
<Generics> ServiceTracker (2/2)
OSGi 4.3
ServiceTracker<PrintService, PrintService> serviceTracker = new ServiceTracker<PrintService, PrintService>(bundleContext, PrintService.class, null) { public PrintService addingService(ServiceReference<PrintService> ref) { return super.addingService(reference); } public void modifiedService(ServiceReference<PrintService> ref, PrintService s) { } public void removedService(ServiceReference<PrintService> reference, PrintService s) { } }; serviceTracker.open(); PrintService service = serviceTracker.getService();
Zenika © 2011 8
<Generics> ServiceFactory
Création d'un nouveau service à chaque lookup
Le service créé est associé au bundle consommateur
Un bundle récupérant deux fois le service reçoit la même instance
public class PrintServiceFactory implements ServiceFactory<PrintService> { public PrintService getService(Bundle b, ServiceRegistration<PrintService> sr) { return new PrintServiceImpl(); } public void ungetService(Bundle b, ServiceRegistration sr, PrintService ps) { } } [...] // Enregistrement du service bundleContext.registerService(PrintService.class, new PrintServiceFactory() , null); [...] // Client PrintService service = bundleContext.getService((bundleContext.getServiceReference(PrintService.class)));
Zenika © 2011 9
<Generics> BundleTracker (1/2)
Avant OSGi 4.3
BundleTracker bundleTracker = new BundleTracker(bundleContext, Bundle.ACTIVE, null) { public Object addingBundle(Bundle bundle, BundleEvent event) { // Méthode appelée lors de l'ajout au tracker d'un bundle satisfaisant l'état spécifié // Avantage : appelée à l'ouverture du tracker pour chaque bundle déjà installé // Retourne un objet associé au bundle tracké
[...] return object; } public void removedBundle(Bundle bundle, BundleEvent event, Object o) { // Méthode appelée lors du retrait d'un des bundles trackés // Possibilité d'effectuer des traitements sur l'objet associé au bundle // Avantage : appelée à la fermeture du tracker pour chaque bundle tracké
} }; bundleTracker.open();
Zenika © 2011 10
<Generics> BundleTracker (2/2)
OSGi 4.3
BundleTracker<String> bundleTracker = new BundleTracker<String> (bundleContext, Bundle.ACTIVE, null) { public String addingBundle(Bundle bundle, BundleEvent event) { // Méthode appelée lors de l'ajout au tracker d'un bundle satisfaisant l'état spécifié // Avantage : appelée à l'ouverture du tracker pour chaque bundle déjà installé // Retourne un objet associé au bundle tracké
[...] return "Objet tracké de type String"; } public void removedBundle(Bundle bundle, BundleEvent event, String o) { // Méthode appelée lors du retrait d'un des bundles trackés // Possibilité d'effectuer des traitements sur l'objet associé au bundle // Avantage : appelée à la fermeture du tracker pour chaque bundle tracké
} }; bundleTracker.open();
Zenika © 2011 11
Capabilities & Requirements Introduction
Jusqu’à présent le framework s’occupait de la résolution des bundles en faisant correspondre des packages importés avec des packages exportés
Depuis OSGi 4.3, généralisation des concepts de dépendances
Un bundle peut offrir un Capability personnalisable
Un bundle peut exprimer une dépendance vers au travers d’un Requirement
Prise en compte lors de la résolution d’un bundle
Permet de définir des dépendances qui ne sont pas des dépendances de code
Ex : nombre minimal de cœurs CPU
Zenika © 2011 12
Capabilities & Requirements Définition (1/2)
Capability
Un set d’attributs (couple clé/valeur) associé à un namespace
Requirement
Un filtre sur des attributs appartenant à un namespace
Namespace réservés
osgi.wiring.package Import-Package, DynamicImport-Package et Export-Package
osgi.wiring.bundle Require-Bundle, Bundle-SymbolicName et Bundle-Version
osgi.wiring.host Fragment-Host, Bundle-SymbolicName et Bundle-Version
Zenika © 2011 13
Capabilities & Requirements Définition (2/2)
Déclaration de le fichier MANIFEST
Capability
Requirement (filtre LDAP)
Déclaration de l’environnement d’exécution requis
Avant OSGi 4.3 (déprécié)
OSGi 4.3
Provide-Capability: com.zenika.formation; year:Long=2011; effective:=resolve
Require-Capability: com.zenika.formation; filter:="(year=2011)"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Capability: osgi.ee;filter:="(&(osgi.ee="JavaSE")(version>=1.6))"
Zenika © 2011 14
Core Services
Package Admin Service
Start Level Service
Conditionnal Permission Service
Bundle Wiring API
Start Level API
Service Hook Service
Resolver Hook Service
Weaving Hook Service
URL Handler Services
Remote Services
Zenika © 2011 15
Package Admin Service Rappel
Service permettant d'analyser et d'agir sur les dépendances
Zenika © 2011 16
Start Level Service Rappel
Service permettant de gérer la séquence d'activation des bundles
Zenika © 2011 17
Deprecated services
« Package Admin Service » et « Start Level Service » sont dépréciés
Utilisés par les outils d’administration de plateformes OSGi
Shells OSGi
Console de management web de Felix
Servers d’applications
Etc.
Zenika © 2011 18
Nouveaux services OSGi 4.3
Remplacement de « Package Admin Service » par « Bundle Wiring API » et de « Start Level Service » par « Start Level API »
A l'origine, choix d'une approche orientée service (dynamique) mais ce design n'était pas suffisamment orienté objet (passage de l'objet bundle à chaque méthode)
Nouvelle représentation des « Wiring » entre bundles en se basant sur l’introduction des concepts de « Capability » et « Requirement »
Zenika © 2011 19
Bundle Wiring API (1/4)
A chaque résolution de bundle, un objet de type BundleWiring est créé pour une révision donnée
A noter : chaque mise à jour d'un bundle déclenche la création d'une nouvelle révision. Seule une opération de « refresh » permet de forcer la rafraichissement des liaisons entre les bundles
Permet de récupérer les informations de dépendance
Nom symbolique, version, etc.
Packages requis / fournis, fragments, etc.
Représentation des liaisons au « runtime »
Zenika © 2011 20
Bundle Wiring API (2/4)
Zenika © 2011 21
Bundle Wiring API (3/4)
Exemple de récupération des packages importés
Namespaces osgi.wiring.bundle et osgi.wiring.host
BundleWiring bundleWiring = bundleContext.getBundle().adapt(BundleWiring.class); for (BundleWire wire : bundleWiring.getRequiredWires("osgi.wiring.package")) { String packageName = (String) wire.getCapability().getAttributes().get("osgi.wiring.package"); Bundle bundle = wire.getProviderWiring().getBundle(); [...] }
List<BundleCapability> capabilities = bundleWiring.getCapabilities(null); for (BundleCapability bundleCapability : capabilities) { System.out.println(bundleCapability.toString()); } // En sortie de la console osgi.wiring.bundle; osgi.wiring.bundle="zenika-bundle"; bundle-version:Version="1.0.0" osgi.wiring.host; osgi.wiring.host="zenika-bundle"; bundle-version:Version="1.0.0"
Zenika © 2011 22
Bundle Wiring API (4/4)
Collection<String> resources = bundleWiring.listResources("/", "*.properties", BundleWiring.LISTRESOURCES_RECURSE); Collection<URL> resources = bundleWiring.findEntries("/", "*.class", BundleWiring.FINDENTRIES_RECURSE);
Zenika © 2011 23
Start Level API
Manipulation des informations de « StartLevel »
Opérations à partir du « System Bundle »
BundleStartLevel bundleStartLevel = bundleContext.getBundle().adapt(BundleStartLevel.class); int startLevel = bundleStartLevel.getStartLevel();
FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class); int initialBundleStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
Zenika © 2011 24
Service Hook Rappel (1/2)
Spécification permettant d'interagir avec le « service engine » : depuis OSGi 4.2
Connaître les services requis par les bundles
Limiter la visibilité de certains services
Mettre facilement en œuvre des proxies de services
Trois types d'interactions
Event Hook : intercepte les évènements liés au cycle de vie des services (enregistrement / désenregistrement / modification) Filtrer tout ou partie des évènements reçus par les bundles
Find Hook : intercepte la recherche de références de services Manipuler les références de services demandées
Listener Hook : intercepte la création et la suppression de ServiceListener Avoir la connaissance des services potentiellement utilisés par les bundles
Zenika © 2011 25
Service Hook Rappel (2/2)
public interface EventHook { // contexts : contextes vers lesquels les évènements sont propagés // (peuvent être modifiés) void event(ServiceEvent event, java.util.Collection contexts); }
public interface FindHook { // allServices : filtre sur getServiceReferences() // ou getAllServiceReferences() void find(BundleContext context, java.lang.String name, java.lang.String filter, boolean allServices, java.util.Collection references); }
public interface ListenerHook { void added(java.util.Collection listeners); void removed(java.util.Collection listeners); }
Zenika © 2011 26
Nouvelles interceptions (1/2)
Ajout de trois nouveaux mécanismes d'interception depuis la version 4.3
Weaving Hook
Permet d'intercepter le chargement de classe des bundles et de manipuler le bytecode avant chargement
Les nouvelles classes générées peuvent dépendre de nouvelles classes, d'où la possibilité de modifier au runtime l'attribut DynamicImport-Package du fichier MANIFEST
Resolver Hook
Permet d'intercepter le mécanisme de résolution de packages et d'influencer le resolver
Exemple : limiter la visibilité de certains packages
Zenika © 2011 27
Nouvelles interceptions (2/2)
Bundle Hook
Permet d'intercepter les évènements du framework à propos du cycle de vie des bundles (Event Hook)
Permet de limiter la visibilité de certains bundles (Find Hook)
Le trio «Service Hook », « Resolver Hook » et « Bundle Hook » offre un mécanisme efficace pour introspecter le framework et agir sur son comportement
Cas d'utilisation : isoler plusieurs applications s'exécutant sur le même framework
Alternative aux mécanismes de sécurité offerts par la plateforme
Zenika © 2011 28
Resolver Hook Service Mise en œuvre
Enregistrement d'un service de type ResolverHookFactory
A chaque tentative de résolution d'un bundle par le framework, création d'une instance de ResolverHook
Possibilité de filtrer la résolution d'un bundle ou la résolution de packages spécifiques
Zenika © 2011 29
Bundle Hook Service Mise en œuvre
Event Hook : intercepte les évènements liés au cycle de vie des bundles (install / start / update / …) avant de les émettre aux différents listeners
Filtrer les évènements reçus par les bundles
Find Hook : intercepte les appels aux méthodes de récupération des bundles présents sur la plateforme
Manipuler la liste de bundles retournées
Zenika © 2011 30
Virgo regions
Eclipse Virgo 3.0 s’appuie sur les mécanismes d’interception pour créer des régions isolées
Précédemment implémentées par les « nested framework » qui ont été abandonnés
Plan de contribution des régions dans Equinox
Zenika © 2011 31
Ressources
Spécifications OSGi http://www.osgi.org
OSGi Wiki http://en.wikipedia.org/wiki/OSGi
Billets de blog http://jaxenter.com/what-s-new-in-core-4-3-36450.html http://www.infoq.com/news/2011/03/osgi-43
Zenika © 2011 32