A Blueprint Container is a mechanism to simplify this process and remove all of the OSGi specific Java code, replacing it with a simple XML file and using dependency injection in the Java code. Today we’ll start using Blueprint by creating a new bundle that imports the service we created last time and registers a second service. We’ll then use this new service to print a message containing the date in the Servlet.

Last time in this series we looked at registering OSGi services and using them in a servlet. You may have noticed that when we registered the service we needed to have a special type of OSGi class: an activator. We then added to it some OSGi specific boiler plate code, if we hadn’t used JNDI to lookup the service then we would of needed even more boiler plate code when we came to use it.

Lets start by creating a new bundle that imports the package containing the interface to obtain a date:

  1. Right click on the “DatePrintingApp” project in the Project Explorer view and select “New” -> “OSGi Bundle Project”
  2. Set the properties:
    • Name: “DateMessageProvider”
    • Target runtime: “WebSphere Application Server V8.5 Liberty Profile”
    • Generate blueprint file: checked
  3. Click “Finish”
  4. Double click on the “Manifest: DateMessageProvider”
  5. Navigate to the “Dependencies” tab
  6. Under “Imported Packages” click on “Add…”
  7. Select “com.example.date”
  8. Click “OK” and save

Now we will define a new service interface that is exported as a public API and a single implementation of it:

  1. Right click on the “src” folder inside the DateMessageProvider project in the Project Explorer view and select “New” -> “Interface”
  2. Give it the properties:
    • Package: “com.example.date.message”
    • Name: “DateMessageProvider”
  3. Click “Finish”
  4. Create the method:

    public String getDateMessage();

  5. Right click on the “src” folder inside the DateMessageProvider project in the Project Explorer view and select “New” -> “Class”
  6. Give it the properties:
    • Package: “com.example.date.message.impl”
    • Name: “DateMessageProviderImpl”
    • Interfaces: com.example.date.message.DateMessageProvider
  7. Add the following implementation to the class:

    public class DateMessageProviderImpl implements DateMessageProvider {
    private DateProvider dateProvider;

      @Override
    public String getDateMessage() {
    String date = (this.dateProvider != null) ? this.dateProvider.getDate() : "unknown";
    return "The current date is: " + date;
    }

    public void setDateProvider(DateProvider dateProvider) {
    this.dateProvider = dateProvider;
    }
    }

Note how we have provided a method to set the DateProvider instance into the class but don’t have any code to look it up. We will use Blueprint’s dependency injection to inject the OSGi service into this class when it is created so lets fill in the Blueprint XML now:

  1. Open the BundleContext/OSGI-INF/blueprint/blueprint.xml file (this was created when we created the project above)
  2.  Click Add… and select “Bean” giving it the following properties:
    • Bean Class: com.example.date.message.impl.DateMessageProviderImpl
    • Bean ID: DateMessageProviderBean
  3. Select the newly created bean and click Add… and select “Property” giving it the following properties:
    • Name: dateProvider
    • Reference: dateProviderRef
  4. Select the root “Blueprint” element again and click Add… selecting “Reference” giving it the following properties:
    • Reference Interface: com.example.date.DateProvider
    • Reference ID: dateProviderRef
  5. Select the newly created reference and under the “Details” section set the “Availability” to “optional”
  6. Select the root “Blueprint” element again and click Add… selecting “Service” giving it the following properties:
    • Service Interface: com.example.date.message.DateMessageProvider
    • Bean Reference: DateMessageProviderBean
  7. If you navigate to the “Source” tab the blueprint.xml should now contain the following:
    <?xml version="1.0" encoding="UTF-8"?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
    	<bean id="DateMessageProviderBean" class="com.example.date.message.impl.DateMessageProviderImpl">
    		<property name="dateProvider" ref="dateProviderRef" />
    	</bean>
    	<reference id="dateProviderRef" interface="com.example.date.DateProvider"
    		availability="optional" />
    	<service ref="DateMessageProviderBean" interface="com.example.date.message.DateMessageProvider" />
    </blueprint>
    

Lets look at each of the elements in this XML:

  • declares a Blueprint bean assigning it an ID and implementation class (if you have used Spring then this should be familiar)
  • declares a property within the bean. The ref property links to the ID of the reference element
  • will lookup an OSGi service that implements the DateProvider interface. We set availability=”optional” because blueprint XML files are processed before starting the bundles in the OSGi application, as the service is being registered in an Activator class it won’t be available when the blueprint file is being processed. As it is an optional reference the bundle will be allowed to start without it being present but will pick it up when it is available, don’t forget that OSGi services are dynamic so may come and go!
  • registers the bean with the service registry, this is equivalent to the Java code that we added to the Activator class last time

With this in place all me need to do is change the servlet that we created last time to use this new service:

  1. In the “DateMessageProvider” project double click on the “Manifest: DateMessageProvider”
  2. Navigate to the “Runtime” tab
  3. Under “Exported Pacakges” and click on “Add…”
  4. Select the “com.example.date.message”
  5. In the “DatePrintingWeb” project double click on the “Manifest: DatePrintingWeb”
  6. Navigate to the “Dependencies” tab and under Imported Packages click “Add…” and import “com.example.date.message”
  7. In the DatePrintingServlet change all occurrences of DateProvider to DateMessageProvider and the method call to getDateMessage()
  8. Refresh the browser

Next time we will be looking at common OSGi bundles. This will allow us to create a bundle that is shared by multiple OSGi applications. If you would like to learn more about Blueprint I would recommend Jarek’s deverloperWorks article.

2 comments on"Getting Started with OSGi Applications: Blueprint Container (Part 3)"

  1. AlexanderDBrown July 28, 2014

    I think there’s a slight typo in step 6. the service interface should be com.ibm.example.date.message.DateMessageProvider; it’s correct in the XML though.

Join The Discussion

Your email address will not be published. Required fields are marked *