The Spring Dynamic Modules for OSGi(tm) Service Platforms project makes it easy to build Spring applications that run in an OSGi framework. A Spring application written in this way provides better separation of modules, the ability to dynamically add, remove, and update modules in a running system, the ability to deploy multiple versions of a module simultaneously (and have clients automatically bind to the appropriate one), and a dynamic service model.
OSGi is a registered trademark of the OSGi Alliance. Project name is used pending approval from the OSGi Alliance.
Milestone releases (such as 1.0-rc2 or 1.1.0-m1) are deployed at:
<repository>
<id>spring-maven-milestone</id>
<name>Springframework Maven Repository</name>
<url>http://s3.amazonaws.com/maven.springframework.org/milestone</url>
</repository>
Nightly snapshot builds are provided for testing and development purposes only. They are built by a Bamboo process automatically using the latest snapshot from Subversion.
The snapshots are deloyed to a Maven2 snapshot repository. To use them, just add the following repository to the POM:
<repository>
<id>spring-maven-snapshot</id>
<snapshots><enabled>true</enabled></snapshots>
<name>Springframework Maven SNAPSHOT Repository</name>
<url>http://s3.amazonaws.com/maven.springframework.org/snapshot</url>
</repository>
Individual dependencies can then by added like so:
<dependency>
<groupId>org.springframework.osgi</groupId>
<artifactId>spring-osgi-core</artifactId>
<version>1.0-XXX-SNAPSHOT</version>
</dependency>
OSGified artifacts (such as aopalliance) are provided for development purposes at:
<repository>
<id>spring-osgified-artifacts</id>
<snapshots><enabled>true</enabled></snapshots>
<name>Springframework Maven OSGified Artifacts Repository</name>
<url>http://s3.amazonaws.com/maven.springframework.org/osgi</url>
</repository>
Note that the repository is used internally by Spring DM and it is not supported.
This page defines the "committers charter" for committers on the Spring Dynamic Modules project.
JIRA is used to manage bug reports and feature requests for this project. When working on a new feature or function, please raise a new JIRA issue to cover it (issue type "new feature" or "improvement" as appropriate). This way the other committers know what you are working on, and we have a record of changes made in a release. Please also use JIRA to record and resolve any significant bugs that you find during development.
New code should not be committed to the repository without also committing corresponding unit (and integration if necessary) tests. How you develop the code and tests prior to commit is up to you!
When working on reported bug in JIRA, please follow the process outlined below:
The basic process for committing code to the repository is as follows:
The project uses the Apache 2 License. Please ensure that all source files you commit contain an appropriate copyright and license declaration. You must be sure that you have the rights to any IP contained in a source file before you commit it to the tree.
Build notifications are sent via email from our continuum server. If your commit causes a build breakage (hopefully rare!), please treat fixing the build as the highest priority item.
Commit rights to the project are earnt by demonstrating a committment to contribute to the project over a period of time through quality patches.
The Spring-OSGi project supplies a maven archetype that will create a Spring bundle project for you all set up and ready to go.
To create a new project simply type the following:
mvn archetype:create \
-DarchetypeGroupId=org.springframework.osgi \
-DarchetypeArtifactId=spring-osgi-bundle-archetype \
-DarchetypeVersion=1.0 \
-DgroupId=<your-project-groupId> \
-DartifactId=<your-project-artifactId> \
-Dversion=<your-project-version>
The result of this is a maven project that defines a simple bean, configures it using src/main/resources/META-INF/spring/bundle-context.xml and src/main/resources/META-INF/spring/bundle-context-osgi.xml, and provides unit and (out of container) integration tests. The project is packaged as an OSGi bundle.
There project does not contain a META-INF manifest yet - to generate one invoke the following command:
mvn package
mvn org.apache.felix:maven-bundle-plugin:manifest
You should now see the MANIFEST under target/classes/META-INF/ folder (the upcoming 1.0.1 version will properly generate this folder under META-INF).
Note: if you haven't already downloaded and installed the spring-osgi artifacts (by running 'mvn install' on the spring-osgi tree) you'll need to add an additional parameter to the above command: -DremoteRepositories=http://s3.amazonaws.com/maven.springframework.org/milestone. If this parameter does not work for you first time, see the additional instructions here.
Second Note: Snapshots version are available from: -DremoteRepositories=http://s3.amazonaws.com/maven.springframework.org/snapshot
Simply 'cd' into your newly created project directory and type 'mvn install' and you are good to go!
You can make it really easy to create a new Spring-OSGi bundle project from within eclipse by defining a new "External Tools" launch configuration. Open the "External Tools" configuration dialog, select the "Program" category and click "new". Now you can define a new launch configuration as shown below:

