Create OSGI-Spring Project with Maven
Introduction
This document is for developers who knows Java, but not familiar with new technologies such as Spring or OSGi.
Your First Spring-OSGi Project
In this section, you will learn how to create simple Spring + OSGi project with Maven.
Setup
For this tutorial, you need to install the following software:
- Java 5/6
- Maven 2.0.9 or later
Installation of Maven is simple. All you have to do is just download, unzip, and set path to the maven directory.
Procedure
- Open the terminal. Make sure maven is correctly installed on your system.
kono$ mvn -version Maven version: 2.0.9 Java version: 1.5.0_16 OS name: "mac os x" version: "10.4.11" arch: "i386" Family: "unix"
- Create new project.
mvn org.ops4j:maven-pax-plugin:create-project -DgroupId=org.cytoscape -DartifactId=osgi-sample
cd to osgi-sample directory (this is your project name).
Add SpringSource Enterprise Bundle Repository to your project.
mvn pax:add-repository -DrepositoryId=com.springsource.repository.bundles.external -DrepositoryURL=http://repository.springsource.com/maven/bundles/external
This means maven trying to find required bundles in the SpringSource's repository if they does not exist in the central maven repository.
Import infrastructure bundles. In our case, we need Spring Framework and Spring Dynamic Modules to run our bundles. So we need to import those bundles.
mvn pax:import-bundle -DgroupId=org.springframework.osgi -DartifactId=spring-osgi-extender -Dversion=1.1.2 "-DimportTransitive" "-DwidenScope"
- Now create your first bundle. Last two options creates some templates for developing bundles running with Spring DM and simple tests.
mvn pax:create-bundle -Dpackage=org.cytoscape.sample "-Dspring" "-Djunit=4.4"
- Compile, test, and run your project.
mvn clean install pax:provision
Type ps. Then you can see something like this:
-> ps START LEVEL 6 ID State Level Name [ 0] [Active ] [ 0] System Bundle (1.4.1) [ 1] [Active ] [ 5] spring-osgi-extender (1.1.2) [ 2] [Active ] [ 5] spring-osgi-core (1.1.2) [ 3] [Active ] [ 5] SLF4J Jakarta Commons Logging Over SLF4J Binding (1.5.0) [ 4] [Installed ] [ 5] SLF4J API (1.5.0) [ 6] [Active ] [ 5] spring-osgi-io (1.1.2) [ 7] [Active ] [ 5] spring-aop (2.5.5) [ 8] [Active ] [ 5] spring-beans (2.5.5) [ 9] [Active ] [ 5] spring-context (2.5.5) [ 10] [Active ] [ 5] spring-core (2.5.5) [ 11] [Active ] [ 5] spring-test (2.5.5) [ 12] [Active ] [ 5] AOP Alliance API (1.0.0) [ 13] [Active ] [ 5] Backport Util Concurrent (3.1.0) [ 14] [Active ] [ 5] Apache Log4J (1.2.15) [ 15] [Active ] [ 5] Java Messaging System API (1.1.0) [ 16] [Active ] [ 5] Java Transaction API (1.1.0) [ 17] [Active ] [ 5] org.cytoscape.sample (1.0.0.SNAPSHOT) [ 18] [Active ] [ 1] osgi.compendium (4.1.0.build-200702212030) [ 19] [Active ] [ 1] OPS4J Pax Logging - API (1.3.0) [ 20] [Active ] [ 1] OPS4J Pax Logging - Service (1.3.0) [ 21] [Active ] [ 1] Apache Felix Shell Service (1.0.2) [ 22] [Active ] [ 1] Apache Felix Shell TUI (1.0.2) ->
Bundles are running on Apache Felix. You can dynamically start/stop these bundles.[ 17] [Active ] [ 5] org.cytoscape.sample (1.0.0.SNAPSHOT)
This is your bundle. All other bundles are infrastructure bundles which provides functions like shell, AOP, Spring bean creation, etc. To stop your bundle, type
stop 17
where 17 is your bundle ID. Type ps again.
START LEVEL 6 ID State Level Name [ 0] [Active ] [ 0] System Bundle (1.4.1) [ 1] [Active ] [ 5] spring-osgi-extender (1.1.2) [ 2] [Active ] [ 5] spring-osgi-core (1.1.2) [ 3] [Active ] [ 5] SLF4J Jakarta Commons Logging Over SLF4J Binding (1.5.0) [ 4] [Installed ] [ 5] SLF4J API (1.5.0) [ 6] [Active ] [ 5] spring-osgi-io (1.1.2) [ 7] [Active ] [ 5] spring-aop (2.5.5) [ 8] [Active ] [ 5] spring-beans (2.5.5) [ 9] [Active ] [ 5] spring-context (2.5.5) [ 10] [Active ] [ 5] spring-core (2.5.5) [ 11] [Active ] [ 5] spring-test (2.5.5) [ 12] [Active ] [ 5] AOP Alliance API (1.0.0) [ 13] [Active ] [ 5] Backport Util Concurrent (3.1.0) [ 14] [Active ] [ 5] Apache Log4J (1.2.15) [ 15] [Active ] [ 5] Java Messaging System API (1.1.0) [ 16] [Active ] [ 5] Java Transaction API (1.1.0) [ 17] [Resolved ] [ 5] org.cytoscape.sample (1.0.0.SNAPSHOT) [ 18] [Active ] [ 1] osgi.compendium (4.1.0.build-200702212030) [ 19] [Active ] [ 1] OPS4J Pax Logging - API (1.3.0) [ 20] [Active ] [ 1] OPS4J Pax Logging - Service (1.3.0) [ 21] [Active ] [ 1] Apache Felix Shell Service (1.0.2) [ 22] [Active ] [ 1] Apache Felix Shell TUI (1.0.2) ->
You can see your bundle is no longer active. Let's start it againstart 17
Now you can see lots of log messages. If you read those messages carefully, you can see some interesting ones:[SpringOsgiExtenderThread-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myExampleBean' [SpringOsgiExtenderThread-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'myExampleBean' [SpringOsgiExtenderThread-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'myExampleBean' to allow for resolving potential circular references [SpringOsgiExtenderThread-4] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'myExampleBean'
This is the message from Spring Dynamic Modules infrastructure bundles. It recognizes your bundle, and read settings, and automatically create bean named myExampleBean.
Inside Your Bundle
Let's look into the code.
kono$ cd org.cytoscape.sample kono$ ls -l total 16 -rw-r--r-- 1 kono kono 201 Mar 11 17:36 osgi.bnd -rw-r--r-- 1 kono kono 2656 Mar 11 17:36 pom.xml drwxr-xr-x 4 kono kono 136 Mar 11 17:36 src drwxr-xr-x 6 kono kono 204 Mar 11 17:54 target
This is the basic directory structure of Spring-OSGi project created by maven. In the following directory, you can see two XML files
These two XML files defines your beans and OSGi Services.
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-2.5.xsd"> <!-- regular spring configuration file defining the beans for this bundle. We've kept the osgi definitions in a separate configuration file so that this file can easily be used for integration testing outside of an OSGi environment --> <bean name="myExampleBean" class="org.cytoscape.sample.internal.ExampleBeanImpl" /> </beans>
This is the file to define your beans. In this example, only one bean named myExampleBean is defined. This entry creates an instance of org.cytoscape.sample.internal.ExampleBeanImpl and that's all Spring does in this example.
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-1.0.xsd"> </beans>
By default, nothing defined in this file. We can tell Spring DM which beans should be exported as OSGi services by writing settings in this file.
Summary So Far
- There are several important setting files.
pom.xml - Setting file for Maven. Defines name of module, dependency (required bundles we need to run the bundle), and remote repository locations.
bundle-context.xml - Defines Spring beans. Spring reads this file and create instances of concrete classes automatically.
bundle-context-osgi.xml - Defines OSGi service. You can import/export Spring beans as OSGi services.
(to be continued...)