Ouertani Slim was born in Tunisia in 1981. Now he is a software engineer since 2004 and he is Java 6 and Spring certified with 100% and 94% respectively. He is very interested in Java technology, Scala and open source projects. He believes that programming is one of the hardest jobs and most beautiful in the world. Slim has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

Hessian Declarative Extender in SCA

02.16.2009
| 5570 views |
  • submit to reddit

Before SCA training, I discussed with one of my colleagues about the Hessian extender. We need to export our OSGI services outside container in the SCA fashion, without the need to create explicit proxy. With the Hessian extender, we need to extend HessainServlet, which is not a clean solution, where the service implementation needs to reference Hessian package as an import.

The purpose of this article, is to enable Hessian service exporting declaratively by adding another extender.


The Hessian extender has the following description :



S :  The service implementation and extends com.caucho.hessian.server.HessianServlet
HE : Hessian extender extends HessianServlet to Servlet
SE : Servlet extender publish registered Servlet
C : non-OSGi service client

I propose to add a third extender as following :




S: The service impl and implements IService with no relation to HessianServlet
DHE: Declarative extender to enable SCA service declarative fashion
other bundles : still the same.

Back to our service :


package com.jtunisie.osgi.hessain.sca.service;

import com.jtunisie.osgi.hessian.IService;
import com.jtunisie.osgi.hessian.exceptions.ServiceException;


public class Service implements IService {


@Override
public String execute() throws ServiceException {
return "jTunisie";
}
}
To register this service (using Spring DM), we add that our service will be published outside container using Hessian using the OSGi service property:


  <osgi:service interface="com.jtunisie.osgi.hessian.IService" ref="service">
<osgi:service-properties>
<entry key="url" value="/jtunisie"/>
<entry key="publish" value="hessian"/>
</osgi:service-properties>
</osgi:service>

The DHE will listen to services with property publish = Hessian and as extender will create a Hessian servlet to be published and registered by Hessian extender.

The draft implementation is :
import com.caucho.hessian.server.HessianServlet;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Dictionary;
import java.util.Properties;
import java.util.Set;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

/**
*
* @author slim
*/
public class SCAServiceListner implements BundleActivator, ServiceListener {

@Override
public void serviceChanged(ServiceEvent serviceEvent) {
System.out.println("SERVICE CHANGED");
String[] objectClass = (String[]) serviceEvent.getServiceReference().getProperty("objectClass");

if (serviceEvent.getType() == ServiceEvent.REGISTERED) {
System.out.println(
"Service of type " + objectClass[0] + " registered.");
ServiceReference serviceReference = serviceEvent.getServiceReference();
Object service = bundleContext.getService(serviceReference);
HessianServlet hessianServlet = new SCAHessianServlet(service.getClass(), service);
String url = (String) serviceReference.getProperty("url");
Dictionary p = new Properties();
p.put("url", url);
bundleContext.registerService("com.caucho.hessian.server.HessianServlet", hessianServlet, p);

} else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) {
System.out.println(
"Ex1: Service of type " + objectClass[0] + " unregistered.");
} else if (serviceEvent.getType() == ServiceEvent.MODIFIED) {
System.out.println(
"Ex1: Service of type " + objectClass[0] + " modified.");
}

}
BundleContext bundleContext;

@Override
public void start(BundleContext bundleContext) throws Exception {
bundleContext.addServiceListener(this, "(publish=hessian)");
this.bundleContext = bundleContext;
System.out.println("SERVICE STARTED");
}

@Override
public void stop(BundleContext bundleContext) throws Exception {
bundleContext.removeServiceListener(this);

}

class SCAHessianServlet extends HessianServlet {

private static final long serialVersionUID = 3332768885321918511L;
private final Object object;

public SCAHessianServlet(Class clazz, Object object) {
this.object = object;
this.setAPIClass(clazz);
this.setService(object);
}
}
}

By this way, Hessian isn't needed as a dependency for our service as the DHE will do this for us. I haven't removed the Hessian extender and merge the two extenders for many reasons :

  1. Old Hessian service still working.
  2. DHE can be updated to be as SCA Extender to listen to different services and register them according to target extender.
  3. HE can be upgraded independently.

Conclusion :
OSGI 4.2 introduces RFC 119 - Distributed OSGi and Apache CXF implementation. I am thinking to add JAX-WS to the list of extenders as Hessian and to have this architecture?

Published at DZone with permission of its author, Slim Ouertani.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)