The "${string_prompt}" entries cause eclipse to pop up a dialog asking you for a value when you run tool. You can also change the working directory to be something other than the workspace location (or even a ${folder_prompt} prompt if you like). This is the directory in which your new project will be created.
Now the creation of a new Spring-OSGi bundle project is as easy as:

Note: the generated eclipse project depends on a number of the spring-osgi bundle projects that it expects to find installed in your workspace. See the instructions here for setting these additional projects up (one-time task).
Start up Eclipse with a new (empty) workspace. You can use an existing workspace if you like of course, but I'll assume here you are creating a workspace dedicated to developing with Spring Dynamic Modules.
Define your maven repository to eclipse by running the maven command:
$ cd workspace_dir $ mvn -Declipse.workspace=. eclipse:add-maven-repo
This command creates an Eclipse classpath variable M2_REPO that points to your local maven repository.
Click on the menu triangle at the far right of the Package Explorer menu bar and select "Top Level Elements" -> "Working Sets".

This configures the Package Explorer to show groups of projects known as working sets as the top-level entity in the view. Right now you'll only have one working set called "Other Projects" which is a catch-all working set for anything that is not in a user-defined working set.
From the File menu select "Import..." and the in the "General" category select "Existing Projects into Workspace".
Click the browse button next to "Select root directory" and select the folder spring-osgi/spring-modules/spring-required-libraries. Eclipse will populate the dialog with all the Eclipse projects found under that root that do not already exist in your workspace. Click on "Finish".
Note, I'm assuming that you have already checked out the Spring-OSGi source tree into a folder "spring-osgi" on your machine - if not you need to do that now before you can complete this step. Instructions for checking out the source are available.

Now select all of these newly created projects in the Package Explorer, and with them still selected click on the menu triangle in the Package Explorer tool bar and select "Configure Working Sets".
Click on "New" and create a working set called "Third Party Library Bundles". The projects that you had selected in the Package Explorer will all be included as members of the working set by default. Click on "Finish" to create the working set, and then "OK" to close the outer dialog.
From the file menu select the option to import existing projects into the workspace again, and this time browse to the spring-osgi/spring-modules folder. Import all the projects found. These will be placed in the "Other Projects" working set by default. Select them all and then create a new working set called "Spring Module Bundles" to contain them.
Note that a number of these projects have build errors. This is expected at this stage. From the Problems view menu (triangle on the far right-hand side of the view toolbar again) select "Configure Filters" and then choose "On any element in same project".
Now click on e.g. the spring-hibernate3 project. You'll see error messages such as "No available bundle exports package 'org.hibernate.cfg'". This is because we haven't yet created a third-party bundle project for the hibernate libraries. All of the core Spring modules should build without errors though. If you need to work with one of the projects showing build errors, you'll need to create an OSGi bundle or bundles for the missing dependencies. The quickest way to do this is to select "New" -> "Plug-in Development" -> "Plug-in from existing JAR archives". Select the jars that you want to package as an OSGi bundle, and Eclipse will create a plug-in (OSGi bundle) project for you. After this project has been created, you'll need to "clean" the spring-module projects that depend on it before Eclipse will remove the error markers.
Using the same approach as before, import existing projects into the workspace and point at the "spring-osgi" root folder. This will import all the remaining projects into your workspace. You can further refine these into additional working sets if you wish (e.g. you might create a working set for the samples). After creating additional working sets in the package explorer, you can simply drag projects into the working set you want them to be part of.
This is what my Package Explorer looks like:

