Northwind Creating the Application

From RifidiWiki

Jump to: navigation, search

This is Step 1 in the Northwind Application Tutorial
Next Step: Step 2: Using Emulator

What you will Learn

  • How to create a Rifidi Edge Server Application Project
  • Declaring OSGi bundle dependencies in the manifest
  • Dependency injection via spring
  • Running an OSGi application in eclipse
  • Redeploying bundles without restarting the server

Creating the new project

First thing you need to do is to create a new OSGi bundle (aka plug-in) project using the wizard provided by eclipse.

  1. Go to File-> New -> Project. Select "Plug-in Project" from the file chooser. Click "Next."
    Tutorial-newwizard1.png
  2. Assign the project a name (for the purposes of this tutorial, I went with "com.northwind.rfid.shipping"). Make sure the plugin is targeted to run with the standard OSGi framework. This makes sure that your plugin is general enough to be deployed in any OSGi runtime (felix, knoplerfish, etc). Click next.
    Tutorial-newwizard2.png
    .
  3. Assign the plugin an ID, which is used to identify the bundle in the OSGi environment. Give it a descriptive name as well as the the name of the entity (company, person, project) that will maintain the bundle. For this bundle, we will keep the Activator, although most of the time when you use spring DM (as we are), it is not necessary to have the activator. Click Finish.
    Tutorial-newwizard3.png

Stating Dependencies in the Manifest

ClassNotFoundException
Sometimes when running a bundle, you will get a ClassNotFoundException even though there were no compile-time errors in your source code. Many times, this is easily solved by adding the package of the problematic class to the import-package statement in the Manifest of your bundle.

An OSGi bundle is simply a jar with some extra information in the manifest. Part of that information is the dependencies of the bundle. There are two ways to state dependency information: bundle-dependencies, and package-dependencies. A bundle dependency means that the bundle you are creating can see all of the exported package of the bundle that is depended on. A package dependency means that some bundle in the OSGi runtime must export that package, but it doesn't matter which bundle. Bundle dependencies are often simpler to state if you will use a large number of packages from the same bundle. However, package dependencies are more flexible since the dependency can be met from any bundle. They make alot of sense for things like javax or apache commons packages since you generally don't know or care exactly which bundle you will use.

In order to get Esper running, we will need to make two bundle-dependencies in the Manifest.

  1. Open up the Manifest.MF file in the META-INF folder
  2. Click on the dependencies tab at the bottom of the editor.
  3. Click "Add" in the Required Plug-ins section.
  4. Add org.rifidi.edge.core.services and org.rifidi.com.espertech.esper.
  5. Click "Add" in the Imported Packages section.
  6. Add net.sf.cglib.reflect
  7. Save the changes.
Tutorial-manifest.png

Creating the Application

Now it's time to actually create the source code for the application.

  1. Right-click on the 'com.northwind.rfid.shipping' package and select New->Class
  2. Give the class a name. I chose ShippingApp. Click finish.
  3. Add a private member of type EsperManagementService. Also make it volatile since the Spring thread will inject the reference (actually a dynamic-proxy) to the object. The volatile keyword will prevent us from experiencing the visibility problem in java.
  4. Add a public setter method. to set the service. This is the method that spring will call when it creates our object.
  5. Add a constructor. Add a printline in the constructor so we know when the object was started.
package com.northwind.rfid.shipping;

import org.rifidi.edge.core.services.esper.EsperManagementService;

/**
 * @author Kyle Neumeier - kyle@pramari.com
 *
 */
public class ShippingApp {
	
	/**Esper service*/
	private volatile EsperManagementService esperService;

	/**
	 * Constructor
	 */
	public ShippingApp() {
		System.out.println("HELLO RFID WORLD!");
	}

	/**
	 * Called by spring
	 * @param esperService
	 */
	public void setEsperService(EsperManagementService esperService) {
		this.esperService = esperService;
	}
}

Creating the Spring Context XML

Next we need to create the spring context XML file. Spring is an application development framework for java; it relieves the amount of boiler-plate code that is normally required when writing applications. In addition, through spring dynamic modules, spring is integrated with OSGi to help start up bundles and access the OSGi service registry among other things.

Rifidi Edge Server applications should use spring to create objectes, register them as services if need be, and look up services from the OSGi service registry and inject them into their objects. To create a spring context xml:

  1. Create a folder called 'spring' in the META-INF folder. Spring will read any xml files in this folder in and use it when starting up the bundle.
  2. Create an xml file. By convention, I call mine spring.xml
  3. Copy and paste the following xml into the file.
<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"
	xmlns:amq="http://activemq.apache.org/schema/core"
	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.xsd">

	<!-- Create the  Application bean and inject dependencies-->
	<bean id="rfidapp" class="com.northwind.rfid.shipping.ShippingApp">
		<property name="esperService" ref="esperManagementService" />
	</bean>

	<!-- Get a reference to the Esper Management Service from the OSGi Service Registry -->
	<osgi:reference id="esperManagementService"
		interface="org.rifidi.edge.core.services.esper.EsperManagementService" />
</beans>

The first beans tag gives the xml processor the location of the xsds that define the namespace information. This allows us to use things like bean and osgi in the xml tags. This makes for cleaner, easier to read files.

The osgi:reference tag tells spring to look up a service in the OSGi service registry which implements the org.rifidi.edge.core.services.esper.EsperManagementService interface. Assign the object to id 'esperManagementService'.

The second bean tag tells spring to instantiate an object of type com.northwind.rfid.shipping.ShippingApp. In addition, we need to inject a bean that is referenced by the ID 'esperManagementService' (which we looked up in the previous tag). To set the service, use a setter method called "setEsperService" (set+<nameProperty>) which exists in the bean.

Running the Application

Now we are ready to run the application. To do this, we need to modify the run configuration slightly in eclipse.

  1. Go to Run-> Run Configurations...
  2. Select the "Edge Server" run configuration under 'OSGi Framework'
  3. Select the Bundles tab. You will see a list of bundles. Each bundle that has a check mark by it will be installed and started when you run the application. The bundles that serve as the 'core' Rifidi Edge Server have already been selected.
  4. Under 'Workspace', check the 'com.northwind.rfid.shipping' bundle.
    Tutorial-RunConfiguration.png
  5. Click "Apply". Click "Run".

Now you should see "HELLO RFID WORLD!" appear in the console, along with other debug information.

Modifying and Redeploying the Application

Now suppose you want to modify your application to print a message when the EsperMangemnetService is injected. You can do this by modifying your application as follows.

	/**
	 * Called by spring
	 * @param esperService
	 */
	public void setEsperService(EsperManagementService esperService) {
		this.esperService = esperService;
		System.out.println("ESPER SERVICE INJECTED!");
	}

Now its time to test out your changes. One thing you could do is shut down the whole edge server and restart it. All the time spent starting and stopping the edge server can add up. One of the benefits of OSGi is being able to start,stop,and update individual bundles without restarting the rest of them. You can use this feature when developing to help cut down on wasted development time.

  1. Make sure the edge server is started inside eclipse
  2. Type 'ss'. This is an equinox command to list every bundle that is currently installed in the OSGi system.
  3. Locate 'com.northwind.rfid.shipping' in the list. Remember the number next to it. For me, the number is '3'.
    Tutorial-ss.png
    .
  4. Now type 'update <bundle_number>'. This is the equinox command to update and restart the given bundle.
  5. You should see both printlines appear.
Personal tools