Presentation is loading. Please wait.

Presentation is loading. Please wait.

Peaberry Stuart McCulloch.

Similar presentations


Presentation on theme: "Peaberry Stuart McCulloch."— Presentation transcript:

1 peaberry Stuart McCulloch

2 Today's menu Origin of peaberry OSGi-fying Guice Service providers Service registry abstraction Blending services & extensions Future ideas

3 patched Guice to support service “auto-binding”
Origin Began as lab project at community site @Inject @OSGiService("(Currency=GBP)") StockQuote quote; new annotations patched Guice to support service “auto-binding” @OSGiService(...) StockQuote quote; // magically added for you bind(StockQuote.class)...

4 Auto-binding introduced too much magic so...
Simplification Auto-binding introduced too much magic so... @Inject @OSGiService("(Currency=GBP)") StockQuote quote; NO new annotations service bindings now explicit, just like pure Guice aim to be a true extension to Guice – no patches!

5 & Squeezing Guice into a bundle Guice now has OSGi metadata thanks to
BND 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 & internal AOP support types

6 com.google.inject.internal.*
Bridge class loader Don't want to expose AOP internals (repackaged CGLIB) A class loader B class loader com.google.inject.internal.* parent parent Guice class loader bridge A bridge B loadClass loadClass proxy proxy proxy proxy proxy so load proxy classes using “bridge” class loaders

7 Bridge class loader (2) No dependency on OSGi ! – only used when needed weak cache 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

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 Service Provider @Inject StockQuote quote; quote.price(“JAVA”); p r o
x y get @Inject StockQuote quote; K P P K P injector K P p r o x y Service Registry get price quote.price(“JAVA”); RealQuote unget

10 Fluent API helps you get the right service Provider<T>
Service binding Fluent API helps you get the right service Provider<T> @Inject A bestService; bind(A.class).toProvider(service(A.class).single()); @Inject Iterable<A> allServices; // each element is a proxy bind(iterable(A.class)).toProvider(service(A.class).multiple()); * import static org.ops4j.peaberry.Peaberry.service; import static org.ops4j.peaberry.util.TypeLiterals.iterable;

11 Service binding (2) So is that it? s:

12 So is that it? ... no, you can also
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 Pluggable API – integrate all kinds of service registries
Service Registry Pluggable API – integrate all kinds of service registries 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); } simple, allows lazinesszzz, no dependency on OSGi service filters not just limited to LDAP strings public interface AttributeFilter { boolean matches(Map<String, ?> attributes); } but we do provide an LDAP adapter (among others)

14 Tracking service use is very important !
public interface Import<T> { T get(); // may throw unchecked ServiceUnavailableException Map<String, ?> attributes(); void unget(); boolean available(); } can easily apply deco ation to imported services public interface ImportDecorator<S> { <T extends S> Import<T> decorate(Import<T> service); } to change dynamic behaviour (e.g. sticky services)

15 Single services wrap iterables to look like single imports
Concurrent Import Single services wrap iterables to look like single imports 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(); avoids thread-locals, provides basic service affinity

16 Export What's the opposite of a imported service? hint

17 Can alter/remove exported instance, update attributes
public interface Export<T> { void put(T instance); void attributes(Map<String, ?> attributes); void unput(); } watchers can receive imports and (re-)export them public interface ServiceWatcher<S> { <T extends S> Export<T> add(Import<T> service); } but wait, isn't a registry a bit like a watcher?

18 Service Registry (revisited)
Yes, and exports are also related to imports public interface ServiceRegistry extends ServiceWatcher<Object> { // etc... public interface Export<T> extends Import<T> { // etc... which leads to interesting possibilities ... // 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 Service binding (revisited)
Exported service handles can be injected @Inject Export<A> exportedService; bind(export(A.class)).toProvider(service(aImpl).export()); can defer publishing a service by passing in null bind(export(A.class)).toProvider(service((A)null).export()); otherwise published when export handle is created * import static org.ops4j.peaberry.Peaberry.service; import static org.ops4j.peaberry.util.TypeLiterals.export;

20 Eclipse extensions Eclipse has its own registry for plug-in extensions this is like another service registry, but less dynamic 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 Same approach as Riena for mapping bean types
Mapping extensions Same approach as Riena for mapping bean types But to configure point id @ExtensionBean("examples.menu.items") public interface Item { String getLabel(); @MapName("label") String toString(); @MapContent String getContent(); } Use from peaberry or Riena

22 GuiceExtensionFactory, similar approach as Spring
Injecting extensions GuiceExtensionFactory, similar approach as Spring <extension point="org.eclipse.ui.views"> <view name="Message" allowMultiple="true" icon="icons/sample2.gif" class="example.ViewImpl" id="example.view" /> </extension> becomes <extension point="org.eclipse.ui.views"> <view name="Message" allowMultiple="true" icon="icons/sample2.gif" class="org.ops4j.peaberry.eclipse.GuiceExtensionFactory:example.ViewImpl" id="example.view" /> </extension> <extension point="org.ops4j.peaberry.eclipse.modules"> <module class="example.ViewModule" />

23 Blending services and extensions
peaberry 1.1-rc2 lets you combine registries binder.install(osgiModule(context, eclipseRegistry())); service proxies will then query both OSGi and 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 !

24 coming soon: lifecycles, configuration support
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 different service registries ... like OSGi services and Eclipse extensions coming soon: lifecycles, configuration support

25 Questions?


Download ppt "Peaberry Stuart McCulloch."

Similar presentations


Ads by Google