Developers, Developers, Developers! Maksim Sorokin IT Blog

18Sep/11Off

Maven + Apache Felix + CXF + DOSGi: An Example of DOSGi Service

Link in series

Link to two Felix instances

Here is yet another post in Maven + Apache Felix + CXF + DOSGi series.

Here I will show how to use Apache CXF DOSGi for cosuming remote services. You may see the sources on my GitHub account.

We will have three projects dosgiRemote.service, dosgiRemote.service.api and dosgiRemote.consumer. dosgiRemote.service.api provides an interface for a service. dosgiRemote.service provides implementation for the service. dosgiRemote.consume will consume the service.
dosgiRemote.service.api has to be shared between dosgiRemote.service and dosgiRemote.consumer as both has to know which service they are publishing and consuming. dosgiRemote.service.api and dosgiRemote.service will run in one OSGi container. dosgiRemote.service.api and dosgiRemote.consumer will run in another OSGi container. You may see how to do that in Eclipse in the previous post.

dosgiRemote.service.api contains the following interface to a service:

package dk.sorokin.maksim.dosgiRemote.service.api;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("greeter")
public interface Greeter {

  @GET
  @Path("sayHello/{name}")
  @Produces(MediaType.TEXT_PLAIN)
  String sayHello(@PathParam("name") String name);
}

dosgiRemote.service provides the following implementation:

package dk.sorokin.maksim.dosgiRemote.internal.service;

import dk.sorokin.maksim.dosgiRemote.service.api.Greeter;

public class GreeterImpl implements Greeter {

  public String sayHello(String name) {
    return "Hello, " + name;
  }
}

Also, dosgiRemote.service registers a service in the following way:

package dk.sorokin.maksim.dosgiRemote.internal;

import java.util.Dictionary;
import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import dk.sorokin.maksim.dosgiRemote.internal.service.GreeterImpl;
import dk.sorokin.maksim.dosgiRemote.service.api.Greeter;

public class Activator implements BundleActivator {

  public void start(BundleContext context) throws Exception {
    Dictionary<String, String> restProps = new Hashtable<String, String>();

    restProps.put("service.exported.interfaces", "*");
    restProps.put("service.exported.configs", "org.apache.cxf.rs");
    restProps.put("service.exported.intents", "HTTP");
    restProps.put("org.apache.cxf.rs.address", "http://localhost:8080/");
    context.registerService(Greeter.class.getName(), new GreeterImpl(), restProps);
  }

  public void stop(BundleContext context) throws Exception {
    //
  }
}

dosgiRemote.consumer will have OSGI-INF\remote-service\remote-services.xml, according to DOSGi documentation:

<?xml version="1.0" encoding="UTF-8"?>
<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
  <service-description>
    <provide interface="dk.sorokin.maksim.dosgiRemote.service.api.Greeter" />
    <property name="service.exported.interfaces">*</property>
    <property name="service.exported.configs">org.apache.cxf.rs</property>
    <property name="service.exported.intents">HTTP</property>
    <property name="org.apache.cxf.rs.address">http://localhost:8080</property>
  </service-description>
</service-descriptions>

And the Activator class for dosgiRemote.consumer will be:

package dk.sorokin.maksim.dosgiRemote.consumer.internal;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

import dk.sorokin.maksim.dosgiRemote.service.api.Greeter;

public class Activator implements BundleActivator {

  @Override
  public void start(BundleContext context) throws Exception {
    ServiceTracker serviceTracker = new ServiceTracker(context, Greeter.class.getName(), null) {
      @Override
      public Object addingService(ServiceReference reference) {
        Object result = super.addingService(reference);

        Object svc = context.getService(reference);
        if (svc instanceof Greeter) {
          final Greeter greeter = (Greeter) svc;
          System.out.println(greeter.sayHello("Max"));
        }

        return result;
      }
    };
    serviceTracker.open();
  }

  public void stop(BundleContext context) throws Exception {
    //
  }
}

We will have two startup configuration for Apache Felix, as described above. The first one:

felix.auto.deploy.action=install,start
felix.log.level=1

org.osgi.framework.storage.clean=onFirstInit

felix.auto.start.1 = \
 assembly:/C:/projects/dosgiRemote/dosgiRemote.service.api/target/classes \
 assembly:/C:/projects/dosgiRemote/dosgiRemote.service/target/classes

And the second one:

felix.auto.deploy.action=install,start
felix.log.level=1

org.osgi.framework.storage.clean=onFirstInit

felix.auto.start.1 = \
 assembly:/C:/projects/dosgiRemote/dosgiRemote.service.api/target/classes \
 assembly:/C:/projects/dosgiRemote/dosgiRemote.service/target/classes

Launch the first configuration and then the second. You should see the following message in the console:

Hello, Max

You could also see the same message in the browser on http://localhost:8080/greeter/sayHello/Max.

You may pass objects as well. Refer to previous posts to do that.

You can take the sources from may GitHub account.

Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.