by

Hello, OSGi, Part 2: Introduction to Spring Dynamic Modules

how-to
Apr 22, 200825 mins

Build a service-oriented application using Spring and OSGi

If you’ve had your ear to the ground recently, you’ve likely been hearing a lot about service-oriented application development with OSGi and Spring Dynamic Modules. In this second article in the Hello, OSGi series, find out why Spring DM is such an exciting option for developers already familiar with Spring configuration, who want to exploit OSGi’s modularity, easy versioning, and application lifecycle support.

OSGi, also known as the Dynamic Module System for Java, specifies a modular approach to Java application development, as well as a set of standardized methods for managing dependencies between modules. The Spring Dynamic Modules for OSGi Service Platforms project (Spring DM) allows you to build Spring applications that can be deployed in an OSGi container. For Java enterprise developers familiar with the Spring programming and configuration model, Spring DM is an easier way to become familiar with OSGi’s modular approach to application development. In addition to enabling Spring developers to access OSGi’s modular framework and dynamic configuration, Spring DM provides the low-level coding required by most OSGi applications, so that you can focus on your application’s business logic.

The first article in this series (“Hello, OSGi, Part 1: Bundles for beginners“) introduced a standard approach to OSGi development using the OSGi API and the open source Equinox container implementation. You learned about the OSGi architecture, especially containers and bundles, and had your first experience developing an OSGi-based Hello World application. The application example did not run very deep because the goal was simply to grasp the fundamentals of OSGi.

In this article, you’ll build another Hello World application, this time using the Spring DM framework. You’ll learn what Spring DM is and how it leverages OSGi’s separation of application logic into modules, as well as its runtime enforcement of module boundaries. You’ll also learn how to use Spring DM to do the following:

  • Dynamically install, update, and uninstall modules in a running system.
  • Build service-oriented applications (SOAs) by dynamically discovering and using services provided by other modules in a system.
  • Use Spring’s DataSource class to instantiate, configure, assemble, and decorate components within and across system modules.

As you’ll see, using Spring DM will free you of some of the rote work, and even the harder work of understanding what is happening beneath the hood with OSGi. As a result, you’ll be able to get deeper into your application logic, and do it sooner in the development process.

To follow the examples in this article you will need a development environment consisting of Eclipse 3.3 and Spring Dynamic Modules. For the final exercise you will also need an RDBMS such as Apache Derby. You’ll find more below about setting up your Spring DM development environment in Eclipse 3.3.

OSGi and the Spring framework

Currently, OSGi’s popularity is very much on the rise. Several application servers have been repackaged to leverage OSGi’s modular framework, including IBM’s WebSphere Application Server, BEA’s microService Architecture (mSA), and JOnAS 5, an open source application server built from the ground up on an OSGi architecture. JBoss has also recently announced its work on an OSGi-based classloader and its intention to create an OSGi core specification implementation. Perhaps most importantly, the Eclipse Foundation’s OSGi container/runtime component engine, Equinox, has recently been elevated to top-level project status, where it will serve as the basis for the new Eclipse Runtime Initiative.

Even before OSGi achieved its current surge in popularity, there was talk of combining it with Spring. Eventually, this talk led to the Spring Dynamic Modules for OSGi Service Platforms project. The functionality of Spring DM can be divided into two main components: First, it provides Spring framework JARs in the form of OSGi bundles. As you know from the previous article in this series, OSGi bundles are nothing but Java Archive (JAR) files that contain additional entries in a META-INF/MANIFEST.MF file, which acts as the deployment descriptor for an OSGi bundle. (Note that you cannot deploy a JAR file directly when using OSGi; you need to package it using the OSGi bundle format.)

Second, Spring DM provides three OSGi-specific Spring bundles/JARs:

  • org.springframeork.osgi.bundle.extender
  • org.springframeork.osgi.bundle.core
  • org.springframeork.osgi.bundle.io

Applications built using Spring DM are built differently from those that use the Spring framework. When you build a Spring application, you define your configuration information in one or more Spring configuration files, which are mostly XML files. The Spring framework uses these config files to create an application-context object at application startup. After the application context is created it is used to instantiate, configure, assemble, and decorate objects within the application.

In Spring DM, at the time of startup the org.springframeork.osgi.bundle.extender queries all of the existing bundles in the resolved state to learn if any of them is Spring powered. The extender bundle considers a bundle to be Spring powered if it has the Spring-Context manifest header, or if it has XML files in its META-INF/spring folder.

