peaberry Stuart McCulloch
Today's menu Origin of peaberry OSGi-fying Guice Service providers Service registry abstraction Blending services & extens...
Origin Began as lab project at community site new annotations @Inject @OSGiService("(Currency=GBP)") StockQuote ...
Simplification Auto-binding introduced too much magic @Inject @OSGiService("(Currency=GBP)") StockQuote quote; N...
Squeezing Guice into a bundle Guice now has OSGi metadata thanks to Guice's type-safety meant no major classloading issues...
Bridge class loader Don't want to expose AOP internals (repackaged CGLIB) parent parent com.google.inject.internal.* loadC...
Bridge class loader (2) No dependency on OSGi ! – only used when needed of bridge classloaders allows re-use ... as well a...
Why peaberry? Guice can now be used in OSGi – so what's missing? no support for dynamic OSGi services! each injector uses ...
Service Provider @Inject StockQuote quote; quote.price(“JAVA”); get unget price injector get K P K P K P P Service Registr...
Service binding Fluent API helps you get the right service  Provider<T> bind( iterable( A.class ) ).toProvider( service( A...
Service binding (2) So is that it? s:
Service binding (2) So is that it? ... no, you can also service( A.class ).filter( /* apply a filter */ )... service( A.cl...
Service Registry public   interface  ServiceRegistry { <T> Iterable<Import<T>> lookup(Class<T> clazz, AttributeFilter filt...
Import public   interface  Import<T> { T get();  // may throw unchecked ServiceUnavailableException Map <String, ?> attrib...
Concurrent Import public   synchronized  T get() { count ++; if  ( null  ==  service ) { final  Iterator<Import<T>> i =  s...
Export What's the opposite of a imported service? hint
Export public   interface  Export<T> { void  put(T instance); void  attributes(Map<String, ?> attributes); void  unput(); ...
Service Registry (revisited) public   interface  ServiceRegistry extends  ServiceWatcher<Object> {  // etc... public   int...
Service binding (revisited) Exported service handles can be injected bind( export( A.class ) ).toProvider( service( (A)nul...
Eclipse extensions Eclipse has its own registry for plug-in this is like another service registry, but less dynamic extens...
Mapping extensions Use  @MapName,   @MapContent  from peaberry or Riena Same approach as Riena for mapping bean types But ...
Injecting extensions <extension point=&quot;org.eclipse.ui.views&quot;> <view name=&quot;Message&quot; allowMultiple=&quot...
Blending services and extensions binder.install(osgiModule(context, eclipseRegistry())); peaberry 1.1-rc2 lets you combine...
Summary Guice can now be used in OSGi peaberry adds  dynamic   services to Guice model easy to switch between services and...
Questions?
Upcoming SlideShare
Loading in …5
×

Peaberry - Blending Services And Extensions

3,095 views
2,950 views

Published on

peaberry extends Guice to support injection of dynamic services. It provides OSGi integration out of the box and has plug-in support for other registry-based service frameworks.

This talk introduces peaberry and shows how it can be used to seamlessly blend both OSGi services and Eclipse extensions in the same application, as well as help switch between the two approaches.

Published in: Technology, Business

Peaberry - Blending Services And Extensions

  1. 1. peaberry Stuart McCulloch
  2. 2. Today's menu Origin of peaberry OSGi-fying Guice Service providers Service registry abstraction Blending services & extensions Future ideas
  3. 3. Origin Began as lab project at community site new annotations @Inject @OSGiService(&quot;(Currency=GBP)&quot;) StockQuote quote; patched Guice to support service “auto-binding” @OSGiService(...) StockQuote quote; // magically added for you bind(StockQuote.class)...
  4. 4. Simplification Auto-binding introduced too much magic @Inject @OSGiService(&quot;(Currency=GBP)&quot;) StockQuote quote; NO new annotations service bindings now explicit, just like pure Guice aim to be a true extension to Guice – no patches! so...
  5. 5. Squeezing Guice into a bundle Guice now has OSGi metadata thanks to Guice's type-safety meant no major classloading issues ... but AOP proxies initially didn't work in OSGi AOP proxies need to see client types AOP support types BND internal &
  6. 6. Bridge class loader Don't want to expose AOP internals (repackaged CGLIB) parent parent com.google.inject.internal.* loadClass loadClass so load proxy classes using “bridge” class loaders
  7. 7. Bridge class loader (2) No dependency on OSGi ! – only used when needed of bridge classloaders allows re-use ... as well as eager unloading of proxy classes BUT cannot apply bridging to package-private types as not visible from other classloaders weak cache
  8. 8. Why peaberry? Guice can now be used in OSGi – so what's missing? no support for dynamic OSGi services! each injector uses immutable set of explicit bindings so ... new Injector on every service change? or ... Provider<T> that returns dynamic proxies? :( :)
  9. 9. Service Provider @Inject StockQuote quote; quote.price(“JAVA”); get unget price injector get K P K P K P P Service Registry p r o x y p r o x y
  10. 10. Service binding Fluent API helps you get the right service Provider<T> bind( iterable( A.class ) ).toProvider( service( A.class ).multiple() ); @Inject A bestService; @Inject Iterable<A> allServices; // each element is a proxy import static org.ops4j.peaberry.Peaberry.service; import static org.ops4j.peaberry.util.TypeLiterals.iterable; * bind( A.class ).toProvider( service( A.class ).single() );
  11. 11. Service binding (2) So is that it? s:
  12. 12. Service binding (2) So is that it? ... no, you can also service( A.class ).filter( /* apply a filter */ )... service( A.class ).in( /* query a specific registry */ )... service( A.class ).out( /* watch for service changes */ )... service( A.class ).decoratedWith( /* apply decoration */ )... each stage of the builder creates an immutable copy which means you can share and re-use builders
  13. 13. Service Registry public interface ServiceRegistry { <T> Iterable<Import<T>> lookup(Class<T> clazz, AttributeFilter filter); <T> void watch(Class<T> clazz, AttributeFilter filter, ServiceWatcher<? super T> watcher); } public interface AttributeFilter { boolean matches(Map<String, ?> attributes); } Pluggable API – integrate all kinds of service registries simple, allows lazines s z z z , no dependency on OSGi service filters not just limited to LDAP strings but we do provide an LDAP adapter (among others)
  14. 14. Import public interface Import<T> { T get(); // may throw unchecked ServiceUnavailableException Map <String, ?> attributes(); void unget(); boolean available(); } Tracking service use is very important ! public interface ImportDecorator<S> { <T extends S> Import<T> decorate(Import<T> service); } can easily apply deco to change dynamic behaviour (e.g. sticky services) ation to imported services
  15. 15. Concurrent Import public synchronized T get() { count ++; if ( null == service ) { final Iterator<Import<T>> i = services .iterator(); if (i.hasNext()) { service = i.next(); instance = service .get(); } } return instance ; } public synchronized void unget() { if (0 == -- count && null != service ) { final Import<T> temp = service ; instance = null ; service = null ; temp.unget(); } } Single services wrap iterables to look like single imports avoids thread-locals, provides basic service affinity
  16. 16. Export What's the opposite of a imported service? hint
  17. 17. Export public interface Export<T> { void put(T instance); void attributes(Map<String, ?> attributes); void unput(); } Can alter/remove exported instance, update attributes public interface ServiceWatcher<S> { <T extends S> Export<T> add(Import<T> service); } watchers can receive imports and (re-)export them but wait, isn't a registry a bit like a watcher?
  18. 18. Service Registry (revisited) public interface ServiceRegistry extends ServiceWatcher<Object> { // etc... public interface Export<T> extends Import<T> { // etc... which leads to interesting possibilities ... Yes, and exports are also related to imports // like pushing services from one registry to another for (Import<A> i : extensionRegistry.lookup(A.class, null)) { serviceRegistry.add(i); } but you don't have to use the raw API to export
  19. 19. Service binding (revisited) Exported service handles can be injected bind( export( A.class ) ).toProvider( service( (A)null ).export() ); @Inject Export<A> exportedService; import static org.ops4j.peaberry.Peaberry.service; import static org.ops4j.peaberry.util.TypeLiterals.export; * bind( export( A.class ) ).toProvider( service( aImpl ).export() ); otherwise published when export handle is created can defer publishing a service by passing in null
  20. 20. Eclipse extensions Eclipse has its own registry for plug-in this is like another service registry, but less dynamic extensions so ... how can we map the service class to an instance? take inspiration from Eclipse Riena, use bean mapping ! unless its a compatible executable extension OR we're looking up IconfigurationElement class
  21. 21. Mapping extensions Use @MapName, @MapContent from peaberry or Riena Same approach as Riena for mapping bean types But use @ExtensionBean to configure point id @ExtensionBean(&quot;examples.menu.items&quot;) public interface Item { String getLabel(); @MapName(&quot;label&quot;) String toString(); @MapContent String getContent(); }
  22. 22. Injecting extensions <extension point=&quot;org.eclipse.ui.views&quot;> <view name=&quot;Message&quot; allowMultiple=&quot;true&quot; icon=&quot;icons/sample2.gif&quot; class=&quot;example.ViewImpl&quot; id=&quot;example.view&quot; /> </extension> <extension point=&quot;org.eclipse.ui.views&quot;> <view name=&quot;Message&quot; allowMultiple=&quot;true&quot; icon=&quot;icons/sample2.gif&quot; class=&quot; org.ops4j.peaberry.eclipse.GuiceExtensionFactory : example.ViewImpl&quot; id=&quot;example.view&quot; /> </extension> <extension point=&quot;org.ops4j.peaberry.eclipse.modules&quot;> <module class=&quot;example.ViewModule&quot; /> </extension> GuiceExtensionFactory, similar approach as Spring becomes
  23. 23. Blending services and extensions binder.install(osgiModule(context, eclipseRegistry())); peaberry 1.1-rc2 lets you combine registries Clients can continue to use the same injection points @Inject StockQuote quote; YOU can choose where the service comes from or even whether to use a dynamic service at all ! service proxies will then query both OSGi and
  24. 24. Summary Guice can now be used in OSGi peaberry adds dynamic services to Guice model easy to switch between services and non-services can mix'n'match coming soon: lifecycles, configuration support ... like OSGi services and Eclipse extensions different service registries
  25. 25. Questions?

×