My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
UserGuide  
Guide for using the peaberry bundle with OSGi.
Featured, Phase-Deploy
Updated Aug 8, 2009 by mccu...@gmail.com

Eclipse/PDE Example - Text Scrambling Service

  1. download and unzip the example
  2. import the contents into Eclipse as existing projects
  3. open peaberry.target and set it as the target platform:
  4. right-click on peaberry.launch and select Run As... -> peaberry:
  5. you should see both bundles start and produce scrambled output:
  6. try stopping and starting the service bundle using the console

Useful Console Commands

ss       -  list all bundles
stop n   -  stop bundle #n
start n  -  start bundle #n
diag n   -  diagnose bundle

Installing the OSGi binding module

 // provides bindings for the current bundle context + OSGi service registry
 Injector injector = Guice.createInjector(osgiModule(bundleContext), ...);

Fluent API Examples

The following static imports were used to simplify the examples

import static org.ops4j.peaberry.Peaberry.osgiModule;
import static org.ops4j.peaberry.Peaberry.service;

import static org.ops4j.peaberry.util.TypeLiterals.export;
import static org.ops4j.peaberry.util.TypeLiterals.iterable;

import static org.ops4j.peaberry.util.Attributes.names;
import static org.ops4j.peaberry.util.Filters.ldap;

Injecting a stock quote service:

 @Inject
 StockQuote quote;
 ...
 bind(StockQuote.class).toProvider(service(StockQuote.class).single());

Injecting many stock quote services:

 @Inject
 Iterable<StockQuote> quotes;
 ...
 bind(iterable(StockQuote.class)).toProvider(service(StockQuote.class).multiple());

Exporting an implementation as a stock quote service:

 @Inject
 // the service can be controlled by the Export handle
 Export<StockQuote> exportedQuote;
 ...
 // the service is exported at injection time
 bind(export(StockQuote.class)).toProvider(service(myQuoteImpl).export());

Applying a custom filter to find a specific service:

 service(StockQuote.class).filter(ldap("(Currency=GBP)")).single()

Applying custom attributes to an exported service:

 service(myQuoteImpl).attributes(names("Currency=GBP")).export()

(the ldap and names utility methods are from org.ops4j.peaberry.util)

You can also decorate services with additional behaviour:

 service(StockQuote.class).decoratedWith(someDecoratorImpl).single()

or ask for them to be injected directly, instead of using a dynamic proxy:

 service(StockQuote.class).single().direct()

similarly, if you don't want to bother with an Export handle when exporting:

 service(myQuoteImpl).export().direct()

You can use your own registry implementation, instead of the default binding:

 service(StockQuote.class).in(myRegistryImpl).single()

And you can now actively watch for changes in the services you inject:

 bind(StockQuote.class).toProvider(service(StockQuote.class).out(new AbstractWatcher<StockQuote>() {

  @Override
  protected StockQuote adding(Import<StockQuote> service) {
   // the returned object is used in the modified and removed calls
   StockQuote instance = service.get();
   System.out.println("ADDING:" + instance);
   return instance;
  }

  @Override
  protected void modified(StockQuote instance, Map<String, ?> attributes) {
   System.out.println("MODIFIED:" + instance);
  }

  @Override
  protected void removed(StockQuote instance) {
   System.out.println("REMOVED:" + instance);
  }
 }).multiple());

AbstractWatcher is a utility class to make implementing ServiceWatcher a bit easier.

Comment by akolleg...@gmail.com, Jan 17, 2009
Are the examples in the user guide up-to-date? It seems to me that the to() calls should be toProvider()
Comment by project member mccu...@gmail.com, Jan 20, 2009

Thanks for spotting that Andreas, glad someone reads these pages!

Comment by plall...@gmail.com, Jan 29, 2009

You mean there's something else to read (other than code/examples)? ;)

Now, really... am I missing something?

Comment by akolleg...@gmail.com, Jan 29, 2009

It all looks to be corrected, so you're not missing anything for now. Unless you mean some non-code for your reading list, for which I'd recommend the upcoming "Pride and Prejudice and Zombies."

Comment by project member mccu...@gmail.com, Jan 30, 2009

Yep, the code + wiki is all you get at the moment ;) of course if there's anything missing (apart from period dramas involving zombies!) feel free to raise an issue or email the group...

Comment by masson.a...@gmail.com, May 29, 2009

Hi, I'm having some problems using Peaberry to inject services between several eclipse plugins. Briefly, I have 4 plugins: one for an editor, one for service interfaces and two for service implementations. I'd like to inject a chosen implementation to my editor using peaberry. Is there a place where I can expose the problem and ask for help? Thanks.

Comment by project member mccu...@gmail.com, May 29, 2009

We have a group for Guice-on-OSGi related questions: http://groups.google.com/group/guice-osgi guice-osgi@googlegroups.com (there's a link on the main page)

Testcases really help when debugging, otherwise please provide as much info as possible upfront as it means less to-and-fro on the email and hopefully a fast resolution ;)

