Wednesday, July 30

OSGi Text Scrambling Service

Here's most of the code from the peaberry example I mentioned in my previous post - as you can see, peaberry lets you import and export OSGi services from your Guice enabled application, without introducing a dependency on the OSGi API. In fact you can even plug your own service frameworks into peaberry.

EXPORTING BUNDLE


package examples.scrambler.impl;

import static org.ops4j.peaberry.Peaberry.registration;
import static org.ops4j.peaberry.util.TypeLiterals.export;

import com.google.inject.AbstractModule;
import com.google.inject.Key;

import examples.scrambler.Scramble;

// here's where we bind the exported service...
public class ExportModule extends AbstractModule {

@Override
protected void configure() {
// note: the service is exported at injection time
bind(export(Scramble.class)).toProvider(
registration(Key.get(ScrambleImpl.class)).export());
}
}

package examples.scrambler.impl;

import static com.google.inject.Guice.createInjector;
import static org.ops4j.peaberry.Peaberry.osgiModule;

import org.ops4j.peaberry.Export;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import com.google.inject.Inject;

import examples.scrambler.Scramble;

@SuppressWarnings("unused")
public class Activator implements BundleActivator {

@Inject
final Export<Scramble> handle = null;

public void start(final BundleContext ctx) throws Exception {

// apply the exported service binding
createInjector(osgiModule(ctx), new ExportModule()).injectMembers(this);
}

public void stop(final BundleContext ctx) throws Exception {

if (null != handle) {
handle.remove();
}
}
}


IMPORTING BUNDLE


package examples.scrambler.test;

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

import com.google.inject.AbstractModule;

import examples.scrambler.Scramble;

// here's where we bind the imported service...
public class ImportModule extends AbstractModule {

@Override
protected void configure() {
bind(Scramble.class).toProvider(service(Scramble.class).single());
}
}

package examples.scrambler.test;

import static com.google.inject.Guice.createInjector;
import static org.ops4j.peaberry.Peaberry.osgiModule;

import org.ops4j.peaberry.ServiceUnavailableException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import com.google.inject.Inject;

import examples.scrambler.Scramble;

@SuppressWarnings("unused")
public class Activator implements BundleActivator {

// plain text to be scrambled...
final static String TEXT = "This is a simple test of peaberry.";

@Inject
final Scramble service = null; // Guice can actually inject final fields!

Thread tester;

public void start(final BundleContext ctx) throws Exception {

// apply the imported service binding
createInjector(osgiModule(ctx), new ImportModule()).injectMembers(this);

// quick'n'dirty test thread
tester = new Thread(new Runnable() {
public void run() {
// support cooperative cancellation
while (Thread.currentThread() == tester) {
try {
System.out.println('[' + service.process(TEXT) + ']');
} catch (final ServiceUnavailableException e) {
System.err.println("No scrambler service!");
}
try {
Thread.sleep(2000);
} catch (final InterruptedException e) {
// wake-up
}
}
}
});

tester.start();
}

public void stop(final BundleContext ctx) throws Exception {

// cooperatively stop the thread
final Thread zombie = tester;
tester = null;
zombie.join();
}
}

2 comments:

Todor Boev said...

Hello,
I am about to try peaberry for an OSGi project. However I have the following issue:

I need to have a thread get stopped when a service dependency dissappears and restarted when it appears again. Restarting the bundle which runs the thread is not an option. I would like to avoid an active wait loop during the period the dependency is missing. Is there a place in the peaberry API where I can add a listener analoguous to OSGi's ServiceListener?

Basically I'm asking you how to modify the Scrambler example so that the thread in the importer bundle starts up only when the Scrambler service appears and stops when it dissappears :)

mcculls said...

The current peaberry API doesn't support registry hooks/listeners, but you could always use an OSGi service tracker or plain listener.

I've had several thoughts on how to provide this functionality, but no time to actually implement it yet :(

Feel free to raise an issue for this at: http://code.google.com/p/peaberry/issues/list - I'd also like to hear if you have suggestions for the listener API