Thursday, November 20, 2008

Tutorial: How to create a remote OSGi service

In this article you will learn how to create a remote OSGi service from a "local" OSGi service using R-OSGi. The OSGi service for an user manager is published by the Activator of the service bundle:
public class Activator implements BundleActivator {
public void start(final BundleContext context) throws Exception {
context.registerService(IUserManager.class.getName(), new UserManager(), null);
System.out.println("Service registered.");
}

public void stop(final BundleContext context) throws Exception {}
}
The Activator of the application bundle uses the service:
public class Activator implements BundleActivator {
public void start(final BundleContext context) throws Exception {
final ServiceReference serviceRef = context.getServiceReference(IUserManager.class.getName());
if (serviceRef == null) {
System.out.println("Service not found!");
} else {
final IUserManager userManager = (IUserManager) context.getService(serviceRef);

try {
System.out.println("All user names:");
final List<String> names = userManager.getUserNames();
for (final String name : names) {
System.out.println("Name = " + name);
}
} finally {
context.ungetService(serviceRef);
}
}
}

public void stop(final BundleContext context) throws Exception {}
}
Now you have to verify that R-OSGi is installed on your local Eclipse. Activate the view "Plug-ins" and search for a bundle named ch.ethz.iks.r_osgi.remote. If it is already there, you may skip the following installation procedure.

The easiest way to install R-OSGi into your Eclipse is to install the Eclipse Communication Framework (ECF). Use one of the following update sites:
After the download of the plug-ins, their installation and the restart of the Eclipse IDE the R-OSGi bundle will be available in the "Plug-ins" view.

First, you have to add the bundle ch.ethz.iks.r_osgi.remote to the list of required plug-ins. Do this for both the application and the service bundle. Then you have to mark the published OSGi service as remote service (inside the Activator of the service bundle):
  public void start(final BundleContext context) throws Exception {
final Hashtable properties = new Hashtable();
properties.put(RemoteOSGiService.R_OSGi_REGISTRATION, Boolean.TRUE);
context.registerService(IUserManager.class.getName(), new UserManager(), properties);
System.out.println("Service registered.");
}
That was easy! Using the remote service requires a little bit more code. Instead of getting the user manager service directly from the service registry, you have to get the R-OSGi service from the service registry. Then you have to query the R-OSGi service for the remote user manager services. The code inside the Activator of the application bundle looks like this:
  public void start(final BundleContext context) throws Exception {
final ServiceReference serviceRef = context.getServiceReference(RemoteOSGiService.class.getName());
if (serviceRef == null) {
System.out.println("R-OSGi service not found!");
} else {
final RemoteOSGiService remote = (RemoteOSGiService) context.getService(serviceRef);
try {
remote.connect(new URI("r-osgi://205.207.25.9:9278"));

final RemoteServiceReference[] references = remote.getRemoteServiceReferences(
new URI("r-osgi://205.207.25.9:9278"), IUserManager.class.getName(), null);
if (references == null) {
System.out.println("Service not found!");
} else {
final IUserManager userManager = (IUserManager) remote.getRemoteService(references[0]);

System.out.println("All user names:");
final List<String> names = userManager.getUserNames();
for (final String name : names) {
System.out.println("Name = " + name);
}
}
} finally {
context.ungetService(serviceRef);
}
}
}
Now you should test the remote OSGi service. Create a run configuration for the service and run it. Then create a run configuration for the application and run it. Depending on your user manager implementation you should see something like this (Console of the application):
osgi> All user names:
Name = Charly
Name = Dennis
Name = Ed
You may download the source code from here.