/**
* This interface represents a simple service provisioning contract with the
* JBI runtime environment. The invoke method is called when a message
* exchange is addressed to this service instance. Classes implementing this
* interface must be registered in the OSGi service registry in order to be
* available to consumers in the JBI runtime environment. Further, the
* service registration must contain a property called "jbi.service.name" which
* contains the name of the service being offered. Optionally, a property
* called "jbi.endpoint.name" can also be specified.
* @author kcbabo
*/
public interface ServiceProvider {
ServiceMessage invoke(ServiceMessage message) throws Exception;
}
a)A user need to implement the api and write code which will acts as the bridge to actual service/java code, example
public class MyProvider implements ServiceProvider {
public ServiceMessage invoke(ServiceMessage message) throws Exception {
//code that interacts with other pojo/osgi service outside of jbi
}
}
b) Also an user has create an osgi bundle and install the bundle , in order to register the above pojo as osgi service. example
service_ = BundleContext .registerService( ServiceProvider.class.getName(), new MyProvider(), serviceProperties);
Summary of the requiremets in order to have a seemless integration of OSGI/POJO services with JBI is as follows
//BundleContext.java
public ServiceRegistration registerService(String[] clazzes,
Object service, Dictionary properties);
The dictionary above will specify JBI/Fuji specific serviceProperties like
properties.put("jbi.service.name", "abcService");
properties.put("jbi.endpoint.name", "endpoint1");
jbiComp-----NMR-----osgiPoweredEndpoint-----mediator----ActualService
The overall architecture diagram is shown below, Note there is not much difference between the Osgi powered and Spring powered webservices, both are osgi services, however there are some difference while handling these services .
![]() |
public interface ServiceMessage extends NormalizedMessage {
void setPayload(Object payload) throws Exception;
.....
}
Handling Method/Operation Parameters/return type
DataStucture to hold the payload can be simple orderedList ( note this is subject to change) , list = {param1, param2,...paramN}, If the list is empty that means the method has no params,the same can be applicable for the return message
Definitely , if such a payload comes to "osgiPoweredEndpoint" , then the payload needs tranformation before that can be use the pojo, example xmlToJava, binaryToJava, however the flow can remain the same.
jbiComp-----NMR-----osgiPoweredEndpoint-----mediator----ActualService
In the above message flow, basically the mediator needs to transform the message(see b) before invoking the Actual service . Message Tranfromation as such can be resolved in a following way
a) the routing logic includes the transformer, the mediator need not require to handle any tranforamtion in this case, ( note router and pojose possibly needs enhancement to handle domain specific object and service message)
jms "jms1"
java "tranformer1"
spring "spring1"
route do
from "jms1"
to "tranformer1"
to "spring1"
end
b) the tranformer is specified using the service.properties for the spring serviceType
jms "jms1"
spring "spring1"
route do
from "jms1"
to "spring1"
end
the service.properties for spring1 will define the set of tranformer which needs to applied to the payload
#the set of interfaces implemented by the service
......
#set of service properties or dictionary
......
#list of tranformers to be applied to the payload
tranformers = t1, t2, t3
t1=... //define t1 here
t2=...
t3=...
QName("osgi.powered", serviceName)
QName("spring.powered",serviceName)
this will helping in avoiding service name collision while activating a JBI endpoint
let us try out an example the IFL may look as follows
jms "jms1"
spring "spring1"
route do
from "jms1"
to "spring1"
end
The spring1 basically represents an existing spring bean which has been exposed using a spring application and springDM, So what would the the service.properties look like for this spring bean
#the set of interfaces implemented by the service
interfaces=com.examples.intf1,com.examples.intf2,com.examples.intf3
#set of service properties or dictionary
dictionary=jbi.service.name=helloService, jbi.endpoint.name=helloEndpoint
The above needs to be handled using a new JBI component (service engine) , which based on the service.properties will create a service tracker, to track the desired service, also the initiate an JBI internal endpoint corresponding this service, Now possible issues with is worth mentioning in this regard is the there could be more than service which has the given interfaces and the dictionary ( service properties), in that case which is the the service object which wins? the algorithm with respect to this is yet to be decided.
jms "jms1"
spring "spring1"
route do
from "jms1"
to "spring1"
end
In the above example , an user will define an spring POJO with respect to spring1, Also the user need to create the spring-config.xml, based on the application requirement, the pojo corresponding to the spring1 can be wired to many other beans. This would definitely require a new JBI component ( service engine) which will initiate the beans based on the spring-config.xml and expose the beans as jbi service.
In this approach a pojo or interceptor invokes the existing spring or osgi service, The invocation will need to create a message exchange, and "ServiceMessage" as the payload
* The bundle path contains a folder META-INF/spring with one or more files in that folder with a '.xml' extension. * META-INF/MANIFEST.MF contains a manifest header Spring-Context.
a) Activation of JBI endpoints the based on service properties, published by the spring powered service
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"> <osgi:service id="simpleServiceOsgi" ref="simpleService" interface="org.xyz.MyService" /> </beans>
the service properties for the above , will be
org.springframework.osgi.bean.name=simpleService
objectClass={interface1, interface2 }
The default convention will be map the bean.name to jbi-endpoint-service-name and map the interface name to jbi-endpoint-name , however this approach will expose all the spring powered service through the jbi activated endpoints, this may not be desired.
<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface">
<service-properties>
<beans:entry key="jbi.service.name" value="MyService"/>
<beans:entry key="jbi.endpoint.name" value="MyEndpoint"/>
</service-properties>
</service>
iPOJO is a service component runtime aiming to simplify OSGi application development. It natively supports ALL the dynamism of OSGi. The example belows shows how to specify fuji specific service properties using IPOJO
public class FooProviderType1 implements FooService {
private String m_foo;
public void foo() {
System.out.println("foo " + m_foo);
m_foo = "bar";
}
}
<component classname="...FooProviderType1">
<provides>
<property name="fuji.service.name" value="FooService"/>
<property name="fuji.endpoint.name" value="FooEndpoint"/>
</provides>
</component>
http://felix.apache.org/site/apache-felix-service-component-runtime.html
OSGI-INF/sample.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="sample.component" immediate="true">
<implementation class="sample.SampleComparator" />
<property name="fuji.service.name" value="MyService"/>
<property name="fuji.endpoint.name" value="MyEndpoint"/>
<service>
<provide interface="java.util.Comparator" />
</service>
</component>