Spring OSGi in Newton reference
Introduction
Newton's support for Spring Dynamic modules for OSGi provides the following capabilities
-
The ability to treat Spring-OSGi bundles as SCA composites and thereby use them just like any other Newton composite.
-
The ability to promote OSGi level services and references to SCA level, so that they can interact using SCA bindings other than OSGi
-
The ability to source the properties in Spring-OSGi configuration files from the SCA properties in their SCA composite document. This makes it easy to deploy and configure Spring-OSGi bundles in a single step.
The approach taken by Newton leaves Spring-OSGi components oblivious to the fact that they are interacting with anything other than the OSGi registry, so their normal lifecycle is undisturbed.
Limitations
At present Newton's Spring-OSGi support is only available when running Newton under Equinox, its default OSGi framework. Support for Felix and Knopflerfish is planned.
Using Spring OSGi bundles with Newton
Configuration basics
To use Spring-OSGi bundles with Newton two new Manifest entries should be added
Installable-Component: true
Installable-Component-Templates=<path to templates>
The first of these simply identifies the bundle as a Newton bundle, and the second tells Newton where to look for the SCA template file (in the case of Spring-OSGi you'll only need one template). Best practice when using Spring-OSGi bundles is to put templates in the META-INF/newton directory alongside the META-INF/spring directory holding Spring configuration files.
To see how these entries can be inserted using Spring-OSGi's build system, take a look at one of the examples.
Spring OSGi based templates can only contain a single SCA level component. This should have implementation type implementaton.spring, in the namespace http://newton.cauldron.org/springdm. implementaton.spring is an implementation type that knows how to wrap a Spring OSGi bundle. It has no attributes because the bundle on which it is based is already known at composite level. Here's a minimal example
<composite name="MyComposite" xmlns:sdm="http://newton.cauldron.org/springdm">
<component name="MyComponent">
<sdm:implementation.spring />
</component>
</composite>
Promoting References and Services from OSGi to SCA
Newton can promote OSGi level services and references to SCA level, where they can be assigned SCA level bindings, and thereby interact with non-OSGi services, e.g. remote ones.
To tell Newton that a service should be promoted to SCA level, the service should be given a single service property called newton.sca.service, the value of which will be used as the service name of the promoted service on the corresponding implementation.spring based SCA component. Here's an example
From bundle-context-osgi.xml
<osgi:service ref="foo" interface="org.cauldron.newton.Foo">
<service-properties>
<entry key="newton.sca.service" value="promotedFoo"/>
</service-properties>
</osgi:service>
This promotes the foo service, giving it the SCA level name promotedFoo. In the corresponding Newton template file this is used as below, and can be wired to any matching SCA composite level service
<component name="MyComponent" xmlns:sdm="http://newton.cauldron.org/springdm">
<service name="promotedFoo" />
<sdm:implementation.spring />
</component>
Similarly, to tell Newton that a reference should be promoted to SCA level it should be given a filter of the form (newton.sca.reference=<SCA level name>).The right hand side of which is used as the name for the SCA reference on the SCA component implemented by Spring. Here's an example:
<osgi:reference id="bar" interface="org.cauldron.newton.Bar"
filter='(newton.sca.reference=promotedBar)'
cardinality="0..1">
<osgi:listener bind-method="bindBar" unbind-method="unbindBar" ref="BarBean"/>
</osgi:reference>
This promotes the bar reference, giving it SCA level name promotedBar. In the corresponding template file this is used as below, and can be wired to any matching SCA composite level reference
<component name="MyComponent" xmlns:sdm="http://newton.cauldron.org/springdm">
<reference name="promotedBar" />
<sdm:implementation.spring />
</component>
Configuring Spring OSGi bundles using SCA properties
Spring-OSGi is able to source bean values from the OSGi Configuration Admin service. Newton is able to source Configuration Admin properties from SCA properties. Consequently Newton SCA properties can be used to set Spring bean properties. To see how this works, take a look at the following example.
On the Spring side, properties are sourced from the Configuration Admin service. For full details see the Spring OSGi documentation. Omitting namespaces, here's a minimal example:
<beans
<property-placeholder persistent-id="org.cauldron.newton.people"/>
<bean name="Person" class="org.cauldron.newton.people.PersonImpl" >
property name="name" value="${person.name}"/>
</bean>
</beans>
Here the persistent-id is the Configuration Admin service pid (persistent id) from which the bean properties are being sourced.
On the Newton side, any implementation.spring based SCA component that sets the property service.pid will have all of its other properties passed to the Configuration Admin service using this service pid. So, for example, to set the property in the above beans file a minimal SCA document would be.
<composite name="springlink" xmlns:sdm="http://newton.cauldron.org/springdm">
<component name="springLink">
<property name="service.pid" value="org.cauldron.newton.people" type="string" />
<property name="person.name" value="Fred" type="string" />
<sdm:implementation.spring />
</component>
</composite>
Note that the properties in Newton template documents can be overridden and augmented in composite instance documents. This leads to a useful design pattern in which the service.pid and default configuration properties are set in the template and any custom values (but not the service pid) are set by overridding these in the instance documents.
Configuring different Spring-OSGi versions
By default Release 1.2 of Newton supports Spring-OSGi version 1.0.1. This version number can be changed by setting the container.springDMVersion property in the the <Newton_HOME>/etc/config.ini.
To simplify loading of the required Spring-OSGi bundles into CDS the following Newton publish file, which loads a minimal set, may be useful
<?xml version="1.0" encoding="iso-8859-1"?>
<publish>
<item name="spring-osgi-core.jar" path="dist/spring-osgi-core-1.0.1.jar" />
<item name="spring-osgi-extender.jar"
path="dist/spring-osgi-extender-1.0.1.jar" />
<item name="spring-osgi-io.jar" path="dist/spring-osgi-io-1.0.1.jar" />
<item name="spring-core-2.5.1.jar" path="lib/spring-core-2.5.1.jar" />
<item name="aopalliance.osgi-1.0-SNAPSHOT.jar"
path="lib/aopalliance.osgi-1.0-SNAPSHOT.jar" />
<item name="jcl104-over-slf4j-1.4.3.jar"
path="lib/jcl104-over-slf4j-1.4.3.jar" />
<item name="slf4j-api-1.4.3.jar" path="lib/slf4j-api-1.4.3.jar" />
<item name="slf4j-log4j12-1.4.3.jar" path="lib/slf4j-log4j12-1.4.3.jar" />
<item name="spring-aop-2.5.1.jar" path="lib/spring-aop-2.5.1.jar" />
<item name="spring-beans-2.5.1.jar" path="lib/spring-beans-2.5.1.jar" />
<item name="spring-context-2.5.1.jar" path="lib/spring-context-2.5.1.jar" />
</publish>
To use this file simple save it as publish-spring-osgi-1.0.1.xml and load from the Newton command line using
cds publish <zone> <path to publish file> <Spring-OSGi install directory>
To use this with later versions of Spring-OSGi the version numbers (at least) will have to be updated. Any more substantial changes will be reflected in a later version of this document.


