Difference between revisions of "Northwind Tutorial"

From RifidiWiki

Jump to: navigation, search
(Writing an Esper query)
(Writing an Esper query)
Line 175: Line 175:
 
* A private Set to keep up with all esper queries that we will define
 
* A private Set to keep up with all esper queries that we will define
 
* Give a reference of this to the Activator (more on this later)
 
* Give a reference of this to the Activator (more on this later)
 +
* Create and submit an esper query
 +
* Stop the query when the bundle shuts down.
 
<pre>
 
<pre>
 
package com.mycompany.rfid.app;
 
package com.mycompany.rfid.app;
Line 230: Line 232:
 
}
 
}
 
}
 
}
 +
}
 +
</pre>
 +
 +
In addition, you will need to edit the Activator file to look like this:
 +
<pre>
 +
/**
 +
* The Activator for the bundle. The start() method is called when the bundle is
 +
* starting up. The stop method is called when it is shutting down
 +
*
 +
* @author Kyle Neumeier - kyle@pramari.com
 +
*
 +
*/
 +
public class Activator implements BundleActivator {
 +
 +
/** A reference to the instance of MyApplication */
 +
protected volatile static MyApplication myApp;
 +
 +
/*
 +
* (non-Javadoc)
 +
*
 +
* @see
 +
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
 +
* )
 +
*/
 +
public void start(BundleContext context) throws Exception {
 +
}
 +
 +
/*
 +
* (non-Javadoc)
 +
*
 +
* @see
 +
* org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
 +
*/
 +
public void stop(BundleContext context) throws Exception {
 +
// stop MyApplication when the bundle shuts down
 +
myApp.stop();
 +
}
 +
 
}
 
}
 
</pre>
 
</pre>

Revision as of 20:56, 29 September 2009

This document provides step-by-step instructions on how to get started on developing your first application that runs on the Rifidi Edge Server. The application we will develop will use Esper to collect tag reads from a reader and put them on a JMS queue to be consumed by a client application. Many of the steps are applicable to many kinds of plugins for the edge server, including creating a sensor plugin.

Prerequisites

For this tutorial, we will use Eclipse to develop the application. While it would be possible to develop the application in any IDE that you are familiar with, Eclipse provides great tooling around OSGi application development and deployment, and thus makes this process much easier. If this is your first time developing with eclipse, there will be a learning curve. However, the payoff is worth it.

To get started see Setting up a Development Environment.

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 (I called mine "com.mycompany.rfid.app"). 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

First Things First: Injecting Esper