Comment by markus.w...@gmail.com, Aug 8, 2009

I think it should read "3. open peaberry.target ..."

Comment by project member mccu...@gmail.com, Aug 8, 2009

Fixed, thanks

Comment by eduardo....@gmail.com, Dec 14, 2009

On the last example, its correct to use the multiple() proxy provider whithout the bind(iterable(StockQuote.class)) ? I think the correct code should be:

bind(*iterable(StockQuote.class)*).toProvider(service(StockQuote.class).out( ... ).*multiple()*);

OR

bind(StockQuote.class).toProvider(service(StockQuote.class).out( ... ).*single()*);
Comment by rocketra...@gmail.com, Oct 31, 2011

Having two issues with AbstractWatcher?:

  1. It doesn't seem to work at all, and
  2. If I can get it to work, I want the watcher to have access to injected objects i.e. I'd like to bind my AbstractWatcher? implementation to my Guice context, but the out(...) method takes only a specific instance, not a ".class". This latter case is probably just my unfamiliarity with Guice but clearly I'm missing something. I want to like Guice, but it just seems a lot more complex than what I'm used to with Spring's bean approach.

Here is my simple attempt to get it working:

exporting module:

    bind(RoutesBuilder.class).to(CamelRouteBuilder.class).in(Singleton.class);
    bindService(RoutesBuilder.class).export();

importing module:

    bindService(RoutesBuilder.class).out(new CamelRouteWatcher()).single();

and I have also tried:

    // alternate full syntax
    bind(RoutesBuilder.class).toProvider(service(RoutesBuilder.class).out(routeWatcher).single());

The exporting module exports the service correctly:

karaf@root> services:list 112

Exporting Module (112) provides:
------------------------------------------------------------
bundle.id = 112
objectClass = org.ops4j.peaberry.cache.CachingServiceRegistry
service.id = 231
----
objectClass = org.apache.camel.RoutesBuilder
service.id = 232

but the watcher is not triggered when bundle 112 is stopped or started.

Comment by project member mccu...@gmail.com, Oct 31, 2011

^ please create an issue and attach your testcase - if it's something I can build and run locally then it's likely to get more attention.

Note that peaberry is currently in maintenance mode, most of my effort these days is focused on sisu (currently moving to Eclipse: http://www.eclipse.org/projects/project.php?id=technology.sisu) which takes inspiration from peaberry but attempts to make it easier to use.

Comment by rocketra...@gmail.com, Oct 31, 2011

Hmm, as of today, Sisu seems to have no user community -- the forums are completely empty, it has no releases, and no information on its wiki page. I've found some useful information at http://sisu.sonatype.org/quick-guide.html, but nothing relating to OSGi service exports and imports, which is the whole point of Peaberry. A brief perusal of the source reveals no usage examples of this either. It seems to be oriented more to being a Maven Plexus replacement. So basically, adopting sisu for OSGi services would seem to be even more of an uphill battle than using Peaberry! :)

I guess I'll look forward to the time when one of Peaberry or Sisu gains some traction.

Comment by project member mccu...@gmail.com, Oct 31, 2011

Well as I mentioned earlier I'm still working through the process of moving Sisu to Eclipse (the initial source contribution based on https://github.com/sonatype/sisu has yet to go through the IP process) so I'm not surprised the mailing lists and forum are quiet. Pre-Eclipse, Sisu has had a number of releases: http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.sonatype.sisu%22%20AND%20a%3A%22sisu-inject-bean%22

For the most part working with Sisu is based around JSR330, so we haven't needed much documentation (apart from put @Named on components and use @Inject for dependencies) - but again, the move to Eclipse is a good opportunity to pull together all the internal and external doc.

It's also not just for Maven/Plexus, that's just an adaptor written on top of the JSR330 support - at its core Sisu provides dynamic injection on top of Guice, and has basic OSGi support. So you can take bundles with @Named components and Sisu will scan them and share the full injector graph via the service registry. The missing piece which will come from peaberry is exporting/importing individual components via the registry (so you can use DS components, etc) but even without that you can use Sisu with OSGi.

For example, build the guice-swing example and start it with:

java -jar guice-swing-main/target/main.jar osgi

and see how starting/stopping the tab bundles changes the UI.

Anyway, if you can attach your testcase (in buildable form) to an issue I'll take a look.

Comment by rocketra...@gmail.com, Oct 31, 2011

Thanks for the information on Sisu. I need the service registry interop so Sisu is a no-go for now.

I can't replicate the watcher issue with a simple project -- I suspect it has something to do with my use of Apache Camel, but I have no idea why that would affect the watcher.

Any hints on problem #2 above i.e. injecting dependencies into a watcher? This seems to work but I'm not sure its the "right" way to use Guice:

AbstractWatcher w = new AbstractWatcher() {...};
requestInjection(w);

bindService(Service.class).out(w).single();

Sign in to add a comment
Powered by Google Project Hosting