Apache Karaf Cellar and DOSGi
Next version of Apache Karaf Cellar will include a DOSGi (Distributed OSGi) implementation.
There are several existing DOSGi implementations: in Apache CXF (powered by the CXF stack), in Fuse Fabric, etc.
The purpose of the Cellar one is to leverage the Cellar existing (Hazelcast instance, distributed map, etc), and to be very easy to use.
Karaf Cellar DOSGi installation
Cellar DOSGi is part of the main cellar feature. To install it:
karaf@root> features:addurl mvn:org.apache.karaf.cellar/apache-karaf-cellar/3.0.0-SNAPSHOT/xml/features
karaf@root> features:install cellar
Distributed services
You can note a new command available in Cellar:
karaf@root> cluster:list-services
It displays the list of services “cluster aware”. It means a service that could be used remotely from another node.
Code sample
To illustrate the Cellar DOSGi usage, we will use two bundles:
- the provider bundle is installed on node A and “expose” a distributed service
- the client bundle is installed on node B and will use the provider service
Provider bundle
The provider bundle expose an OSGi service, flagged as a distributed service.
The service is very simple, it’s just an echo service.
Here’s the interface describing the service:
package org.apache.karaf.cellar.sample;
public interface EchoService {
String process(String message);
}
and the corresponding implementation:
package org.apache.karaf.cellar.sample;
public class EchoServiceImpl implements EchoService {
&nbps; public String process(String message) {
return "Processed by distributed service: " + message;
}
}
Up to now, nothing special, nothing related to DOSGi or Cellar.
To expose the service in Karaf, we create a blueprint descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="echoService" class="org.apache.karaf.cellar.sample.EchoServiceImpl"/>
<service ref="echoService" interface="org.apache.karaf.cellar.sample.EchoService">
<service-properties>
<entry key="service.exported.interfaces" value="*"/>
</service-properties>
</service>
</blueprint>
We can note that the only “special” part is that we added the service.exported.interfaces
property to the echoService
.
It’s just a flag to define the interface/service to define as distributed (it means accessible from remote node).
We didn’t change the code of the service itself, just added this property. It means that it’s really easy to turn an existing service as a distributed service.
Client bundle
The client bundle will get a reference to the echoService
. In fact, the reference will be a kind of proxy to the service implementation located remotely, on another node.
The client is really simple, it indefinitely iterates to use the clusterService:
package org.apache.karaf.cellar.sample.client;
public class ServiceClient {
private EchoService echoService;
public void setEchoService(EchoService echoService) {
this.echoService = echoService;
}
public EchoService getEchoService() {
return this.echoService;
}
public void process() throws Exception {
int count = 0;
while (true) {
System.out.println(echoService.process("Call " + count));
Thread.sleep(5000);
count++;
}
}
}
We inject the echoService
using Blueprint:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<reference id="echoService" interface="org.apache.karaf.cellar.sample.EchoService"/>
<bean id="serviceClient" class="org.apache.karaf.cellar.sample.client.ServiceClient" init-method="process">
&nbps; <property name="echoService" ref="echoService"/>
</bean>
</blueprint>
It’s done. The serviceClient
will use the echoService
. If a “local” echoService
exists, the OSGi framework will bind the reference to this service, else Cellar will look for a distributed service (on all node) exporting the EchoService
interface and bind a proxy to the distributed service.
Comments
Post a Comment