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 Client Extender With Dynamic Proxy Inside OSGi

04.14.2009
| 10009 views |
  • submit to reddit
The next OSGi release (4.2) contains many enhancements such as service registry hooks, transactions and distribution. Apache CXF and Eclipse Riena are the pioneers using this to enable distribution inside OSGi. Newton as an SCA implementation and others frameworks used yet remoting inside osgi current version (4.1).

Introduction


In a previous post I presented how to register a Hessian web service in a declarative way by chaining three extenders. Now, I will try to present how to reference it from remote client bundle using the SCA declaration model adopted in 4.2 release.

To do this I used :
  1. Dynamic Proxys
  2. DynamicImport-Package
  3. Extender bundle listner
  4. Stax XML parser 
  5. Hessian client.


I'll start at the end :

I - Hessian Client

The client bundle contains one activator to track the reference for com.jtunisie.osgi.hessian.IService.

package com.jtunisie.osgi.hessian.client.test;

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

public class Activator implements BundleActivator {

private RemoteServieTracker remoteServiceTracker;

@Override
public void start(BundleContext context) throws Exception {
remoteServiceTracker = new RemoteServieTracker(context);
remoteServiceTracker.open();
String execute = remoteServiceTracker.execute();
System.out.println(execute);
}

@Override
public void stop(BundleContext context) throws Exception {
if (remoteServiceTracker != null) {
remoteServiceTracker.close();
}
}
}


package com.jtunisie.osgi.hessian.client.test;

import com.jtunisie.osgi.hessian.IService;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;


public class RemoteServieTracker extends ServiceTracker implements IService {

public RemoteServieTracker(BundleContext context) {
super(context, IService.class.getName(), null);
}

@Override
public String execute() {
IService service = (IService) getService();
String execute = service.execute();
return execute;
}
}



The requested service is not registered in the current registry. To get it  :

  1. Add remote-services.xml under the OSGI-INF/remote-service directory :
<?xml version="1.0" encoding="UTF-8"?>

<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
<service-description>
<provide interface="com.jtunisie.osgi.hessian.IService" />
<property name="osgi.remote.interfaces">*</property>
<property name="osgi.remote.configuration.type">pojo</property>
<property name="osgi.remote.configuration.pojo.address">http://localhost:8082/jtunisie</property>
</service-description>

</service-descriptions>

 2- Add to the following line to the MANIFEST.MF file : 

Hessian-File : OSGI-INF/remote-service/remote-services.xml


We have finished our test client bundle. Lets start our Extender. The idea is to register a proxy service that will hide remote access as may frameworks do.

II- STAX Parser :

I have used STAX to parse remote-services.xml file :

package com.jtunisie.osgi.hessian.client;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;
import org.osgi.framework.ServiceRegistration;

/**
*
* @author slim
*/
public class Parser {

public static List<Pair> parseRemoteconfig(URL url) {


// Create event reader
InputStream openStream = null;
try {
XMLInputFactory factory = XMLInputFactory.newInstance();
// Setup a new eventReader
openStream = url.openStream();

XMLEventReader eventReader = factory.createXMLEventReader(openStream);
QName name = new QName("name");
QName iname = new QName("interface");
List<Pair> remotes = null;
String remotInterface = "";
String remoteAdress = "";

while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();



if (event.isStartElement()) {

if (event.asStartElement().getName().getLocalPart().equals("service-descriptions")) {
remotes = new ArrayList<Pair>();
}
if (event.asStartElement().getName().getLocalPart().equals("service-description")) {
}
if (event.asStartElement().getName().getLocalPart().equals("provide")) {
Attribute attributeByName = event.asStartElement().getAttributeByName(iname);
if (attributeByName != null) {
remotInterface = attributeByName.getValue();
}
}
if (event.asStartElement().getName().getLocalPart().equals("property")) {

Attribute attributeByName = event.asStartElement().getAttributeByName(name);
if (attributeByName != null && attributeByName.getValue().equals("osgi.remote.configuration.pojo.address")) {
remoteAdress = eventReader.nextEvent().asCharacters().getData();
}
}


}
if (event.isEndElement()) {
if (event.asEndElement().getName().getLocalPart().equals("service-descriptions")) {
return remotes;
}
if (event.asEndElement().getName().getLocalPart().equals("service-description")) {
Pair p = Pair.getInstence(remotInterface, remoteAdress);
remotes.add(p);
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (XMLStreamException ex) {
ex.printStackTrace();
} finally {
try {
openStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
throw new RuntimeException("Parse Exception");
}

public static class Pair {

private String remoteInterface;
private String remoteAdress;
private Class<?> clazz;
private ServiceRegistration serviceRegistration;

static Pair getInstence(String remotInterface, String remoteAdress) {
try {
return new Pair(remotInterface, remoteAdress);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
return null;
}
}

private Pair(String remotInterface, String remoteAdress) throws ClassNotFoundException {
this.remoteInterface = remotInterface;
this.remoteAdress = remoteAdress;
this.clazz = Class.forName(remotInterface);
}

public Class<?> getClazz() {
return clazz;
}

public String getRemoteInterface() {
return remoteInterface;
}

public String getRemoteAdress() {
return remoteAdress;
}

public ServiceRegistration getServiceRegistration() {
System.out.println("Service registred !!");
return serviceRegistration;
}

public void setServiceRegistration(ServiceRegistration serviceRegistration) {
this.serviceRegistration = serviceRegistration;
}
}
}

5
Your rating: None Average: 5 (1 vote)
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.)

Comments

Slim Ouertani replied on Wed, 2009/04/15 - 3:13am

An interesting article about proxies :http://www.osgi.org/blog/2008/08/classy-solutions-to-tricky-proxies.html

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.