What you will learn:

  • Declaring OSGi bundle dependencies in the manifest
  • Dependency injection via spring
  • Running an OSGi application in eclipse
  • Redeploying bundles without restarting the server

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. 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.mycompany.rfid.app' package and select New->Class
  2. Give the class a name. I chose MyApplication. 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.mycompany.rfid.app;

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

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

	/**
	 * Constructor
	 */
	public MyApplication() {
		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"
	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">

	<!-- 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" />

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


</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.mycompany.rfid.app.MyApplication. 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.mycompany.rfid.app' 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.mycompany.rfid.app' 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.

Event Stream Processing

What you will learn:

  • Using Rifidi Emulator to speed up RFID development.
  • Controlling the edge server from the command line.
  • Writing Esper queries and listeners.

Running Rifidi Emulator

Rifidi Emulator is a developer tool that emulates the interfaces of many popular RFID readers. It can be used to speed up development of RFID applications, since you can write applications that talk to RFID readers without the need for access for a physical reader. To get Rifidi Emulator up and running follow the steps in the Emulator User's Guide.

For the purposes of this tutorial, create one Alien ALR reader with address 127.0.0.1:20000. Create a few tags (does not matter which kind). Drag and drop the tags onto the antenna. Start the reader.

Connecting to Emulator from the Edge Server

There are two ways (currently) to create a connection to a reader using the edge server. One is to use Workbench.

However, when developing applications on the edge server, it is often quicker to use the Edge Server Console.

Once the edge server is up and going, type the following commands into the console:

  1. readertypes. This lists the kind of reader adapters available. You should see one called Alien9800
  2. createreader Alien9800. This makes a new instance of a reader configuration with the default properties (including the IP & port, which by default is 127.0.0.1:20000 for the Alien). You should see output indicating the sensor was created along with it's ID (probably Alien9800_1).
  3. readers. This lists the created readers. You should see your reader listed here.
  4. createsession Alien9800_1. This creates a session that you will use to connect to the Alien in the emulator.
  5. commandtypes This lists the available kind of commands you can execute.
  6. createcommand Alien9800-GetTagList. Like createreader this creates a new configuration with default properties, except this time its a command configuration.
  7. executecommand Alien9800_1 1 Alien9800-GetTagList_1 1000. This tells the edge server to schedule a Alien9800-GetTagList command on session 1 of Alien9800_1 once every second.
  8. startsession Alien9800_1 1 This tells the session to make the TCP/IP connection. At this point you should see activity on the console of the emulator.

Once you make sure this configuration is working, you can stop the session for now. Just type stopsession Alien9800_1 1.

In addition, type save. This saves the current configuraiton so that you don't have to create the reader, command, session, or schedule the command on the session the next time that you start up the edge server.

Writing an Esper query

Esper is an event processing language and run time. It allows you to define queries in an SQL-like syntax that operate on events rather than the table in a database. It is useful to think of esper queries as SQL queries turned upside down: rather than on-demand queries that operate on static data, you define a relatively static query and the data flows through the query as it is produced. For more information see How to write esper queries.

For this tutorial, we will define a simple query that returns all data produced by a certain reader. Modify MyApplication.java to add the following changes:

  • A private Set to keep up with all esper queries that we will define
  • Give a reference of this to the Activator (more on this later)
  • Create and submit an esper query
  • Stop the query when the bundle shuts down.
package com.mycompany.rfid.app;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

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

import com.espertech.esper.client.EPStatement;

/**
 * @author Kyle Neumeier - kyle@pramari.com
 * 
 */
public class MyApplication {

	/** Esper service */
	private volatile EsperManagementService esperService;
	/**All statements that have been defined so far*/
	private final Set<EPStatement> statements = new CopyOnWriteArraySet<EPStatement>();

	/**
	 * Constructor
	 */
	public MyApplication() {
		Activator.myApp=this;
	}

	/**
	 * Called by spring
	 * 
	 * @param esperService
	 */
	public void setEsperService(EsperManagementService esperService) {
		this.esperService = esperService;
		start();
	}
	
	/**
	 * A method that starts the application
	 */
	private void start(){
		EPStatement query1 = esperService.getProvider().getEPAdministrator().createEPL(
				"select * from ReadCycle where readerID='Alien9800_1'");
		statements.add(query1);
	}
	
	/**
	 * Iterate through all statements and stop them.
	 */
	protected void stop(){
		for(EPStatement statement : statements){
			statement.destroy();
		}
	}
}

In addition, you will need to edit the Activator file to look like this:

/**
 * The Activator for the bundle. The start() method is called when the bundle is
 * starting up. The stop method is called when it is shutting down
 * 
 * @author Kyle Neumeier - kyle@pramari.com
 * 
 */
public class Activator implements BundleActivator {

	/** A reference to the instance of MyApplication */
	protected volatile static MyApplication myApp;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
	 * )
	 */
	public void start(BundleContext context) throws Exception {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		// stop MyApplication when the bundle shuts down
		myApp.stop();
	}

}

Writing an esper listener

Sending out events with JMS

What you will learn:

  • Importing the JMS services provided by Rifidi Edge Server
  • Sending out events over JMS

Exposing events with web services

What you will learn

  • Exporting a service with Web Services

Control With RMI

What you will learn:

  • Providing an RMI interface for control of your application
  • Creating an API bundle
  • Creating a client application for your application

Exporting the application

What you will learn:

  • Exporting your application out of eclipse
  • Running the application in a deployed instance of Rifidi Edge Server
Personal tools