Index Changes

Simple Service API

Current Support:

The simple service provides the capability to invoke/interact with JAVA code outside of JBI, i.e Service API provides a bridge between code that is hosted outside of a JBI component and service endpoints available on the NMR. The interface below shows what a user need to do in-order to use simple service api while provision an osgi service.

/**
     * 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;
    }

The two key points with respect to simple service api is

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);

POJO/Spring support , no dependency on fuji api.

How can we enable a jbi component to invoke a OSGI service which has been deployed outside of JBI , without the used any java code or simple service api. The user is expected to use existing osgi service or the user is creating an new POJO ( say as part of a spring application , or using OSGI declarative services or other mechnism and want that POJO to be accessible from JBI or NMR. The user while exposing this pojo as OSGI service needs to specify a set of service properties for those given services and Fuji/JBI framework will facilitate activation for internal endpoint for the given osgi service, so that any component can access the service using JBI MessageExchange. One of the points to note in this case is, what should be the payload for this MessageExchange ?. We will discuss in details of the payload handling in a different section.

Summary of the requiremets in order to have a seemless integration of OSGI/POJO services with JBI is as follows

1. Registering the osgi service:

There could couple of ways this can be done

a) Creating osgi bundle which implements the service registration code.

Also during service registraion the implementation use Service properties which indicates the service needs to activate an internal endpoint

    //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");

b) Declarative way:

This basically assumes that the user make use of other framework like spring/springDM , iPOJO or use OSGI declarative services ( supported by most osgi implementation) to define the service and its properties. more discussion on this at a later stage how ( spring/springDM , iPOJO or OSGI declarative services) can be used for this purpose. The fuji runtime will track the service based on the properties/dictionary irrespective of how they are registered

2. Service tracker :

The fuji/jbi runtime will track all services with required set of properties, ( or osgi powered services), Once such a service is registered , an internal endpoint ( say osgiPoweredEndpoint) will be activated so any jbi component can access the service.

3. Mediator:

For bottom up approach ( example bpel or jruby of pojo invoking a osgi service by sending a jbi messageExchange) the mediation will be done by the JBI framework itself, i.e JBI framework takes care of activation of the endpoint and handling the actual call to the service. For the top down approach there will be separate components (JBI service engine) which activates endpoints based on the service unit artifacts , However the main functionality of the mediator is to mediates all invocation to the osgi service, similar to the existing capability , however now it will have added complexity because of the generic nature, i.e invocation needs to be done using reflection, The interface is not fixed any more ( i.e most likely will be based on the user or business requirement) , and can have any number of methods, The following shows the flow of message exchange and where the mediator fits in
    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 .

4.Payload Handling

Java Object Payload:

This is natural fit to invoke java, however some of the details needs to be worked out, The jbi component/EIP/router needs to use ServiceMessage in this case to create the message-exchange
    public interface ServiceMessage extends NormalizedMessage {
           void setPayload(Object payload) throws Exception;
    .....
    }
Handling Method/Operation Parameters/return type
  1. method with no params: does not require special handling
  2. methods params , using simple javaObject : does not require special handling
  3. methods params using domain specific javaObject: This will require special handling, as the current implementation use StreamSource /ObjectInputStream, fuji runtime or the component( service engine) will not be aware of the domain specific class-definition, so the requirement is to load the class/object back using the module classlaoder which registered the original service. However if the java object payload handling does not involve object serialization and serilization, then it is important to ensure that the class definition of these objects come from the the same osgi bundle as that is used by the target application or osgi service

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

XML payload or any Other payload?

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=...

5.Namespace for JBI endpoints:

Ideally all services which based on configuration or metadata necessitates activation of JBI endpoints can be grouped based on the source of the service registration , the service name can be done as following
    QName("osgi.powered", serviceName)
    QName("spring.powered",serviceName)

this will helping in avoiding service name collision while activating a JBI endpoint

6. ThreadContext Classloader:

The Fuji runtime, will unlikely to have knowledge of the service object and its dependent classes, some libraries used by the serivce object may require the thread context classloader to be module classloader which loaded the bean, so the fuji runtime must ensure set the appropiate context classloader before calling the operation/method on the service object. However for most cases setting the threadContext classloader does not have any effect.

7. UnRegistering service:

The Fuji runtime that uses a service object should register a ServiceListener object to track the availability of the service object, and take appropriate action(deactivate endpoint) when the service object is unregistering. This can also be accomplished using the serivce tracker,

8. Service availabilty:

It might happen that for a given set of interface and service properties more than one service will be available, the runtime basically will choose one of the service at a time, what does that means? if a service goes down then the next appropiate service can be chosen for that endpoint

Top down approach

a) User is using existing Spring beans(libraries) and wants to call them from IFL, what one might characterize as top-down where they work from the service composition/declaration view down.

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.

b)User wants to implement/create a new Spring based service from the IFL, This basically will provide native support for spring, i.e will be able a create a spring application. what this look like when an user is creating an IFL application, let us consider an example

    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.

Bottom up approach

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

SpringDM

Integration of spring with osgi

1. Bundles and Application Contexts

The unit of deployment (and modularity) in OSGi is the bundle, Spring powered bundles. The Spring extender recognizes a bundle as "Spring-powered" and will create an associated application context when the bundle is started and one or both of the following conditions is true:

* 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.

2. Exporting A Spring Bean As An OSGi Service

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.

b) Activation of JBI endpoints the based on fuji specific service properties, published by the spring powered service

    <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 , felix,equinox

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>

OSGI declarative services:

Another possible approach is using OSGI declarative services, the following show how this is done using apache felix

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>



Note

The above document is based on discussion between Andi, Mark White, Girish and Sujit

JSPWiki v2.4.100
[RSS]
« Home Index Changes Prefs
This page (revision-9) was last changed on 23-Sep-09 14:05 PM, -0700 by sujit