You can run any of the unit and integration tests in the source tree simply by choosing "run as..." -> "JUnit test" from the context menu. You can also configure Eclipse to start up Equinox using the Spring-OSGi bundles. Here's how you do this to run the "Simple Service" example:
This will start up equinox (you should see the "osgi>" prompt in the console window). Type 'ss' to see a short status summary of the bundles installed, and 'help' to get an overview of the commands available.
One snag you may have spotted is that out of the box when run in this way the configuration files in META-INF/spring aren't picked up by equinox (because in the exploded project, these are packaged under target/classes). This is only an issue when running inside Eclipse in this way (using the integration test harness or maven build, the resources are found quite happily. You can fix this in one of two ways: create a symbolic link 'spring' from META-INF to src/main/resources/META-INF/spring in the "Simple Service Sample bundle" project (I made my link on the filesystem using 'ln -s' rather than within eclipse. The alternative is to create a copy of the spring folder underneath META-INF. You will need to do this trick for each Spring bundle project you create and want to launch under Eclipse in this manner.
With the link defined, the simple service bundle should now create 2 beans in its application context, and export one of them as a service.
This sample demonstrates how to create a Spring-managed OSGi bundle, publish a service, and test the bundle in an OSGi container. You will find the sample in the svn tree under samples/simple-service.
We're using maven to build the sample, which comprises two separate maven projects: one containing the simple service OSGi bundle, and one for the integration tests. Let's look at the Simple Service bundle project first.
The project defines a simple java interface, org.springframework.osgi.samples.simpleservice.MyService, and an implementation of the interface org.springframework.osgi.samples.simpleservice.impl.MyServiceImpl. When packaging a project as an OSGi bundle, configuration files go in the META-INF/spring directory. This project has two configuration files, simpleservice.xml which defines the simpleService bean, and simpleservice-osgi.xml which includes the Spring OSGi namespace support and uses the osgi:service element to export the simpleService bean as an OSGi service. There is no requirement to split the definitions across two configuration files like this: we did it this way to make it easier to integration test the non-OSGi specific parts of the configuration outside of an OSGi container.
If you look at the pom.xml file for this project you'll see that it specifies packaging osgi-bundle. This causes the project to be packaged as an OSGi bundle when it is built. (The osgi-bundle packaging is supported by the parent pom.xml file which defines the maven-osgi-plugin and configures it to find the OSGi manifest for the bundle in META-INF/MANIFEST.MF.
The MANIFEST.MF file for this bundle gives the bundle a unique symbolic name, and exports the package org.springframework.osgi.samples.simpleservice. This is the package that defines the service interface type. The implementation type (in another package) will be completely hidden from clients of the bundle.
Under the test source root of the simple service bundle project we place tests that are intended to be run outside of any OSGi container. We've added two simple tests, a basic unit test for MyServiceImpl, and a simple integration test. Note how the integration test uses only the simpleservice.xml configuration file.
We want to test the simple service bundle inside a running OSGi container and verify that the service really is exported as we wish. An integration test like this depends on the packaged simple service bundle artifact, so we need to define the test in a separate project, simple-service-integration-test.
Let's start by looking at the pom.xml file for this project. The key part is the build section where we configure the surefire plugin to run during the integration-test phase and not during the test phase. The integration-test lifecycle phase comes after the packaging phase, when the packaged simple service bundle artifact will be available to us to use.
The SimpleServiceBundleTest test case is placed in the test source tree (where surefire can find it). It extends one of the Spring-OSGi JUnit test support classes, ConfigurableBundleCreatorTests. When this test case runs, an OSGi runtime is started up (equinox, felix, or knopflerfish, depending on the maven profile used to run the integration tests :- equinox is the default) and the test artifacts are packaged into a "virtual" bundle on the fly. This bundle is installed into the runtime, together with the other bundles the test depends on, and the test then executes inside the OSGi runtime, passing the results back out.
We override the getTestBundlesNames() method to define the set of bundles that we want to be installed for this test (certain bundles, such as the test support bundle, are always installed automatically). The helper method localMavenArtifact finds a packaged maven artifact produced by the current build. We also override the getManifestLocation operation to define the manifest to be used for the virtual bundle we are creating.
And that's it... we now know how to create a Spring-managed OSGi bundle, unit test, integration test out of the container, and integration test inside OSGi.
Please see this chapter from the reference documentation for more information on the features supported by Spring-DM testing framework.