Platinum Partner
java,osgi,enterprise-integration,frameworks,maven,sca,spring dm,newton

SCA, Newton and Spring DM

Last week I attended Newton training presented by David Savage and Mike Francis from Paremus. Newton is an open source project aimed to implement the SCA specification using the power of OSGi inside a single JVM and JINI outside it.

 

Goal

Create 2 composite applications:

  • Composite 1: Publish a service outside the current JVM using SCA with Spring DM and Newton
  • Composite 2: Consume service.

Tools

 For this purpose I used:

Project creation

  1. Create a new group project on Netbeans named sca.
  2. New maven projects :
    1. parent pom project that will contain 3 sub-projects :
    2. api : service interface.
    3. impl : service implementation.
    4. client : consuming the service.
  3. Add api dependency to impl and client.
  4. Add resources directories to impl and client projects with empty Spring DM and Newton XML files. 
  5. Project directory will be :

.
|-- api
|   |-- pom.xml
|   `-- src
|       `-- main
|           `-- java
|               `-- com
|                   `-- jtunisie
|                       `-- osgi
|                           `-- sca
|                               `-- IService.java
|-- client
|   |-- pom.xml
|   `-- src
|       `-- main
|           |-- java
|           |   `-- com
|           |       `-- jtunisie
|           |           `-- osgi
|           |               `-- sca
|           |                   `-- client
|           |                       `-- Activator.java
|           `-- resources
|               `-- META-INF
|                   |-- newton
|                   |   `-- client.composite
|                   `-- spring
|                       |-- bundle-context-osgi.xml
|                       `-- bundle-context.xml
|-- impl
|   |-- pom.xml
|   `-- src
|       `-- main
|           |-- java
|           |   `-- com
|           |       `-- jtunisie
|           |           `-- osgi
|           |               `-- sca
|           |                   `-- impl
|           |                       `-- Service.java
|           `-- resources
|               `-- META-INF
|                   |-- newton
|                   |   `-- service.composite
|                   `-- spring
|                       |-- bundle-context-osgi.xml
|                       `-- bundle-context.xml
`-- pom.xml

The IService contains one method signature :

public interface IService extends Serializable  {

String getMessage(String name);
}

The Service implementation is :

public class Service implements IService  {

@Override
public String getMessage(String name) {
return "Hello " + name;
}
}

The client Activator (not an OSGi Activator ):

public class Activator {

IService service;

public void setService(IService service) {
this.service = service;
}

public void init() {
String message = service.getMessage("world!!!!");
System.out.println(message);
}
}

 

Pom Files

  • Change the three projects to bundle packaging : adding <packaging>bundle</packaging> to pom headers.
  • Api will export com.jtunisie.osgi.sca package

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.jtunisie.osgi.sca</Export-Package>
<Bundle-SymbolicName>${pom.name}-${pom.version}</Bundle-SymbolicName>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
  • impl will also export com.jtunisie.osgi.sca package and make implementation private

<build>
<plugins>
<plugin>
<groupid>org.apache.felix</groupid>
<artifactid>maven-bundle-plugin</artifactid>
<extensions>true</extensions>
<configuration>
<instructions>
<export-package>com.jtunisie.osgi.sca</export-package>
<private-package>com.jtunisie.osgi.sca.impl</private-package>
<bundle-symbolicname>${pom.name}-${pom.version}</bundle-symbolicname>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
Note : The impl bundle contains api interface so don't deploy the api bundle. Yes, we don't need to include api inside the impl bundle. Just import the com.jtunisie.osgi.sca package and deploy the two bundles.
  • The client bundle doesn't export any package :

  <build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Private-Package>com.jtunisie.osgi.sca.client</Private-Package>
<Bundle-SymbolicName>${pom.name}-${pom.version}</Bundle-SymbolicName>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
  • Add Newton headers : Installable-Component-Templates is the name of the composite file under resources|-- META-INF|-- newton directory.
    • Impl pom :

        <build>
    <plugins>
    <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
    <instructions>
    <Export-Package>com.jtunisie.osgi.sca</Export-Package>
    <Private-Package>com.jtunisie.osgi.sca.impl</Private-Package>
    <Bundle-SymbolicName>${pom.name}-${pom.version}</Bundle-SymbolicName>
    <Installable-Component>true</Installable-Component>
    <Installable-Component-Templates>META-INF/newton/service.composite</Installable-Component-Templates>
    </instructions>
    </configuration>
    </plugin>
    </plugins>
    </build>
    • client pom :
      <build>
      <plugins>
      <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <extensions>true</extensions>
      <configuration>
      <instructions>
      <Private-Package>com.jtunisie.osgi.sca.client</Private-Package>
      <Bundle-SymbolicName>${pom.name}-${pom.version}</Bundle-SymbolicName>
      <Installable-Component>true</Installable-Component>
      <Installable-Component-Templates>META-INF/newton/client.composite</Installable-Component-Templates>
      </instructions>
      </configuration>
      </plugin>
      </plugins>
      </build>

 

Publishing service

  • Back to impl bundle and it's Spring XML files. Declare the simple Spring bean on bundle-context.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
>

<bean id="service" class="com.jtunisie.osgi.sca.impl.Service"/>
</beans>
  • Publish it on bundle-context-osgi.xml:

<?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-2.5.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">




<osgi:service id="_service" interface="com.jtunisie.osgi.sca.IService" ref="service"/>

</beans>
The service is now published inside the local OSGi container using Spring DM.
  • Now we will expose it outside of the local container. To do this we first add a property to our exposed service to let Newton detect it. bundle-context-osgi.xml will contain.

 <osgi:service id="_service" interface="com.jtunisie.osgi.sca.IService" ref="service">
<osgi:service-properties>
<entry key="newton.sca.service" value="sca_service"/>
</osgi:service-properties>
</osgi:service>
  • Exporting Service :
Newton basically exposes services using RMI outside of the local JVM and we can use OSGi inside it. The composite file is an XML document. To edit it let's add this type to the Netbeans IDE.
  •  Go to tools-->options-->miscellaneous
  • In file extension click new and add composite add associate to it and "APPLICATION/xhtml+xml" .
  •  Open service.composite.
  •   Edit service.composite, add two services for rmi and osgi :
      <service name="sca_service_rmi" >
    <interface.java interface="com.jtunisie.osgi.sca.IService"></interface.java>
    <binding.rmi/>
    </service>
    <service name="sca_service_osgi" >
    <interface.java interface="com.jtunisie.osgi.sca.IService"></interface.java>
    <binding.osgi/>
    </service>
  •  We can use short declaration (but I didn't test it):


    <service name="sca_service_rmi" >
    <interface.java interface="com.jtunisie.osgi.sca.IService"></interface.java>
    <binding.rmi/>
    <binding.osgi/>
    </service>
  • Add our bundle as a component which is implemented using Spring:

<component name="srv">
<description>spring configuration</description>
<service name="sca_service" />
<sdm:implementation.spring />
</component>
The service name is the newton.sca.service property value spring file.
  • We have two services binding and one component. Now, add wiring services :

 <wire>
<source.uri>sca_service_rmi</source.uri>
<target.uri>srv/sca_service</target.uri>
</wire>
<wire>
<source.uri>sca_service_osgi</source.uri>
<target.uri>srv/sca_service</target.uri>
</wire>
  • Add Impl composite :

<?xml version="1.0" encoding="UTF-8"?>
<composite name="configuration"
xmlns:sdm="http://newton.cauldron.org/springdm">.
<service name="sca_service_rmi" >
<interface.java interface="com.jtunisie.osgi.sca.IService"></interface.java>
<binding.rmi/>
</service>
<service name="sca_service_osgi" >
<interface.java interface="com.jtunisie.osgi.sca.IService"></interface.java>
<binding.osgi/>
</service>
<component name="srv">
<description>spring configuration</description>
<service name="sca_service" />
<sdm:implementation.spring />
</component>
<wire>
<source.uri>sca_service_rmi</source.uri>
<target.uri>srv/sca_service</target.uri>
</wire>
<wire>
<source.uri>sca_service_osgi</source.uri>
<target.uri>srv/sca_service</target.uri>
</wire>
</composite>
  • We have finished our first composite. It publishes a service inside and outside of the JVM by configuring just three XML files.

Consuming The Service :

Let's use Spring annotations to consume this service in the client project
  • Add spring-osgi-annotation to pom XML dependency :

<dependency>
<groupId>org.springframework.osgi</groupId>
<artifactId>spring-osgi-annotation</artifactId>
<version>1.1.1</version>
</dependency>
Register Activator bean in bundle-context.xml and enable annotation processor
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-init-method="init">


<bean id="activator" class="com.jtunisie.osgi.sca.client.Activator"/>


<!-- annotation processor -->
<bean class="org.springframework.osgi.extensions.annotation.ServiceReferenceInjectionBeanPostProcessor"/>
</beans>
 
init() method will called as default-init-method.
  • No need to bundle-context-osgi.xml, we can delete it.
  • In the Activator class we add the Spring annotation as follows:

@ServiceReference(filter="(newton.sca.reference=service_cons)")
public void setService(IService service) {
this.service = service;
}
Note: Filter is used to enable Newton.
  • In the composite file we add a service reference named service_ref_rmi

 <reference name="service_ref_rmi" multiplicity="0..1">
<interface.java interface="com.jtunisie.osgi.sca.IService" />
<binding.rmi/>
</reference>
  • Declare a component named serv-test with the reference name as the newton.sca.reference filter value

  <component name="serv-test">
<description>spring configuration</description>
<reference name="service_cons" />
<sdm:implementation.spring />
</component>
  • Wire reference to component :

 <wire>
<source.uri>serv-test/service_cons</source.uri>
<target.uri>service_ref_rmi</target.uri>
</wire>
  • We have finished our second composite :

<?xml version="1.0" encoding="UTF-8"?>
<composite name="service_test"
xmlns:sdm="http://newton.cauldron.org/springdm">

<reference name="service_ref_rmi" multiplicity="0..1">
<interface.java interface="com.jtunisie.osgi.sca.IService" />
<binding.rmi/>
</reference>
<component name="serv_test">
<description>spring configuration</description>
<reference name="service_cons" />
<sdm:implementation.spring />
</component>

<wire>
<source.uri>serv_test/service_cons</source.uri>
<target.uri>service_ref_rmi</target.uri>
</wire>

</composite>

Running The SCA composite :

Before starting this final step,  we need to add to folders and two files.
  • ls
bin  etc       hello                LICENSE.txt  publish-springdm-1.2.0.xml  sdk                   springdm
doc  examples  hello-config.script  lib          NOTICE.txt                  README.html           var

  • Springdm directory contains Spring 1.2 bundles and the hello bundles :

springdm
|-- aopalliance.osgi-1.0-SNAPSHOT.jar
|-- jcl104-over-slf4j-1.4.3.jar
|-- log4j.osgi-1.2.15-SNAPSHOT.jar
|-- slf4j-api-1.4.3.jar
|-- slf4j-api-1.5.2.jar
|-- slf4j-log4j12-1.4.3.jar
|-- slf4j-log4j12-1.5.2.jar
|-- spring-2.5.5.jar
|-- spring-aop-2.5.5.jar
|-- spring-beans-2.5.5.jar
|-- spring-context-2.5.5.jar
|-- spring-context-support-2.5.5.jar
|-- spring-core-2.5.5.jar
|-- spring-osgi-annotation-1.2.0-m1-SNAPSHOT.jar
|-- spring-osgi-core-1.2.0-m1.jar
|-- spring-osgi-extender-1.2.0-m1.jar
`-- spring-osgi-io-1.2.0-m1.jar
hello
|-- client-1.0-SNAPSHOT.jar
`-- impl-1.0-SNAPSHOT.jar

  • publish-springdm-1.2.0.xml will be used to publish the Spring bundles

<?xml version="1.0" encoding="iso-8859-1"?>
<publish>
<item name="spring-2.5.5.jar" path="springdm/spring-2.5.5.jar" />
<item name="spring-aop-2.5.5.jar" path="springdm/spring-aop-2.5.5.jar" />
<item name="spring-beans-2.5.5.jar" path="springdm/spring-beans-2.5.5.jar" />
<item name="spring-context-2.5.5.jar" path="springdm/spring-context-2.5.5.jar" />
<item name="spring-context-support-2.5.5.jar" path="springdm/spring-context-support-2.5.5.jar" />
<item name="spring-core-2.5.5.jar" path="springdm/spring-core-2.5.5.jar" />
<item name="spring-osgi-annotation-1.2.0-m1-SNAPSHOT.jar" path="springdm/spring-osgi-annotation-1.2.0-m1-SNAPSHOT.jar" />
<item name="spring-osgi-core-1.2.0-m1.jar" path="springdm/spring-osgi-core-1.2.0-m1.jar" />
<item name="spring-osgi-extender-1.2.0-m1.jar" path="springdm/spring-osgi-extender-1.2.0-m1.jar" />
<item name="spring-osgi-io-1.2.0-m1.jar" path="springdm/spring-osgi-io-1.2.0-m1.jar" />
<item name="aopalliance.osgi-1.0-SNAPSHOT.jar" path="springdm/aopalliance.osgi-1.0-SNAPSHOT.jar" />
<item name="jcl104-over-slf4j-1.4.3.jar" path="springdm/jcl104-over-slf4j-1.4.3.jar" />
<item name="slf4j-api-1.4.3.jar" path="springdm/slf4j-api-1.4.3.jar" />
<item name="slf4j-log4j12-1.4.3.jar" path="springdm/slf4j-log4j12-1.4.3.jar" />

</publish>



  • hello-config.script contains script routines :
exec etc/scripts/single-jvm-dist-infra 
# install jini browser (optional)
installer install etc/instances/jinibrowser.composite


installer install etc/instances/server-cds.composite
system manage etc/systems/remote-container.system 


# load bundles into cds
cds scan remote /springdm
cds publish remote  publish-springdm-1.2.0.xml . 
cds scan remote /hello
  • Open two terminals and in the first one we execute :
 bin/container -fabricName=test

on the second one
 bin/container -fabricName=test instance=1

If 2 machines are used

 bin/container -fabricName=test -bindAddress=machineIP(1) -serviceLookupURLs=jini:machineIP(1)
 bin/container -fabricName=test -bindAddress=machineIP(2) -serviceLookupURLs=jini:machineIP(1) -instance=1

  • Execute hello-config.script, type it on two terminals.

>exec hello-config.script


  • On the first jvm, we will install the service implementation :

>installer install composite:sca_service

the Service is now installed and you can verify it on the jini  browser.

  • On the other jvm, we will install the client . Let's verify it presence :

>cds find ser*
>Content[service_test:{bundle.symbolic.name=client-1.0-SNAPSHOT, type=component.template, version=1.0.0.SNAPSHOT, zone=remote}]
  • Install it
> installer install composite:service_test
> Hello world!!!!
  • We get our first service message. In fact, the client bundle is downloaded in the client jvm.
  • Verify Bundles

On the client console type :

>eq ss
.....
109 RESOLVED impl-1.0-SNAPSHOT_1.0.0.SNAPSHOT
110 RESOLVED org.springframework.bundle.osgi.io_1.2.0.m1
111 RESOLVED org.springframework.bundle.osgi.core_1.2.0.m1
112 RESOLVED org.springframework.bundle.osgi.extensions.annotations_1.2.0.m1-SNAPSHOT
113 ACTIVE org.springframework.bundle.osgi.extender_1.2.0.m1
114 ACTIVE client-1.0-SNAPSHOT_1.0.0.SNAPSHOT

Impl bundle is downloaded too but not started. Impl bundle is downloaded because it exports the api interfaces.
On the server console type :

> eq ss 
....
108 ACTIVE impl-1.0-SNAPSHOT_1.0.0.SNAPSHOT
109 RESOLVED org.springframework.bundle.spring_2.5.5
110 RESOLVED org.springframework.bundle.osgi.io_1.2.0.m1
111 RESOLVED org.springframework.bundle.osgi.core_1.2.0.m1
112 RESOLVED org.springframework.bundle.osgi.extensions.annotations_1.2.0.m1-SNAPSHOT
113 ACTIVE org.springframework.bundle.osgi.extender_1.2.0.m1
114 ACTIVE com.sun.jini.browser_2.1.0
Note : The implementation is deployed on the server and is activated.
Note : If we have split the impl on two bundles api and impl, only api bundle will be downloaded and an RMI exception may be thrown.

Conclusion :

  1. The next release of OSGii 4.2 encourages using Apache CXF and JEE features.
  2. SCA makes communication simple without any need to know communication protocols, publishing service and consuming in a  declarative way.

source code is published under svn :
svn checkout http://hellosca.googlecode.com/svn/trunk/hellosca-read-only
{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}