Upon finding a Spring-powered bundle, the org.springframeork.osgi.bundle.extender loads the Spring configuration files in that bundle to create an application-context object for it. While creating the application-context object, the extender also checks whether the bundle is exporting any OSGi services. If so, it exports that Spring bean to the OSGi shared-service registry. If a bundle is importing an OSGI service, it finds the service and adds it as a normal Spring bean in the application context for that bean. The extender also registers a listener for bundle events so that whenever any OSGi bundle goes into a resolved state it checks whether it is Spring powered and follows the same steps.

All of this will become more clear as you develop your first Spring DM application, starting with setting up the environment in the next section.

Setting up your Spring DM development environment

The Spring Dynamic Modules framework 1.0 supports the development of OSGi bundles compliant with OSGi Specification Release 4 and above and JDK 1.4 and above. Spring DM is also tested against the three open source OSGi container implementations: Equinox 3.2.2, Felix 1.0.1, and Knopflerfish 2.0.3, so you can execute your code in any of them.

In developing the examples for this article I have used Eclipse 3.3, which has the Equinox 3.3 OSGi container embedded. The Eclipse IDE provides excellent support for developing, executing, and debugging OSGi bundles. I tested the sample code for this article using JDK 1.5. Please follow these steps for setting up your development environment using the Eclipse IDE:

  1. Download Spring DM, which is in release 1.0.2 at the time of this writing. Be sure to download the spring-osgi-1.0.2-with-dependencies.zip or most current equivalent.
  2. Extract the contents of spring-osgi-1.0.2-with-dependencies.zip onto your machine, say in your c:software folder.
  3. Start up your Eclipse IDE. When asked to select a workspace, select an empty folder such as c:samplespringdm.
  4. Import all the necessary Spring DM JARs for the project. Right-click in the Package Explorer and click on Import –> Plug-in Development –> Plug-ins and Fragments, then click Next. The Import Plug-ins and Fragments dialog will open.
  5. In this dialog, uncheck the target platform checkbox (as specified in the Preferences).
  6. The Browse button for the Plug-in Location should now be enabled; click on it and select C:softwarespring-osgi-1.0.2dist, as shown in Figure 1.

    Importing Spring DM in Eclipse.
    Figure 1. Importing Spring DM JARs (click to enlarge)
  7. Click Next and the Selection dialog will open; add the following three plug-ins to your Plug-ins and Fragments to import:
    • org.springframeork.osgi.bundle.core
    • org.springframeork.osgi.bundle.extender
    • org.springframeork.osgi.bundle.io
    Now click Finish. Eclipse will import these three bundles into your workspace, where you should be able to see them in the Package Explorer view.
  8. Next, you want to import few more bundles from C:softwarespring-osgi-1.0.2lib, so go back and repeat Steps 4 and 5. In Step 6, choose a plug-in location equal to C:softwarespring-osgi-1.0.2lib and click Next.
  9. In the Selection dialog you will see more plug-ins available; select the following:
    • org.springframeork.bundle.spring.aop
    • org.springframeork.bundle.spring.beans
    • org.springframeork.bundle.spring.context
    • org.springframeork.bundle.spring.core
    • org.springframeork.bundle.spring.jdbc
    • org.springframeork.bundle.spring.tx
    • org.springframeork.osgi.aopalliance.osgi
    • backport-util-concurrent.osgi-3.0-SNAPSHOT.jar (if you're using JDK 1.4)
    Click Finish when you’re done and Eclipse will import these seven bundles into your workspace.

Apache Commons Logging is the logging framework for Spring DM. Spring DM provides Apache Commons Logging, as well as Apache Log4j JARs, in the OSGi bundle format. It seems there is some issue with these bundles, however, for I was not able to import them using Eclipse. If you encounter the same problem, take the following steps to create your own OSGi bundle containing these two JARs:

  1. From within Eclipse, click on File –> New –> Project -> Plug-in Development –> Plug-in from existing JAR archives, then click Next. Eclipse will open the JAR Selection dialog.
  2. In JAR Selection, click Add External and you should get the File Selection dialog box. Here you can select commons-logging.jar and log4j-1.2.14.jar. Your JAR Selection dialog should look like the screenshot in Figure 2.

    Select the JARs to include in the plugin.
    Figure 2. Select the JARs to include in the plugin (click to enlarge)
    Click Next and Eclipse will take you to the Plug-in Project Properties dialog.
  3. In the Plug-in Project Properties dialog, enter a project name — something like org.apache.commons.logging. In the Target Platform section select <b>OSGi Framework --> Standard</b> and click Finish.

With this you have set up your Eclipse environment for developing Spring Dynamic Modules plugins. Are you ready to try developing a Hello World application using Spring DM?

Hello, Spring World!

In this section we will develop a simple Hello World application using Spring DM. This very simple application will print “Hello Spring World!!” in your console at the time of starting, and will print “Goodbye Spring World!!” at the time of shutting down. The first step is to create a simple HelloWorld.java class, like this one:

Listing 1. HelloWorld.java

package com.javaworld.osgi.spring;
public class HelloWorld {
    public void start() throws Exception {
        System.out.println("Hello Spring World!! "  );
    }
    public void stop() throws Exception {
        System.out.println("Goodbye Spring World!!");
    }
}


As you can see, HelloWorld.java is a simple class that does not implement any interfaces or extend any superclasses. It has two methods: start() and stop(). The start() method is called at the time of application startup; the stop() method is called at the time of application shutdown.

Your next step is to create a helloworld.xml file in a META-INF/spring folder:

Listing 2. helloworld.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 name="hello" class="com.javaworld.osgi.spring.HelloWorld"
        init-method="start" destroy-method="stop" />
</beans>

In this file you declare only one bean, hello, pointing to the com.javaworld.osgi.spring.HelloWorld class. The value of init-method for this bean is start. The value of the destroy-method attribute is stop.

When you execute your application as an Eclipse OSGi application, you should see the “Hello Spring World!!” message in your console. How could it be so easy? Well, you set it up that way when you created the META-INF/spring folder to contain your helloworld.xml file.

When the extender bundle is started, it sees that your HelloWorld bundle is Spring powered. It then reads helloworld.xml and uses it to create an application context for the bundle. The helloworld.xml file defines a hello bean pointing to your HelloWorld class. The hello bean has defined start() as its initialization method, so the Spring framework will call the start() method of the HelloWorld class. Similarly, when you try to shut down the HelloWorld bundle, the Spring framework will call HelloWorld.java‘s stop() method.

Service-oriented applications in Spring DM

OSGi’s applicability to service-oriented application development is one of its most compelling features. The OSGi service platform allows you build service-oriented applications using OSGi services. A service is nothing but a simple Java object that is published under one or more interface names. The concept of the OSGi service platform is that a source bundle exports services in a common registry. A consumer bundle then searches for a service implementing a particular interface; once found it binds to that service and consumes it.

The OSGi service platform can be very useful when building complex enterprise applications. For example, let’s say you are building a Web application. In an OSGi implementation, you might break up the application into two bundles. The data access bundle would interact with databases and export data access services into a common registry. The Web layer bundle would import data access services and use them to display data to the end user.

Building your application based on this modular architecture (executed as a series of bundles) makes it easy to update your data access service from, for instance, a slow service to a faster one. For that matter, you could create a different data access service to talk to a Web services implementation, then replace the RDMBS access service with this new service without restarting your application.

In the next section we’ll build a service-oriented contact management application. The application will demonstrate how Spring beans can be exported as OSGi services, as well as how OSGi services can be imported as Spring beans.

Importing and exporting service bundles

The Contact Management application has two bundles. The first bundle, ContactDAO, talks to databases and exports ContactDAO objects as OSGi services. The second bundle is the HelloWorld application you developed earlier, which we’ll extend here to import ContactDAO objects (aka OSGi services).

Let’s start by creating the ContactDAO bundle. In order to keep things simple we won’t add real database interaction logic to the bundle; instead, every method will simply write its method name to the Eclipse console.

The first thing to do is create a com.javaworld.sample.osgi.spring.contact.Contact.java class, which we’ll use to carry data from ContactDAO to the HelloWorld bundle, as shown in Listing 3. (Contact.java is a simple class that will represent one contact record in a database.)

Listing 3. Contact.java

package com.javaworld.sample.osgi.spring.contact;
public class Contact {
    int contactId;
    String firstName;
    String lastName;
    public int getContactId() {
            return contactId;
    }
    public void setContactId(int contactId) {
            this.contactId = contactId;
    }
}

Next, we create the ContactDAO.java interface, as shown in Listing 4.

Listing 4. ContactDAO interface

package com.javaworld.sample.osgi.spring.contact;
public interface ContactDAO {
    public List getContactList();
    public Contact getContact(int contactId);
    public void insertContact(Contact contact);
    public void updateContact(Contact contact);
    public void deleteContact(int contactId);
}

ContactDAO is a simple CRUD interface: it defines methods to create, update, retrieve, and delete operations.

Now, create an implementation of the ContactDAO.java class, as shown in Listing 5.

Listing 5. ContactDAOImpl.java

package com.javaworld.sample.osgi.spring.contact.impl;
public class ContactDAOImpl implements ContactDAO {
    public Contact getContact(int contactId) {
        System.out.println("Inside ContactDAOImpl.getContact()");
        return null;
    }
    // Do nothing implementation of all other methods defined in ContactDAO
}

ContactDAOImpl.java provides a “do nothing” implementation of the ContactDAO interface. All we’re doing with this class is writing the method name to System.Out.

Note that both Contact and ContactDAO, which are public classes by necessity (other bundles will need to access them in order to use the ContactDAO service), are in the com.javaworld.sample.osgi.spring.contact package. But the actual implementation class, ContactDAOImpl.java (which is an internal class to the ContactDAO bundle) is in the com.javaworld.sample.osgi.spring.contact.impl package.

Let’s change the MANIFEST.MF file for the ContactDAO bundle to export the com.javaworld.sample.osgi.spring.contact bundle so that it can be accessed from the HelloWorld bundle. All we need to do is add the following line to the MANIFEST.MF:

Export-Package: com.javaworld.sample.osgi.spring.contact

Spring configuration in Spring DM

Now we’re ready to create our Spring configuration files. The recommended practice in Spring DM is to break your configuration into two files, one for defining Spring beans and the other for exporting the Spring beans as OSGi services. We will also break the configuration for our sample application into two files. The first step is to create a contactdao-service.xml file in our META-INF/spring folder, as shown in Listing 6.

Listing 6. Spring context file

<?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 name="contactDAOService"

        class="com.javaworld.sample.osgi.spring.contact.impl.ContactDAOImpl">

    </bean>

</beans>


This simple Spring context file defines the contactDAOService, pointing to the com.javaworld.sample.osgi.spring.contact.impl.ContactDAOImpl class.

Next, we create the META-INF/spring/contactdao-osgi.xml file, which will be used to export the contactDAOService object as an OSGi service:

Listing 7. contactdao-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.xsd
                      http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
    <osgi:service id="contactDAOOSGiService" ref="contactDAOService"
        interface="com.javaworld.sample.osgi.spring.contact.ContactDAO">
    </osgi:service>
</beans>

The contactdao-osgi.xml file has only one <service> element, which is used to export Spring beans as OSGi services in a common registry. The service <service> [element] must have two attributes at minimum: One is the id attribute with a value equal to the name of the Spring bean to be exported. The other is the interface attribute, whose value should be equal to the interface name under which the service should be exported. (See the Spring Dynamic Modules Reference Guide for a complete list of attributes supported by the <service> element.)

So now our ContactDAO service is ready to go. The next step is to extend the HelloWorld application so that it can consume the new service.

HelloWorld as a consumer

If we want the simple HelloWorld application to act as a consumer, we have to empower it to do so. The first step is to change the bundle’s MANIFEST.MF file by adding an Import-Package statement, like this:

Import-Package: com.javaworld.sample.osgi.spring.contact

The HelloWorld bundle will now be able to access classes exported from the com.javaworld.sample.osgi.spring.contact package of the ContactDAO bundle.

Next, we change the HelloWorld.java class, as shown in Listing 8.

Listing 8. Changes to HelloWorld.java

public class HelloWorld {
    ContactDAO contactDAO;
    public ContactDAO getContactDAO() {
        return contactDAO;
    }
    public void setContactDAO(ContactDAO contactDAO) {
        this.contactDAO = contactDAO;
    }
    public void start() throws Exception {
        System.out.println("Hello Spring World!! " );
        System.out.println(contactDAO.getContactList()  );
    }
    public void stop() throws Exception {
        System.out.println("Goodbye Spring World!!");
    }
}


The first thing we did in Listing 8 was to add ContactDAO as a Java bean property, with all the corresponding getter and setter methods. Next, we changed the class’s start() method to call the getContactList() method of the ContactDAO service, in addition to printing out the “Hello Spring World!!” message.

Spring configuration files

The Spring configuration for the HelloWorld bundle is divided into two files: helloworld.xml and helloworld-osgi.xml. Let’s start with helloworld-osgi.xml, shown in Listing 9.

Listing 9. Spring config – helloworld-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.xsd
                      http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
    <osgi:reference id="contactDAOService" interface="com.javaworld.sample.osgi.spring.contact.ContactDAO"/>
</beans>

The helloworld-osgi.xml file declares one reference element, which is used to retrieve the OSGi service and make it available as a Spring bean in the HelloWorld bundle. The reference element has two attributes, id and interface, as previously mentioned. The value of the id attribute is used by Spring DM while adding an OSGi service as a Spring bean in the application context. In this case, we have said that Spring DM should make the service available as a contactDAOService in the application context of the HelloWorld bundle.

The second attribute is interface. Spring DM will use the value of this attribute to find a service matching the given interface. In our sample code we have said that we want a service that implements the com.javaworld.sample.osgi.spring.contact.ContactDAO interface.

Spring DM calls BundleContext.getServiceReference()to find a service that implements the com.javaworld.sample.osgi.spring.contact.ContactDAO interface. If more than one service in the OSGi framework matches that requirement, then the one with the highest ranking is returned. You can also use a filter attribute to precisely define the service you want.

Next, we change the helloworld.xml file so that it will inject the contactDAOService object into our hello bean, as shown in Listing 10.

Listing 10. Spring config – helloworld.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 name="hello" class="com.javaworld.osgi.spring.HelloWorld"
        init-method="start" destroy-method="stop" >
        <property name="contactDAO" ref="contactDAOService"/>
  </bean>
</beans>

Once the ContactDAOService is injected into the application context of your bundle, you can use it as you would any other Spring bean. In our sample code we are injecting the service as a contactDAO property in a HelloWorld bean.

HelloWorld imports a service

Having executed your bundles in the Eclipse IDE, you should get a “Hello Spring World!! Inside ContactDAOImpl.getContactList()” message in your console when you start up the HelloWorld bundle. Under the hood, once the Spring extender bundle is started it sees that there are two Spring-powered bundles. In response, it will first create an application context for the ContactDAO bundle. At the same time, it finds the contactdao-osgi.xml file and exports ContactDAO as an OSGi service in the common registry. Next, it attempts to create an application context for the HelloWorld bundle. Seeing that it has one reference element, extender calls the BundleContext.getService("com.javaworld.sample.osgi.spring.contact.ContactDAO") method, in order to find the class service implementing the com.javaworld.sample.osgi.spring.contact.ContactDAO interface.

In our sample code (in Listing 5) ContactDAOImpl is the only service implementing this interface, so extender returns an object of ContactDAOImpl. Once that object is returned, Spring DM injects it into the HelloWorld bean as a contactDAO property.

Using a Spring DataSource

One of the strengths of the Spring framework is that it provides a set of readymade beans for handling common requirements. In this last section you’ll learn how Spring DM allows you to access these readymade beans in your OSGI-based applications.

In this exercise, we’ll change the ContactDAO bundle so that it connects to an RDBMS to interact with a contact table. We’ll use the Spring DataSource (org.springframework.jdbc.datasource.DriverManagerDataSource) class for connection management. Note that Spring’s DataSource is part of the org.springframework.bundle.spring.jdbc service bundle. I’ve used Apache Derby to test the application code for this exercise; you can use the database of your choice.

The first step in the exercise is to create a contact table in your database. You can use the DDL script in Listing 11 to create the CONTACT table.

Listing 11. DDL for the CONTACT table

CREATE TABLE CONTACT(
   CONTACTID int NOT NULL,
   FIRSTNAME varchar(300),
   LASTNAME varchar(300)
);

We want to use Spring’s DriverManagerDataSource bean for connection management. The problem is, the DriverManagerDataSource class is part of the spring.jdbc bundle, which needs to access your JDBC driver class in order to do its work. The easiest way to resolve the dependency is to import your JDBC driver JAR into the spring.jdbc bundle.

The first step, then, is to right-click on the org.springframework.bundle.spring.jdbc bundle and then click New –> Folder. Name this folder “JARs folder.”

Next, right-click on the newly created JARs folder and click Import –> General –> File System. Under From Directory, the File System dialog should show the location of the directory that contains your JDBC driver JAR. In my case, the location is C:softwaredb-derby-10.2.2.0-binlib. Select the location and it will display a list of JARs in the Select box. Select derbyclient.jar (assuming you are using Derby) and click Finish. Eclipse will import derbyclient.jar to your JARs folder.

The last step in importing the JDBC driver JAR is to add it in your bundle classpath. In order to do that, open the MANIFEST.MF file for the org.springframework.bundle.spring.jdbc bundle in the Plug-in Manifest Editor. Then go to the Runtimes tab and select jars/derbyclient.jar, as shown in Figure 3.

Adding derbyclient.jar to the bundle classpath.
Figure 3. Adding derbyclient.jar to the bundle classpath (click to enlarge)

(If you prefer you can manually update the bundle-classpath entry to: Bundle-ClassPath: spring-jdbc-2.5.jar, jars/derbyclient.jar.)

Now, we’re ready to change the implementation of the ContactDAOImpl class by adding JDBC code to interact with the CONTACT table. If you want, you can import the ContactDAOImpl.java from the sample code for this article; or just take what you see in Listing 12.

Listing 12. ContactDAO implementation for RDBMS access – ContactDAOImpl.java

public class ContactDAOImpl implements ContactDAO {
    DataSource dataSource;
    public DataSource getDataSource() {
        return dataSource;
    }
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
        public List getContactList() {
            List contactList = new ArrayList();
            try {
                Connection connection = dataSource.getConnection();
                Statement stmt= connection.createStatement();
                ResultSet rs =stmt.executeQuery("SELECT * FROM CONTACT");
                while(rs.next()){
                    int contactId = rs.getInt("CONTACTID");
                    String firstName = rs.getString("FIRSTNAME");
                    String lastName = rs.getString("LASTNAME");
                    Contact contact = new Contact(contactId,firstName,lastName);
                    contactList.add(contact);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return contactList;
        }
        //
}

You’ll note a couple of changes to ContactDAOImpl.java in Listing 12:

  • First we’ve added dataSource as a Java bean property with corresponding getters and setters. The Spring framework will take care of creating a DataSource object and injecting it into ContactDAOImpl.
  • The getContactList() method gets connection from the datasource, then uses it to retrieve all the contact records from the CONTACT table. Note that Listing 12 is a partial listing of ContactDAOImpl.java; see the sample code for complete listing.

With the ContactDAOImpl bean ready, the last thing we need to do is change the contactdao-service.xml in the ContactDAO bundle, as shown in Listing 13:

Listing 13. Updating the Spring context file – contactdao-service.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 name="contactDAOService"
        class="com.javaworld.sample.osgi.spring.contact.impl.ContactDAOImpl">
        <property name="dataSource"  >
            <ref bean="dataSource" />
        </property>
    </bean>
    <bean name="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"
            value="org.apache.derby.jdbc.ClientDriver" />
        <property name="url"
            value="jdbc:derby://localhost:1527/C:/derby_home/databases/ClientDB" />
        <property name="username" value="test" />
        <property name="password" value="test" />
    </bean>
</beans>

Changes to contactdao-service.xml are as follows:

  • We’ve declared a dataSource bean pointing to org.springframework.jdbc.datasource.DriverManagerDataSource. This configures Spring to take care of database connection management for the application. (Be sure to use JDBC properties specific to your database in your own bean definition.)
  • Next, we’ve changed the definition of the contactDAOService bean to add a dependency to the dataSource bean.

With this the Spring DM-built HelloWorld service application is ready to go. When you execute the application in your Equinox container, it will print a list of contacts on the console at the time of application startup.

In conclusion

The OSGi specification introduces modularity and a dynamic service model to Spring application development. For developers already familiar with Spring programming and configuration, Spring DM presents an easier entry point to OSGi’s dynamic, modular development specification, without having to learn the OSGi API. As you’ve seen in this article, Spring DM is an excellent platform for service-oriented application development in an OSGi container. Application modules written using Spring DM can be dynamically added, removed, and updated in a running system, and you can also deploy multiple versions of a given module simultaneously.

The final article in this series will be a hands-on introduction to modular, server-side Java development with OSGi. You’ll learn the process of building pluggable, compenentized Web applications in an OSGi container, and also have the opportunity to explore servlet-container options for deploying your applications once they’re built.