What's cool in the new and updated OSGi Specs Carsten Ziegeler David Bosschaert 1 of 53
Speakers Carsten Ziegeler (cziegeler@apache.org) ⦿ RnD Adobe Research Switzerland ⦿ OSGi Board, CPEG and EEG Member ⦿ ASF member David Bosschaert (davidb@apache.org) ⦿ RnD Adobe Research Dublin ⦿ Co-chair OSGi EEG ⦿ Open-source and cloud enthusiast 2 of 53
Agenda ⦿ Framework updates ⦿ Repository update ⦿ Asynchronous Services & Promises ⦿ Declarative Services ⦿ Http Service ⦿ Cloud ⦿ Semantic Versioning Annotations ⦿ Other spec updates 3 of 53
OSGi Core R6 Release ⦿ Service Scopes ⦿ Package and Type Annotations ⦿ Data Transfer Objects ⦿ Native Namespace ⦿ WeavingHook Enhancements ⦿ System Bundle Framework Hooks ⦿ Extension Bundle Activators ⦿ Framework Wiring 4 of 53
Framework Updates Service Scopes (RFC 195) OSGi R5 supports two service scopes: ⦿ Singleton ⦿ Bundle (ServiceFactory) Transparent to the client S getService(S Se er rv vi ic ce eR Re ef fe er re en nc ce e<S> r re ef f) v vo oi id d ungetService(S Se er rv vi ic ce eR Re ef fe er re en nc ce e<S> r re ef f) 5 of 53
Framework Updates Service Scopes (RFC 195) ⦿ Third Scope: prototype ⦿ Driver: Support for EEG specs (EJB, CDI) ⦿ Usage in other spec updates Clients need to use new API / mechanisms 6 of 53
Framework Updates Service Scopes (RFC 195) New BundleContext Methods API S getServiceObjects(S Se er rv vi ic ce eR Re ef fe er re en nc ce e<S> r re ef f).getService() v vo oi id d getServiceObjects(S Se er rv vi ic ce eR Re ef fe er re en nc ce e<S> r re ef f).ungetService(S) Transparent to the client 7 of 53
Framework Updates Service Scopes (RFC 195) ⦿ New PrototypeServiceFactory interface ⦿ Managed service registration properties for inspection ⦿ Support in component frameworks (DS, Blueprint) 8 of 53
Data Transfer Objects 9 of 53
RFC 185 – Data Transfer Objects ⦿ Defines a DTO model for OSGi ⦿ Serializable/Deserializable objects ⦿ Use cases: REST, JMX, Web Console... ⦿ To be adopted by other specs 10 of 53
RFC 185 – Data Transfer Objects Getting DTOs: adapter pattern p pu ub bl li ic c c cl la as ss s B Bu un nd dl le eD DT TO O e ex xt te en nd ds s org.osgi.dto.DTO { p pu ub bl li ic c l lo on ng g id; p pu ub bl li ic c l lo on ng g lastModified; p pu ub bl li ic c i in nt t state; p pu ub bl li ic c S St tr ri in ng g symbolicName; p pu ub bl li ic c S St tr ri in ng g version; } 11 of 53
RFC 185 – Data Transfer Objects DTOs for the OSGi framework ⦿ FrameworkDTO ⦿ BundleDTO ⦿ ServiceReferenceDTO ⦿ BundleStartLevelDTO, FrameworkStartLevelDT ⦿ CapabilityDTO, RequirementDTO, ResourceDTO ⦿ BundleWiringsDTO, etc 12 of 53
Repository 1.1 13 of 53
OSGi Repository today 14 of 53
Example Repository namespaces 15 of 53
RFC 187 - Repository 1.1 Existing repository powerful but: limited to queries in a single namespace New in RFC 187: Combine requirements spanning multiple namespaces: R Re ep po os si it to or ry y repo = ... // Obtain from Service Registry C Co ol ll le ec ct ti io on n<R Re es so ou ur rc ce e> res = repo.findProviders( repo.getExpressionCombiner().a an nd d( repo.newRequirementBuilder("osgi.wiring.package"). addDirective("filter","(osgi.wiring.package=foo.pkg1)"). buildExpression(), repo.newRequirementBuilder("osgi.identity"). addDirective("filter", "(license=http://opensource.org/licenses/Apache-2.0)"). buildExpression())); 16 of 53
Asynchronous Services & Promises 17 of 53
Async Services ● Asynchronously invoke services existing service new ones, written for async access ● Client invokes the service via a mediator ● Invocation returns quickly result can be obtained later 18 of 53
Async Services - example A typical service: p pu ub bl li ic c i in nt te er rf fa ac ce e C Ca al lc cS Se er rv vi ic ce e { B Bi ig gI In nt te eg ge er r factorial(i in nt t num); } Invoke it asynchronously: C Ca al lc cS Se er rv vi ic ce e mySvc = ... // from service registry A As sy yn nc c asyncService = ... // from service registry C Ca al lc cS Se er rv vi ic ce e myMediator = asyncService.mediate(mySvc); f fi in na al l P Pr ro om mi is se e<B Bi ig gI In nt te eg ge er r> p = asyncService.call( myMediator.factorial(1000000)); // ... factorial invoked asynchronously ... // callback to handle the result when it arrives p.onResolve(n ne ew w R Ru un nn na ab bl le e() { p pu ub bl li ic c v vo oi id d run() { S Sy ys st te em m.o ou ut t.println("Found the answer: " + p.getValue()); } }); 19 of 53
OSGi Promises ● Inspired by JavaScript Promises Make latency and errors explicit ● Provide async chaining mechanism Based on callbacks ● Promises are Monads ● Works with many (older) Java versions ● Designed to work with Java 8 CompletableFuture and Lambdas ● Used with Async Services Also useful elsewhere 20 of 53
OSGi Promises - example S Su uc cc ce es ss s<S St tr ri in ng g,S St tr ri in ng g> transformResult = n ne ew w S Su uc cc ce es ss s<>() { p pu ub bl li ic c P Pr ro om mi is se e<S St tr ri in ng g> call(P Pr ro om mi is se e<S St tr ri in ng g> p) { r re et tu ur rn n P Pr ro om mi is se es s.resolved(toHTML(p.getValue())); } }; P Pr ro om mi is se e<S St tr ri in ng g> p = asyncRemoteMethod(); p.t th he en n(validateResult) .t th he en n(transformResult) .t th he en n(showResult, showError); 21 of 53
Declarative Services 22 of 53
RFC 190 - Declarative Services Enhancements ⦿ Support of prototype scope ⦿ Introspection API ⦿ DTOs ⦿ But most importantly... 23 of 53
Simplify Component Dvlpmnt @Component(p pr ro op pe er rt ty y={ M My yC Co om mp po on ne en nt t.PROP_ENABLED + ":Boolean=" + M My yC Co om mp po on ne en nt t.DEFAULT_ENABLED M My yC Co om mp po on ne en nt t.PROP_TOPIC + "=" + M My yC Co om mp po on ne en nt t.DEFAULT_TOPIC_1, M My yC Co om mp po on ne en nt t.PROP_TOPIC + "=" + M My yC Co om mp po on ne en nt t.DEFAULT_TOPIC_2, "service.ranking:Integer=15" }) p pu ub bl li ic c c cl la as ss s M My yC Co om mp po on ne en nt t { s st ta at ti ic c f fi in na al l S St tr ri in ng g PROP_ENABLED = "enabled"; s st ta at ti ic c f fi in na al l S St tr ri in ng g PROP_TOPIC = "topic"; s st ta at ti ic c f fi in na al l S St tr ri in ng g PROP_USERNAME = "userName"; s st ta at ti ic c f fi in na al l b bo oo ol le ea an n DEFAULT_ENABLED = t tr ru ue e; s st ta at ti ic c f fi in na al l S St tr ri in ng g DEFAULT_TOPIC_1 = "topicA"; s st ta at ti ic c f fi in na al l S St tr ri in ng g DEFAULT_TOPIC_2 = "topicB"; 24 of 53
Simplify Component Dvlpmnt @Activate p pr ro ot te ec ct te ed d v vo oi id d activate(f fi in na al l M Ma ap p config) { f fi in na al l b bo oo ol le ea an n enabled = P Pr ro op pe er rt ti ie es sU Ut ti il l.toBoolean(config.g ge et t(PROP_ENABLED), DEFAULT_ENABLED); i if f ( enabled ) { t th hi is s.userName = P Pr ro op pe er rt ti ie es sU Ut ti il l.toString(config.g ge et t(PROP_USERNAME), n nu ul ll l t th hi is s.topics = P Pr ro op pe er rt ti ie es sU Ut ti il l.toStringArray(config.g ge et t(PROP_TOPIC), n ne ew w S St tr ri in ng g[] {DEFAULT_TOPIC_1, DEFAULT_TOPIC_2}); } } 25 of 53
Use annotations for configuration... @interface M My yC Co on nf fi ig g { b bo oo ol le ea an n enabled() d de ef fa au ul lt t t tr ru ue e; S St tr ri in ng g[] topic() d de ef fa au ul lt t {"topicA", "topicB"}; S St tr ri in ng g userName(); i in nt t service_ranking() d de ef fa au ul lt t 15; } 26 of 53
...and reference them in lifecycle methods @Component p pu ub bl li ic c c cl la as ss s M My yC Co om mp po on ne en nt t { S St tr ri in ng g userName; S St tr ri in ng g[] topics; @Activate p pr ro ot te ec ct te ed d v vo oi id d activate(f fi in na al l M My yC Co on nf fi ig g config) { // note: annotation MyConfig used as interface i if f ( config.enabled() ) { t th hi is s.userName = config.userName(); t th hi is s.topics = config.topic(); } } } 27 of 53
Recommend
More recommend