Tuesday, January 24, 2012

Whirlwind Tour of OSGi: Using Maven for Bundle Packaging, Activators, Service Registration, Configuration, and Custom Shell Commands

OSGi, without the proper assistance, can be a pretty complex technology for engineers to learn.  There's a lot of things to know in order to be productive, and worse yet, most of the process is a departure from what Java developers are accustomed to.  I'm going to attempt to demonstrate how to do some very basic things to become immediately productive in OSGi, including:
  1. Setting up an OSGi bundle project in Maven.
  2. Importing the project into Eclipse.
  3. Configuring Maven and Adding Dependencies.
  4. Writing an OSGi Activator.
  5. Compiling/Creating the Bundle.
  6. Registering a Service in OSGi.
  7. Consuming a Service in OSGi.
  8. Consuming Configuration Updates.
  9. Writing Menu Extensions for the Apache Felix Gogo shell.
  10. Dynamically configuring a Service using the Gogo shell.

I’m not going to spend any time discussing what OSGi is or the importance of the technology.  If you would like to understand the impetus for the framework, I suggest reading the Wikipedia article.  Before starting this tutorial, you should understand what a "bundle" is and the general lifecycle of bundles within an OSGI container.

1.  Setting up an OSGi bundle project in Maven.

Let's start by setting up the project structure in Maven.  I'm going to walk the reader through the correct steps of setting up Maven to do all of the "bundle" work.

Start by creating a project using the "quickstart" archetype.  (I ran this command in the root folder of my Eclipse workspace).
mvn archetype:generate \
 -DgroupId=com.berico.time \
 -DartifactId=timeprovider \
 -Dpackage=com.berico.timeprovider \
 -Dversion=0.0.1-SNAPSHOT
After executing this command, Maven's going to dump 534 different archetypes to choose from.  The default archetype is the Maven "quickstart" archetype (# 169 at the time of this writing).  You can enter 169, or just hit enter.  In all following questions, just use the default (by pressing enter).

2.  Importing the project into Eclipse.

We need to "Eclipsify" your project.  This will let you import the project into Eclipse.  This command also helps sometimes when Eclipse starts messing up the Maven dependency management process (I find that my Eclipse instance stops refreshing the Maven dependencies and this is the only fix).
cd timeprovider
mvn eclipse:eclipse
Now we need to import the project through the IDE.  First start by going to File and selecting Import...


Then we select the Existing Projects into Workspace option and press the Next > button.


When the next window pops up, press the Browse button and select the directory created by Maven and then press Open.


Eclipse should accept the directory as an Eclipse project.  If you did not perform the mvn eclipse:eclipse, it will not allow you to import the directory as a project.  Select Finish to continue.


In the Project Explorer, pane to the left (in Java Perspective), you should see your Maven generated project with the source folders and the pom.xml file.



The last thing we want to do is allow Maven to control the dependencies within Eclipse.  If you are using the SpringSource Tool Suite, the Maven plugin should be installed.  Otherwise, you will need to go through the process of installing it (I think it's called "m2eclipse").

Right-click the project, navigate to the Maven submenu and select Enable Dependency Management.


Ok, we've setup Eclipse and are now ready to configure Maven.

3.  Configuring Maven and Adding Dependencies.

Now that we have the project imported into Eclipse, let's set up Maven to support the creation of OSGi bundles.  The Apache Felix project includes a plugin for Maven which makes developing OSGi bundles a lot easier.  We are going to modify the Maven pom.xml file to include this plugin, as well as, adding a couple of dependencies we will need for our module.

First, let's add the dependencies.  For the purpose of this project, we want the following libraries:

  • org.osgi.core - this is the model necessary to write OSGi applications.  We will get this from the Apache Felix project.
  • org.apache.felix.configadmin - we will use this package later on in the application for configuring our Time Provider service.
  • org.apache.felix.gogo.runtime - Gogo is the shell service used to manage Apache Felix (bundled with Felix).  We will use Gogo to create menu options for the OSGi container. Gogo compliant to the newest OSGi standards, and can actually be used as a replacement shell for other OSGi runtimes like Knopperfish and Eclipse Equinox. For the purpose of this tutorial, we will only use Apache Felix.
  • joda-time - the only useable Date and Time library in Java!  We will use Joda to output time from different time zones in the application.
  • junit - Unit testing library.  Please note that Maven defaults to JUnit 3, so we are changing the only dependency present in the "quickstart" archetype to the newer version of the library.

You pom.xml's dependencies element should now look like this:
<dependencies>
    <dependency>
 <groupId>org.apache.felix</groupId>
 <artifactId>org.osgi.core</artifactId>
 <version>1.0.0</version>
    </dependency>
    <dependency>
 <groupId>org.apache.felix</groupId>
 <artifactId>org.apache.felix.configadmin</artifactId>
 <version>1.2.8</version>
    </dependency>
    <dependency>
 <groupId>org.apache.felix</groupId>
 <artifactId>org.apache.felix.gogo.runtime</artifactId>
 <version>0.10.0</version>
    </dependency>
    <dependency>
 <groupId>joda-time</groupId>
 <artifactId>joda-time</artifactId>
 <version>2.0</version>
    </dependency>
    <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.10</version>
 <scope>test</scope>
    </dependency>
 </dependencies>
Next, we need to add a plugin to Maven to allow it to produce OSGi bundles.  Add the following plugins section to the pom.xml's root element:
<build>
  <plugins>
   <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>2.3.2</version>
     <configuration>
       <target>1.5</target>
       <source>1.5</source>
     </configuration>
   </plugin>
  <plugin> 
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.6</version>
    <extensions>true</extensions>
    <configuration>
      <instructions>
        <Export-Package>
          com.berico.timeprovider.api
        </Export-Package>
        <Private-Package>
          com.berico.timeprovider.internal.*
        </Private-Package>
        <Bundle-Activator>
          com.berico.timeprovider.internal.Activator
        </Bundle-Activator>
      </instructions>
    </configuration>
   </plugin> 
  </plugins>
</build>
The maven-bundle-plugin will provide the facilities to allow bundle create, extending Maven.  The maven-compiler-plugin adds support for annotation processing by forcing the compiler to support Java 5 (or later) language features.

For the most part, you will probably cut and paste this every time you create a bundle.  You do want to pay attention to the plugin -> configuration -> instructions element of this section.  Within this element, you will need to provide bundle-specific information.  In this case, I've specified that the com.berico.timeprovider.api package should be exported within the OSGi runtime.  This is where I will provide interfaces and model that I want consumers to work with.  Alternatively, I don't want developers to be messing with the com.berico.timeprovider.internal package (and subpackages), so I instruct the OSGi container that these are sealed.  Finally, I've specified that the com.berico.timeprovider.internal.Activator class is my bundle activator (think "main method" of the package).

The information contained within this section will be translated into the appropriate bundle metadata required by OSGi, stored in the MANIFEST.MF file.  The observant eye will notice that I did not specify the Import-Package information, required for our bundle to operate (literally having those libraries exposed by OSGi to our bundle's classloader).  One of the really cool things about the Maven plugin is the auto-generation of this metadata based on our dependency declaration in the pom.xml.  Another cool feature of the plugin is the implicit addition of the bundle's classes to the Import-Package, a convention imposed by the OSGi framework.

The last thing we need to do is modify some of the basic information included by default in the pom.xml. We are going to add a couple of properties about the bundle itself (the project.build.sourceEncoding was added by Maven already).  The bundle.symbolicName property maps directly to the Bundle-SymbolicName and the bundle.namespace (though I'm not certain) to the package namespace we want to use on Import-Package.
<properties>
  <bundle.symbolicName>com.berico.timeprovider</bundle.symbolicName>
  <bundle.namespace>com.berico.timeprovider</bundle.namespace>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Now let's change the name of the package to reflect the bundle's symbolic name and namespace (this will appear as the Bundle's name (literally the OSGi Bundle-Name property) within Apache Felix Gogo shell:
<name>Berico Time Provider</name>
And the last change we want to make is to ensure the way Maven packages the project is in the form of a bundle and not a jar (which is the current setting):
<packaging>bundle</packaging>
With these changes, we are now ready to write some code, compile it, and package the results in a properly formatted OSGi bundle.

4.  Write an OSGi Activator.


Now that we can produce a bundle, it's time to write an Activator to demonstrate how this bundle will work in an OSGi container.  An Activator is the entry point of a bundle (it's literally a way to execute code when the bundle is started or stopped by an OSGi container).  The purpose of the Activator is to initialize your service (or tear it down); both the start and stop methods are given access to the BundleContext of the OSGi container.  Using the BundleContext, you can produce or consume services, register listeners for life cycle events with the container, among other things.

The first thing I'm going to do is delete the App class created by Maven in the com.berico.timeprovider package, and create the following classes and subpackages:
  • com.berico.timeprovider.internal.Activator - class that we are referencing as the bundle activator in our Maven pom.xml.
  • com.berico.timeprovider.api.TimeProvider - interface that we are going to offer consumers who want to request the time.
  • com.berico.timeprovider.internal.TimeProviderImpl - this is the implementation of the TimeProvider interface that we will provide consumers.
I've implemented the TimeProvider interface and TimeProviderImpl class completely, but I'm going to leave the Activator inept at the moment.  All we are going to do with the Activator is print a message to the screen when the bundle starts and stops.

TimeProvider.java
package com.berico.timeprovider.api;

public interface TimeProvider {

  String getTime();
 
  String getTime(String timezone) throws Exception;
 
  void setDefaultTimeZone(String timezone) throws Exception;
}
TimeProviderImpl.java
package com.berico.timeprovider.internal;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.berico.timeprovider.api.TimeProvider;

public class TimeProviderImpl implements TimeProvider {
  
  // Default Time Zone is Zulu/GMT (0)
  private DateTimeZone defaultTimeZone 
        = DateTimeZone.forOffsetHours(0);
  
  public String getTime() {
    
    return getTime(this.defaultTimeZone);
  }

  public String getTime(String timezone) throws Exception {
  
    return getTime(DateTimeZone.forID(timezone));
  }
  
  public void setDefaultTimeZone(String timezone) throws Exception {
    
    DateTimeZone dtz = getTimeZone(timezone);
    
    this.defaultTimeZone = dtz;
  }

  private String getTime(DateTimeZone dtz){
    
    DateTime dt = new DateTime(dtz);
    
    return dt.toString();
  }
  
  private DateTimeZone getTimeZone(String timezone) throws Exception {
    
    DateTimeZone dtz = DateTimeZone.forID(timezone);
    
    if(dtz == null){
      
      throw new Exception(
        String.format(
          "Could not parse timezone [%s].", timezone));
    }
    
    return dtz;
  }
}
Activator.java
package com.berico.timeprovider.internal;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

  public void start(BundleContext bundleContext) throws Exception {
    
    System.out.println("com.berico.timeprovider Started");
  }

  public void stop(BundleContext bundleContext) throws Exception {
    
    System.out.println("com.berico.timeprovider Stopped");
  }
}
We will build out the Activator in a little bit.  Before we go any further, let's create our bundle, download an OSGi container, and test to see if the bundle runs correctly.

5.  Compiling/Creating the Bundle.

Now that we have some code, let's compile the bundle.  We're going to perform these steps from the command line instead of using Eclipse.

First, let's ensure our code compiles:
mvn compile
If everything was written correctly, you should see a "BUILD SUCCESS" when Maven finishes executing the build.  Now let's produce the bundle:
mvn bundle:bundle
Once again you should see a "BUILD SUCCESS" at the end of the process.  If you go to the target directory, located in the root of the project, you should see a jar file called timeprovider-0.0.1-SNAPSHOT.jar.


I'm going to change the file extension to zip and extract the contents to show the directory structure.


Finally, let's inspect the MANIFEST.MF file to see what the Maven Bundle Plugin did:
Manifest-Version: 1.0
Bnd-LastModified: 1327273047610
Build-Jdk: 1.6.0_29
Built-By: rclayton
Bundle-Activator: com.berico.timeprovider.internal.Activator
Bundle-ManifestVersion: 2
Bundle-Name: Berico Time Provider
Bundle-SymbolicName: com.berico.time.provider
Bundle-Version: 0.0.1.SNAPSHOT
Created-By: Apache Maven Bundle Plugin
Export-Package: com.berico.timeprovider.api;version="0.0.1.SNAPSHOT"
Import-Package: com.berico.timeprovider.api;version="[0.0,1)",org.joda.t
 ime;version="[2.0,3)",org.osgi.framework;version="[1.3,2)"
Tool: Bnd-1.50.0
Awesome.  Now let's try to get this bundle to install and start in an OSGi container.

In terms of OSGi containers, you have a number of options to choose from.  The entire Eclipse platform is built on the Eclipse Equinox OSGi container.  For our purposes, I'm going to stick with Apache Felix since I am most familiar with it's environment.

Download the Apache Felix from here:  http://felix.apache.org/site/downloads.cgi.

We will also need to ensure our project's dependencies are satisfied; the org.osgi.core dependency is satisfied by the container.  The other dependencies are apart of the Apache Felix project; I will show you a nifty way to retrieve those from Felix's console.  The one library that we will have to manually retrieve is the Joda Time library.

 Download the Joda Time library from here:  http://sourceforge.net/projects/joda-time/files/joda-time/2.0/joda-time-2.0-dist.zip/download

Extract the Apache Felix archive somewhere meaningful.  Next, extract the Joda Time archive, and place the joda-time-2.0.jar in the bundle directory located in the root folder of Apache Felix.  Any OSGi bundle placed in this directory will automatically be installed by the container; for this reason, this folder is ofter referred to as the auto-deploy folder on an OSGi container.


Hey, look at that!  The org.apache.felix.gogo.runtime bundle is already there!  That's one less dependency we will need to load for this example.

Let's start Felix and install the final dependency, the org.apache.felix.configadmin bundle.

To launch Felix, you use the jar switch of the java command to launch the container.  From the root directory of the Felix installation, you would execute the following command:
java -jar bin/felix.jar
I prefer to setup an alias to this command since its so long and dependent on being in the root of that directory:
alias osgi="java -jar `pwd`/bin/felix.jar"
Now we can start the Felix container using the osgi command:


Ok, first let's look at the bundles installed within the container by calling the lb command:


Great!  We have the Joda-Time bundle installed, now we only need to get the org.apache.felix.configadmin bundle installed before we can install our newly created bundle.  Felix includes a bundle called the Apache Felix Bundle Repository that is capable of downloading commonly used OSGi bundles and automatically installing them in the current OSGi container instance.

To see the list of available bundles that can be downloaded by the Felix Bundle Repository, simply type obr:list in the Gogo shell:
g! obr:list
And you should see...
Apache Felix Bundle Repository (1.6.6, ...)
Apache Felix Configuration Admin Service (1.2.4, ...)
Apache Felix Declarative Services (1.6.0, ...)
Apache Felix EventAdmin (1.0.0)
Apache Felix File Install (3.0.2, ...)
Apache Felix Gogo Command (0.10.0, ...)
Apache Felix Gogo Runtime (0.10.0, ...)
Apache Felix Gogo Shell (0.10.0, ...)
Apache Felix Gogo Shell Commands (0.2.0)
Apache Felix Gogo Shell Console (0.2.0)
Apache Felix Gogo Shell Launcher (0.2.0)
Apache Felix Gogo Shell Runtime (0.2.0)
Apache Felix Http Api (2.0.4)
Apache Felix Http Base (2.0.4)
Apache Felix Http Bridge (2.0.4)
Apache Felix Http Bundle (2.0.4)
Apache Felix Http Jetty (2.0.4)
Apache Felix Http Proxy (2.0.4)
Apache Felix Http Samples - Filter (2.0.4)
Apache Felix Http Samples - Whiteboard (2.0.4)
Apache Felix HTTP Service Jetty (1.0.1, ...)
Apache Felix Http Whiteboard (2.0.4)
Apache Felix iPOJO (1.8.0, ...)
Apache Felix iPOJO (0.8.0)
Apache Felix iPOJO API (1.6.0, ...)
Apache Felix iPOJO Arch Command (1.6.0, ...)
Apache Felix iPOJO Composite (1.8.0, ...)
Apache Felix iPOJO Composite (1.0.0, ...)
Apache Felix iPOJO Event Admin Handler (1.8.0, ...)
Apache Felix iPOJO Extender Pattern Handler (1.4.0, ...)
Apache Felix iPOJO Extender Pattern Handler (1.0.0, ...)
Apache Felix iPOJO Gogo Command (1.0.1, ...)
Apache Felix iPOJO JMX Handler (1.4.0, ...)
Apache Felix iPOJO Temporal Service Dependency Handler (1.6.0, ...)
Apache Felix iPOJO URL Handler (1.6.0, ...)
Apache Felix iPOJO WebConsole Plugins (1.6.0, ...)
Apache Felix iPOJO White Board Pattern Handler (1.2.0, ...)
Apache Felix iPOJO White Board Pattern Handler (1.6.0, ...)
Apache Felix Log Service (1.0.0)
Apache Felix Metatype Service (1.0.2, ...)
Apache Felix Prefrences Service (1.0.2)
Apache Felix Remote Shell (1.0.4, ...)
Apache Felix Remote Shell (1.1.2, ...)
Apache Felix Shell Service (1.4.2, ...)
Apache Felix Shell TUI (1.4.1, ...)
Apache Felix UPnP Base Driver (0.8.0)
Apache Felix UPnP Extra (0.4.0)
Apache Felix UPnP Tester (0.4.0)
Apache Felix Web Console Event Plugin (1.0.2)
Apache Felix Web Console Memory Usage Plugin (1.0.0)
Apache Felix Web Console Memory Usage Plugin (1.0.2)
Apache Felix Web Console UPnP Plugin (1.0.0)
Apache Felix Web Management Console (3.1.2, ...)
Apache Felix Web Management Console (3.1.2, ...)
OSGi OBR Service API (1.0.0)
OSGi R4 Compendium Bundle (4.0.0)
Servlet 2.1 API (1.0.0)
The Apache Felix Configuration Admin Service is the final dependency we need to install.  We can install the dependency using the obr:deploy command, supply the argument org.apache.felix.configadmin as the bundle we want deployed:
g! obr:deploy org.apache.felix.configadmin
Which displays...
Target resource(s):
-------------------
   Apache Felix Configuration Admin Service (1.2.4)

Optional resource(s):
---------------------
   Apache Felix Log Service (1.0.0)

Deploying...
done.
Very nice.  Remember, you can check to see if the bundle is installed by using the lb command (lb = "list bundles").  Now let's stop the container.  At the time of this post, I have not yet found an elegant way to terminate the container.  Felix use to have a command called "shutdown", but I cannot find it anymore.  One can always press control-c if the process is running in a terminal, but I found a more elegant (but ugly) way.  If you execute lb, you will see that the first bundle (0, or zero) is the System Bundle.  All other bundles require the system bundle.  So, if you tell the framework to stop the System Bundle, it will shutdown the container and all other bundles dependent on it:
g! stop 0
Your container should yield control back to BASH (or DOS for the poor Windows users).

Even though people will tell you using the auto-deploy feature is not the best way to install a bundle, let's live dangerously and drop our timeprovider bundle into Felix's bundle directory.  Your bundle directory should look like this now:


Let's start Felix up again and see what happens...
osgi
Results in...
com.berico.timeprovider Started
____________________________
Welcome to Apache Felix Gogo

g! 
Wicked! As you saw in the Activator class, when the bundle started (literally the start method was called), we printed the following message out to the console: com.berico.timeprovider Started.

So, if the bundle started successfully, and we saw our start message, we should see the stop message when we tell the container to stop the bundle.  Let's try it out.

Find the id of the bundle using the lb command:
g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (4.0.2)
    1|Active     |    1|Joda-Time (2.0.0)
    2|Active     |    1|Apache Felix Bundle Repository (1.6.6)
    3|Active     |    1|Apache Felix Gogo Command (0.12.0)
    4|Active     |    1|Apache Felix Gogo Runtime (0.10.0)
    5|Active     |    1|Apache Felix Gogo Shell (0.10.0)
    6|Installed  |    1|Apache Felix Configuration Admin Service (1.2.4)
    7|Installed  |    1|Apache Felix Log Service (1.0.0)
    8|Active     |    1|Berico Time Provider (0.0.1.SNAPSHOT)
Now tell the container to stop the bundle supplying the timeprovider's bundle id (in this case, number 8):
g! stop 8
com.berico.timeprovider Stopped
Viola! Our stop message is displayed as expected.

If you gotten this far (assuming you are doing this self and not cheating by simply reading this post), congratulate yourself.  You've created an OSGi bundle, using Maven, and deployed it to an OSGi container.  Furthermore, you've done some cool stuff at the Gogo command line, like installing a bundle using the Felix Bundle Repository.

6.  Registering a Service in OSGi.

Now it's time to start playing with services, the core reason you probably want to learn OSGi.  We created our TimeProvider interface for a reason!  We want to expose this interface as an OSGi service that another bundle can consume.  So how do we do this?  Well, it actually quite easy as you will see.

The only class that needs to change in order to provide an instance of TimeProvider as a service for other bundles is the Activator class.  These changes are reflected below:
package com.berico.timeprovider.internal;

import java.util.Dictionary;
import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

import com.berico.timeprovider.api.TimeProvider;

public class Activator implements BundleActivator {
  
  //Save a handle to the service we registered
  private static 
     ServiceRegistration timeProviderRegistration = null;
  
  public void start(BundleContext bundleContext) throws Exception {
    
    TimeProvider timeProvider = new TimeProviderImpl();
    
    // Ignore this ugliness
    Dictionary properties = new Hashtable();
    
    timeProviderRegistration = 
      bundleContext.registerService(
        TimeProvider.class.getName(), timeProvider, properties);  
    
    System.out.println("com.berico.timeprovider Started");
  }

  public void stop(BundleContext bundleContext) throws Exception {
    
    if(timeProviderRegistration != null){
      
      bundleContext.ungetService(
        timeProviderRegistration.getReference());
    }
    
    System.out.println("com.berico.timeprovider Stopped");
  }
}
A couple of things to note about the changes we've made to the Activator.  We interact with the OSGi environment through the BundleContext.  This includes registering and unregistering services.  To register a service, you simply need to call the registerService method on the BundleContext.  The method takes three arguments.  The first is the String name of the service.  The second parameter is the service itself (implementation).  Finally, we supply metadata to the OSGi framework about the service we are registering.  This metadata is important for certain aspects of OSGi, including bundle queries, where you can search for bundles by the metadata they provide.  In our case, we have nothing useful to supply, so we give it an empty (but initialized) Dictionary collection.

If you've done any serious work in Java, you are probably wondering why we are not using Java Generics.  The OSGi framework was originally created to support mobile phone applications before Generics were introduced on the Java platform.  Since the specification targets platforms pre-Java 5, we are stuck "boxing" and "unboxing" objects and using non-generic collections.  From what I understand, the newest specification for OSGi will include an API supporting generics, cleaning up this ugliness.

Now that we've learned how to register a service with the OSGi container, let's create a new bundle that will consume the service.

7.  Consuming a Service in OSGi.

Without going through the steps all over again, I'm going to create a new, separate bundle called timeconsumer.  In the new timeconsumer project, I'm only going to create one BundleActivator class (and nothing else), which I will unimaginatively call Activator:
package com.berico.timeconsumer;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import com.berico.timeprovider.api.TimeProvider;

public class Activator implements BundleActivator {

  private static ServiceReference timeProviderReference = null;
  
  public void start(BundleContext bundleContext) throws Exception {
    
    timeProviderReference
      = bundleContext.getServiceReference(
        TimeProvider.class.getName());
    
    if(timeProviderReference != null){
    
      TimeProvider timeProvider = 
        (TimeProvider)bundleContext.getService(timeProviderReference);
      
      System.out.println("com.berico.timeconsumer Started");

      System.out.println(
        String.format("Current Time is %s", timeProvider.getTime()));
    }
    else {
      
      System.out.println("Could not find a valid Time Provider");
    }
  }

  public void stop(BundleContext bundleContext) throws Exception {
    
    if(timeProviderReference != null){
      
      bundleContext.ungetService(timeProviderReference);
    }
    
    System.out.println("com.berico.timeconsumer Stopped");
  }

}
The Activator class is first grabbing a ServiceReference to the service we want to consume.  The ServiceReference contains the service id along with information about the bundle the service was registered from.  We next ensure the reference is not null.  If it is null, we print a message to the console saying we couldn't find the time provider.  If the reference is set, we go back to the BundleContext grabbing the service.  Remember that OSGi doesn't currently support generics, so we have to cast the object that is returned to the appropriate type.  Finally, we print the time to the console, provided by the time provider instance.

The hard part, believe it or not, is the pom.xml and not the Activator class.  There are some little tricks we have to do in order to get our timeconsumer to use the timeproducer as a dependency.  The first thing we need to do is install our timeproducer as an artifact in the local Maven repository.  This is a simple command that you can execute within the root directory of the timeproducer project:
mvn install:install
With the timeproducer bundle installed, we need to add a dependency to the timeproducer project in our timeconsumer's pom.xml:
<dependency>
  <groupId>com.berico.time</groupId>
  <artifactId>timeprovider</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>
Adding the dependency is only the first step.  Since we depend on the timeproducer to start and register the TimeProvider implementation with the OSGi container before we attempt to consume the service in the timeconsumer bundle, we will need to add a special element to the plugin > configuration > instructions of the Maven Bundle Plugin configuration:
<Require-Bundle>com.berico.time.provider</Require-Bundle>
The Require-Bundle attribute essentially tells the OSGi container not to start the bundle until the bundles referenced in the value of the property are started.  The strange thing you might notice is the name of the bundle: com.berico.time.provider.  The groupId in our timeprovider Maven configuration is com.berico.time and our name is timeprovider.  The bundle.symbolicName property in the pom.xml is com.berico.timeprovider.  However, when the bundle is created by Maven, the MANIFEST.MF is written with the Bundle-SymbolicName as com.berico.time.provider.  I suspect there is an error with Maven Bundle Plugin causing it to improperly output the symbolic name.  If you are ever unsure what to use, the simple way to find out the symbolic name of a bundle is to unzip the bundle and open the MANIFEST.MF in a text editor.  If the bundle in question will install in the OSGi container, you can also execute the headers command of the Gogo shell, followed by the id of the bundle to inspect:
g! headers 19
Which Produces:
Berico Time Provider (19)
-------------------------
Bnd-LastModified = 1327295763667
Build-Jdk = 1.6.0_29
Built-By = rclayton
Bundle-Activator = com.berico.timeprovider.internal.Activator
Bundle-ManifestVersion = 2
Bundle-Name = Berico Time Provider
Bundle-SymbolicName = com.berico.time.provider
Bundle-Version = 0.0.1.SNAPSHOT
Created-By = Apache Maven Bundle Plugin
Export-Package = com.berico.timeprovider.api;version="0.0.1.SNAPSHOT"
Import-Package = com.berico.timeprovider.api;version="[0.0,1)",org.joda.time;version="[2.0,3)",org.osgi.framework;version="[1.3,2)"
Manifest-Version = 1.0
Tool = Bnd-1.50.0
g! 
Now let's drop the timeconsumer bundle in the auto-deploy directory of Felix.
Start up the OSGi container:
osgi
And you should see...
com.berico.timeprovider Started
Current Time: 2012-01-24T02:48:58.374Z
com.berico.timeconsumer Started
Current Time is 2012-01-24T02:48:58.395Z
____________________________
Welcome to Apache Felix Gogo

g! 
Success!  We have now not only produced a service in OSGi, but also consumed one.  Next, we will learn how to use the Configuration Admin specification of OSGi to dynamically receive configuration updates.

8.  Consuming Configuration Updates.

Once you've learned how to create bundles and register and consume services, I find the next thing most engineers want to learn how to do is pass configuration to there services.  Who can argue with that?  I mean, what's the point of creating highly modular systems if you hard code the configuration those module rely on?

There are a number of ways to configure an OSGi application; here are a couple:

Embed your settings in a property file.

This is somewhat idiomatic for Java.  I mean, it's incredibly simple to call System.getProperty to pull the desired configuration value from the environment.  The Felix container even offers a global properties file you can use to bundle all of this configuration data (conf/config.properties).  In many cases this works if you know what your configuration is going to be before you start the container.

Create and register a configuration service with the OSGi container.

Another option is to create a bundle and some sort of API around configuration.  For instance, you could register a Config object with the container, which is consumed by the service/bundle you need configured.  This adds an interesting benefit because you could prevent a the bundle from activating unless the Config object becomes available.  You can also change the configuration by recompiling the bundle with the Config object and updating the bundle, which should in turn update the dependent service.

Use the OSGi Specification for Configuration Admin.

The Configuration Admin specification for OSGi formalizes the previous notion (services dedicated for configuration) providing a nice model for handling these configuration updates, along with a persistence mechanism that ensure updates remain once they are set.  More importantly, the Configuration Admin service provides hooks for allowing configuration updates without needing to create special configuration bundles.  A service that wants to use the Configuration Admin service merely needs to implement the ManagedService interface.  This interface is made available to us from the org.apache.felix.configadmin artifact we referenced as a dependency in our Maven pom.xml file earlier in the post.

I've taken the liberty to implement the ManagedService interface and its corresponding update method:
package com.berico.timeprovider.internal;

import java.util.Dictionary;
import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;

import com.berico.timeprovider.api.TimeProvider;

public class Activator implements BundleActivator, ManagedService {

  private static ServiceRegistration timeProviderRegistration = null;
  private static ServiceRegistration configRegistration = null;
  private static TimeProvider timeProvider = new TimeProviderImpl();
  
  public void start(BundleContext bundleContext) throws Exception {
    
    // Properties for the TimeProvider registration
    Dictionary registrationProperties = new Hashtable();
    
    timeProviderRegistration = 
      bundleContext.registerService(
        TimeProvider.class.getName(), 
        timeProvider, 
        registrationProperties);  
    
    //Properties for the Config Admin Registration
    Dictionary configProperties = new Hashtable();
    configProperties.put(Constants.SERVICE_PID, "timeprovider.pid");
    
    configRegistration = 
      bundleContext.registerService(
        ManagedService.class.getName(), 
        this, configProperties);
    
    System.out.println("com.berico.timeprovider Started");
    
    printTime();
  }

  public void stop(BundleContext bundleContext) throws Exception {
    
    unregister(timeProviderRegistration, bundleContext);
    
    unregister(configRegistration, bundleContext);  
    
    System.out.println("com.berico.timeprovider Stopped");
  }
  
  public void updated(Dictionary configuration) throws ConfigurationException {
    
    System.out.println("Updating Time Provider Configuration.");
    
    if(configuration != null){
      
      String timezone = configuration.get("timezone").toString();
      
      System.out.println(
          String.format("Changing Time Zone to: %s", timezone));
      
      try {
        
        timeProvider.setDefaultTimeZone(timezone);
      
        printTime();
        
      } catch (Exception e) {
        
        System.out.println(
          String.format(
            "Could not set the provided timezone [%s]; reason: %s", 
            timezone, 
            e.getMessage()));
      }
      
    }
    else {
      
      System.out.println("Time Service: Configuration Null");
    }
  }
  
  private static void unregister(
      ServiceRegistration registration, BundleContext bundleContext){
    
    if(registration != null){
      
      bundleContext.ungetService(registration.getReference());
    }
  }
  
  private static void printTime(){
    
    System.out.println(
      String.format("Current Time: %s", timeProvider.getTime()));
  }
  
}
Now that you've see how we can consume configuration updates, I'm going to demonstrate how to produce an update.  Instead of creating a whole new bundle to make this happen, I'm going to show how to extend the Apache Felix Gogo Shell to serve as a mechanism for updating our timeproducer service.

9.  Writing Menu Extensions for the Apache Felix Gogo shell.

Writing Shell Extensions for the Felix Gogo shell is surprising easy.  Shell commands are actually methods on a POJO, and Gogo does some clever Reflection work to turn those commands into executable actions.

Let's create a simple menu extension that prints the time on command, as well as, sets the default timezone:
package com.berico.timeprovider.internal;

import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;

import org.apache.felix.service.command.Descriptor;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;

import com.berico.timeprovider.api.TimeProvider;

public class ShellCommands {

  private final BundleContext bundleContext;
  private ConfigurationAdmin configAdmin;
  
  ShellCommands(BundleContext bundleContext){
    
    this.bundleContext = bundleContext;
    
    getConfigAdmin();
  }
  
  @Descriptor("Show the current time.")
  public void show(){
    
    ServiceReference timeProviderReference = 
      bundleContext.getServiceReference(
        TimeProvider.class.getName());
    
    TimeProvider timeProvider = 
      (TimeProvider)bundleContext.getService(
        timeProviderReference);
    
    System.out.println(timeProvider.getTime());
  }
  
  @Descriptor("Set the Default Time Zone for the Time Provider")
  public void timezone(
      @Descriptor("Valid Time Zone") 
        String timezone){
    
    System.out.println(
      String.format("Setting Time Zone: %s", timezone));
    
    ServiceReference configurationAdminReference = 
            bundleContext.getServiceReference(
              ConfigurationAdmin.class.getName());  
    
    Configuration config = null;
    
    try {
    
      config = configAdmin.getConfiguration(
              "timeprovider.pid");
      
      Dictionary props = config.getProperties();
      
      if (props == null) {
          props = new Hashtable();
      }

      props.put("timezone", timezone);

      config.update(props);
      
    } catch (IOException e) {
      
      e.printStackTrace();
    }
    
  }
  
  private void getConfigAdmin(){
    
    if(this.configAdmin == null){
    
      ServiceReference configurationAdminReference = 
              this.bundleContext.getServiceReference(
                ConfigurationAdmin.class.getName()); 
    
      if (configurationAdminReference != null) 
          {  
        
              this.configAdmin 
                = (ConfigurationAdmin) 
                  bundleContext.getService(
                    configurationAdminReference);  
          }
    }
  }
}
In this example, the methods show and timezone will serve as the "executables" the OSGi containers call when a command is typed in the Gogo shell.  In the show method, we grab an instance of the TimeProvider instance from the OSGi context and print the current time to the shell.  In the timezone method, instead of retrieving the service directly from the OSGi context, we instead grab a reference to the ConfigurationAdmin service, create a new set of properties for the timeprovider service (we refer to the service using the "pid" of the timeprovider, what I've simply called "timeprovider.pid"), and tell the ConfigurationAdmin service to update the properties for that service.  This will call the update method on our Activator class, which will in turn set the default time zone.

The last thing to mention is the @Descriptor annotation.  This is used by the Gogo shell to provide contextual help for the command.  If the annotation is placed over the method name, the description applies to the command.  If the annotation is on a function argument, it applies to one of the command's parameters.

In order to demonstrate the difference in time zone when we make changes to the default time zone stored within the TimeProvider, I'm going to make a small modification to the TimeProviderImpl.getTime method:
private String getTime(DateTimeZone dtz){
  
  DateTime dt = DateTime.now(dtz);
  
  return dt.toString("ZZZ - yyyy-MM-dd HH:mm:ss");
}
We register the ShellCommands class like any other service in OSGi.  You might be wondering, how does the Felix Gogo Shell know to "pick up" the service after it's registered with the container?  This is another example of when the properties (metadata) provided to the container is useful for service consumption.  Let's modify timeprovider's Activator class to register the ShellCommands service with the container:
//Properties for the Gogo Shell
Dictionary shellCommandsProperties = new Hashtable();
    
shellCommandsProperties.put("osgi.command.scope", "time");
    
shellCommandsProperties.put("osgi.command.function", 
  new String[] {"show", "timezone"});
    
bundleContext.registerService(
  ShellCommands.class.getName(), 
  new ShellCommands(bundleContext), 
  shellCommandsProperties);
Adding the osgi.command.scope and osgi.command.function properties to the service registration will provide the appropriate information to the Felix Gogo plugin to detect and install the ShellCommands instance as a viable addition to the menu.  Using some nifty Reflection, the Felix Gogo service can pull the description of the commands and their parameters from the annotations.  Reading the signature of the method, the Felix Gogo service can determine the number and types of parameters required to execute the function, mapping those parameters onto the particular method instance.

10.  Dynamically configuring a Service using the Gogo shell.

Now we are ready to demonstrate how to dynamically configure a service using Gogo shell.  Before we go any further, it would be wise to uninstall the timeprovider and timeconsumer bundles from the OSGi container, recompile and package them, and place the new versions in the auto-deploy directory of Apache Felix.
Updating Time Provider Configuration.
Time Service: Configuration Null
com.berico.timeprovider Started
Current Time: UTC - 2012-01-24 23:07:37
com.berico.timeconsumer Started
Current Time is UTC - 2012-01-24 23:07:37
____________________________
Welcome to Apache Felix Gogo

g!
Let's first start by seeing if our commands were loaded into the Gogo shell.  We can see a list of commands by typing the "help" command:
g! help
The Felix Gogo Shell will dump a list of commands:
felix:bundlelevel
felix:cd
felix:frameworklevel
felix:headers
felix:help
felix:inspect
felix:install
felix:lb
felix:log
felix:ls
felix:refresh
felix:resolve
felix:start
felix:stop
felix:uninstall
felix:update
felix:which
gogo:cat
gogo:each
gogo:echo
gogo:format
gogo:getopt
gogo:gosh
gogo:grep
gogo:not
gogo:set
gogo:sh
gogo:source
gogo:tac
gogo:telnetd
gogo:type
gogo:until
obr:deploy
obr:info
obr:javadoc
obr:list
obr:repos
obr:source
time:show
time:timezone
g! 
At the bottom you will notice our two commands prefixed by time.  If you recall, time was the osgi.command.scope (think namespace).  Our two methods, registered as an array of Strings with the osgi.command.function key, appear after the scope.

We can inspect the contextual help message of any command by calling help again and supplying the name of the command:
g! help show
Which displays:
show - Show the current time.
   scope: time
And the help message for the timezone command:
g! help timezone
Which displays:
timezone - Set the Default Time Zone for the Time Provider
   scope: time
   parameters:
      String   Valid Time Zone
Keep in mind that you can always prefix a command with it's scope (e.g.: time:timezone; if there isn't another command with the same name, you can remain lazy like me and simply use the command name.

Let's execute the timezone command supplying America/Phoenix (a Joda Time constant) for our new timezone:
g! timezone America/Phoenix
We get a response first from inside our ShellCommands.timezone method notifying us that the timezone is being set, followed by notifications within the Activator.update method indicating it has received new configuration:
Setting Time Zone: America/Phoenix
Updating Time Provider Configuration.
Changing Time Zone to: America/Phoenix
Current Time: America/Phoenix - 2012-01-24 16:11:37
We also have the option to display the time at any time by calling the show command:
g! time:show
Which displays:
America/Phoenix - 2012-01-24 17:49:03

Conclusion


Although this was a very long post, my intent was to provide a complete introduction into creating an OSGi bundle in Maven, registering and consuming services, using the ConfigurationAdmin service, and manipulating the Apache Felix Gogo shell.  In this tutorial, I didn't spend a whole lot of time talking about the theory and mechanics of OSGi.  Thanks for your time and patience!

For an in depth look at OSGi, I recommend the following books:

OSGi in Depth
http://www.manning.com/alves/
OSGi in Action
http://www.manning.com/hall/



Wednesday, January 18, 2012

Modeling Scientific Attributes in Java using JScience


A couple of years ago the Mars Climate Orbiter famously wrecked into Mars's upper atmosphere due to a unit conversion error between two teams of developers (one using English units and the other metric).  The result was the loss of $125m satellite and years of development due to a simple programming snafu [1].  While the problem probably should have been identified during testing, this small mistake highlights the important of domain models, especially in scientific computing.

Working on a side project in the field of "Environmental Intelligence," a shameless attempt for me to utilize my years of Meteorological experience, I found myself spending an exorbitant amount of time writing a domain model that handled the conversion between different types of scientific units for environmental attributes like temperature, pressure, velocity, direction, time, and location.  I also found myself relatively uninspired in how I wanted to actually model these attributes.  Since the intent of this spike was not to reinvent the wheel in modeling the domain, but in fact to write a parser for METAR data, I decided to look online to see if someone had already modeled this domain and had a reasonable set of functions for converting between units.

Much to my surprise, there was an existing library that did exactly what I needed and more.  More importantly, I discovered that this library was actually the "reference implementation" for a JSR (275) regarding the use of "Units and Measures" in Java.  

Meet JScience.  JScience is a humble little library for scientific and mathematical computations on the JVM.  JScience (http://jscience.org/) is powered by the Javolution (http://javolution.org/) a library for building real-time systems.  JScience hides the complexity of modeling environmental attributes and dealing with unit conversions allowing you to get to the core problems in your domain.

In this post, I will demonstrate the basics of using JScience in your application.

For those using Maven, for some reason, JScience hasn't made it into the Maven Central Repository.  Funny enough, I found an instance of JScience 4.3 being hosted out of the JCurl ("Olympic sport of Curling") repository.  So, thank you maintainers of JCurl for making my life easier!  If you want to use geospatial units, you will also need to include the Geotoolkit repository as well.

The following is the repository configuration in your Maven pom.xml file.

<repositories>
  <repository>
    <id>geotoolkit</id>
    <name>Geotoolkit repository</name>
    <url>http://maven.geotoolkit.org</url>
  </repository>
  <repository>
    <id>jcurl</id>
    <name>JCurl Library</name>
    <url>http://jcurl.berlios.de/m2/repo</url>
  </repository>
</repositories>

Here are the dependencies required to use JScience (also in the pom.xml file):

<dependencies>
  <dependency>
    <groupId>org.jscience</groupId>
    <artifactId>jscience</artifactId>
    <version>4.3.1</version>
  </dependency>
  <dependency>
    <groupId>javolution</groupId>
    <artifactId>javolution</artifactId>
    <version>5.4.5</version>
  </dependency>
  <dependency>
    <groupId>org.opengis</groupId>
    <artifactId>geoapi-pending</artifactId>
    <version>2.3-RC1</version>
  </dependency>
</dependencies>

Update your Maven dependencies and you should be set to use all of JScience's units and measures, including the geospatial constructs.

Let's start by demonstrating some really naive code from a domain modeling standpoint.  I have the requirement to deliver the daily maximum and minimum temperatures to my users on a website, so perhaps I create a DailyMaxMin class to represent this data structure.

public class DailyMaxMin {

  protected double minimumTemperature = Double.MIN_VALUE;
  
  protected double maximumTemperature = Double.MIN_VALUE;

  public DailyMaxMin(){}
  
  public DailyMaxMin(double minimumTemperature, double maximumTemperature) {

    this.minimumTemperature = minimumTemperature;
    this.maximumTemperature = maximumTemperature;
  }

  public double getMinimumTemperature() {
    
    return minimumTemperature;
  }

  public void setMinimumTemperature(double minimumTemperature) {
    
    this.minimumTemperature = minimumTemperature;
  }

  public double getMaximumTemperature() {
    
    return maximumTemperature;
  }

  public void setMaximumTemperature(double maximumTemperature) {
    
    this.maximumTemperature = maximumTemperature;
  }
  
}

Ok, if we learned anything from the anecdote about the Mars Climate Orbiter, it's that we need to be specific about the type of temperature we are working with.  Carrying around these primitives was the problem they ran into.

Weather guys deal a lot with temperatures.  We have ambient air temperature (which you normally would call "the temperature") and dew point temperatures, but we also deal with "wet bulb temperatures", "heat indexes", "globe temperatures", "potential temperature", etc.  Since all are measured in the same way, some form of temperature unit, we will create a convenient little class for them:

public class Temperature {

  protected double valueAsCelsius = Double.MIN_VALUE;
  
  public Temperature(){}
  
  public Temperature(double celsiusValue){
    
    setValue(celsiusValue);
  }
  
  public void setValue(double celsiusValue){
    
    this.valueAsCelsius = celsiusValue;
  }
  
  public double getValue(){
    
    return this.valueAsCelsius;
  }
  
}

Like I said, this class is naive from a domain modeling standpoint, and is just as bad as simply using a primitive in the aggregate's parent class to represent a temperature value (like we did in the DailyMaxMin class).  For instance, what keeps another developer from giving us the temperature in Fahrenheit?  We must trust that other developers will see that we named the parameter in the 'setter' "celciusValue".  Not exactly the best practice from a "defensive programming" perspective.

We will mature this example by adding some guards that ensure the Temperature class is as intended:

public class Temperature {

  public enum Units {
    Celsius,
    Fahrenheit
  }
  
  protected double valueAsCelsius = Double.MIN_VALUE;
  
  public Temperature(){}
  
  public Temperature(double value, Units unit){
    
    setValue(value, unit);
  }
  
  public void setValue(double value, Units unit){
  
    if(unit == Units.Celsius){
      
      this.valueAsCelsius = value;
    }
    else {
      
      this.valueAsCelsius = fahrenheitToCelsius(value);
    }
  }
  
  public double getValue(Units unit){
    
    if(unit == Units.Fahrenheit){
      
      return celsiusToFahrenheit(this.valueAsCelsius);
    }
    
    return this.valueAsCelsius;
  }
  
  public static double celsiusToFahrenheit(double celsius){
  
    return celsius * 9d / 5d + 32;
  }
  
  public static double fahrenheitToCelsius(double fahrenheit){
  
    return (fahrenheit - 32) * 5d / 9d;
  }
}

Now we have an enum of Temperatures and we force developers to specify what unit the value was measured in.  This kind of works.  The problem is, we are forced to continuously refactor this class every type a new unit of measurement is added to the system.  For instance, what if you get the requirement to immediately include both Kelvin and Rankine to your model?  You could expand the number of labels in the Units enumeration and modify the getters and setters to use some sort of switch statement.  Probably the better alternative would be to develop a more complex model to elegantly represent your units of measure.

For the sake of argument, let's pretend that using our Temperature class was the route we chose to pursue.  Let's modify the DailyMaxMin class to represent our new way of handling temperatures.

public class DailyMaxMin {

  protected Temperature minimumTemperature = null;
  
  protected Temperature maximumTemperature = null;

  public DailyMaxMin(){}
  
  public DailyMaxMin(
      Temperature minimumTemperature,
      Temperature maximumTemperature) {

    this.minimumTemperature = minimumTemperature;
    this.maximumTemperature = maximumTemperature;
  }

  public Temperature getMinimumTemperature() {
    
    return minimumTemperature;
  }

  public void setMinimumTemperature(Temperature minimumTemperature) {
    
    this.minimumTemperature = minimumTemperature;
  }

  public Temperature getMaximumTemperature() {
    
    return maximumTemperature;
  }

  public void setMaximumTemperature(Temperature maximumTemperature) {
    
    this.maximumTemperature = maximumTemperature;
  }
  
}

We've just went through a lot of trouble to get a simple class to carry a more robust representation of maximum and minimum temperatures.  If you had to deal with more than just temperatures (like all the other factors in weather: wind, pressure, precipitation, etc.), you will find yourself spending months writing tedious model code to represent the simpler concepts in your application.

JScience addresses this problem through a highly-flexible Generics-based model.  The model is centered around the Measurable<Q extends Quantity> interface.  Quantity is a "marker interface" (an interface with no behavior [e.g.: no methods]) which is extended by the types of physical attributes we would want to work with in a scientific applications (temperature, force, pressure, power, money, mass, energy, etc.).

We can create concrete instances of Measurable objects using static factory methods provided by the JScience Amount class. 

import javax.measure.Measurable;
import javax.measure.quantity.Temperature;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Length;
import javax.measure.quantity.Velocity;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;

import org.jscience.physics.amount.Amount;

//...

double temperatureAsDouble = 42.0d;

Measurable<Temperature> temperature 
    = Amount.valueOf(temperatureAsDouble, SI.CELSIUS);

double pressureAsDouble = 1013.2d;

Measurable<Pressure> pressure 
    = Amount.valueOf(pressureAsDouble, SI.MILLI(NonSI.BAR));

long lengthAsLong = 10l;

Measurable<Length> length 
    = Amount.valueOf(lengthAsLong, NonSI.FOOT);

long velocityAsLong = 15l;

Measurable<Velocity> velocity 
    = Amount.valueOf(velocityAsLong, NonSI.KNOT);

In the following example, we are using the Amount.valueOf method to create instances of measurable objects of various types of Quantity by providing either a long or double value and the corresponding Unit of measure.  One interesting variation you might notice with the pressure example is the clever use of the Decorator pattern, where SI.MILLI is used to magnify the quantity of the NonSI.BAR measurement, to effectively create Millibars (the standard unit of measure for atmospheric pressure used in meteorological models and products).  For those that didn't get the reference, SI refers to the standard scientific unit of measurement, while NonSI is the grouping for everything else.

Extracting values from Measurable objects is equally simple.

import javax.measure.Measurable;
import javax.measure.quantity.Temperature;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Length;
import javax.measure.quantity.Velocity;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;

import org.jscience.physics.amount.Amount;

//...

Measurable<Temperature> temperature 
    = Amount.valueOf(42.0d, SI.CELSIUS);

double tempFahrenheit = temperature.doubleValue(NonSI.FAHRENHEIT);
double tempRankine = temperature.doubleValue(NonSI.RANKINE);
double tempKelvin = temperature.doubleValue(SI.KELVIN);

Measurable<Pressure> pressure 
    = Amount.valueOf(1013.2d, SI.MILLI(NonSI.BAR));

double pressureInchesOfMercury = pressure.doubleValue(NonSI.INCH_OF_MERCURY);
double pressureAtmospheres = pressure.doubleValue(NonSI.ATMOSPHERE);

Measurable<Length> length 
    = Amount.valueOf(10l, NonSI.FOOT);

long lengthMiles = length.longValue(NonSI.MILE);
long lengthMeters = length.longValue(SI.METER);
long lengthYards = length.longValue(NonSI.YARD);

Measurable<Velocity> velocity 
    = Amount.valueOf(15l, NonSI.KNOT);

long velocityMetersPerSecond = velocity.longValue(SI.METERS_PER_SECOND);
long velocityMilesPerHour = velocity.longValue(NonSI.MILES_PER_HOUR);
long velocityKilometersPerHour = velocity.longValue(NonSI.KILOMETERS_PER_HOUR);

So to wrap this up, JScience offers a nice open source alternative to the code intensive practice of writing those model objects yourself.  Do yourself a favor and start replacing those scientific primitives with Measurable objects:

public class DailyMaxMin {

  protected Measurable<Temperature> minimumTemperature = null;
  
  protected Measurable<Temperature> maximumTemperature = null;

  public DailyMaxMin(){}
  
  public DailyMaxMin(
      Measurable<Temperature> minimumTemperature,
      Measurable<Temperature> maximumTemperature) {

    this.minimumTemperature = minimumTemperature;
    this.maximumTemperature = maximumTemperature;
  }

  public Measurable<Temperature> getMinimumTemperature() {
    
    return minimumTemperature;
  }

  public void setMinimumTemperature(
    Measurable<Temperature> minimumTemperature) {
    
    this.minimumTemperature = minimumTemperature;
  }

  public Measurable<Temperature> getMaximumTemperature() {
    
    return maximumTemperature;
  }

  public void setMaximumTemperature(
    Measurable<Temperature> maximumTemperature) {
    
    this.maximumTemperature = maximumTemperature;
  }
  
}

There's a little more, but not much, to the JScience package.  Probably the thing I love the most about the framework is how absolutely simple it is.  If you are doing any scientific or mathematical computing in Java, I highly recommend this library.  Need a better reason?  NASA could provide you a 150 million why.


Works Cited:

[1].  CNN Tech.  "NASAs metric confusion caused Mars Orbiter loss."  Sept 30, 1999. Retrieved Jan 18, 2012 from http://articles.cnn.com/1999-09-30/tech/9909_30_mars.metric_1_mars-orbiter-climate-orbiter-spacecraft-team?_s=PM:TECH.

Monday, January 16, 2012

Top 10 Technologies I Want My Software Engineers to Know In 2012

I now have the Top 10 Technologies of 2013 posted here:
http://www.gettingcirrius.com/2013/01/top-10-technologies-i-want-my-software.html



As the Chief Engineer of Berico Technologies, one of my responsibilities is to push adoption of technologies I feel are essential to enhancing productivity or delivering value to our customers.  Over the last two years, I’ve evaluated hundreds of technologies; this is my short-list of what I consider the most valuable for our engineers to know in the year 2012:
  1. Hadoop + HBase
  2. Spring Framework
  3. Ruby on Rails
  4. Redis
  5. CoffeeScript
  6. OSGi
  7. RabbitMQ
  8. Lucene + Solr
  9. Node.js
  10. A new JVM Language
And here is my rationale:


1.  Hadoop + HBase:  if this isn’t obvious, you probably don’t work in IT.  Hadoop is the platform for storing and processing “cloud-scale” data, but that’s not the only reason why I want my engineers to learn it.  In my opinion, the most important aspect of Hadoop is that it provides a framework for the concurrent processing of data.  I know of a number of projects that have rolled their own concurrent processing frameworks, most of which turned out to be utter failures.

In addition to Hadoop, I find it essential for engineers to know how to use, and intimately understand, HBase. HBase is capable of scaling into the Petabyte range without sacrificing those low-latency read and writes.  HBase has an extremely flexible API and can do a lot of things (not all) you can do in a RDBMS. If you have the time, I highly recommend picking up Lars George’s HBase: The Definitive Guide.

 Apache Hadoop:  http://hadoop.apache.org/
 Apache HBase:  http://hbase.apache.org/
2.  Spring Framework:  even though Spring is sooooo 2003, there are still some Java developers who choose to roll their own configuration frameworks and manually instantiate their object graph.  In general, I consider not using an IOC/DI framework as an interview “turn off”, because it is a clear sign of immature software development practices.

What I really want my engineers to understand is that the Spring Framework is more than just an IOC.  Spring Java contains a bunch of really useful tools to help engineers produce and consume Web Services, interact with databases, perform batch processing, employ AOP, and integrate services like an ESB.

* For our .NETers, I actually recommend users steer clear of Spring.NET.  Spring.NET is great for Java developers migrating to .NET who are already familiar with Spring Java.  Spring.NET would not be my first pick for an IOC container in .NET, because it does not follow a lot of the .NET idioms (feels a little unnatural).  Instead, we recommend the Castle Windsor stack.

 Spring Framework:  http://www.springsource.org/


3.  Ruby on Rails:  while certainly not a new technology, having just jumped headlong into Ruby myself, I’ve had the benefit to learn the framework that has deeply inspired so many other MVCs.  Having used other non-Ruby MVC frameworks (ASP.NET MVC 3 and Spring MVC), I find that none compare to the power of Rails.  Probably one of the greatest surprises for me was the amazing ActiveRecord framework.  Needless-to-say, I’ve been emphasizing the use of Rails since I believe it provides a sustainable platform for rapidly developing web applications.  Add in JBoss TorqueBox, an integration framework for running Ruby apps (like Rails) on JBoss (via JRuby), and you have access to all the power and functionality of the JVM!

 Ruby on Rails:  http://rubyonrails.org/
 TorqueBox:  http://torquebox.org/


4.  Redis:  Redis is an extremely fast key-value store that can also be used as a cache, pub-sub delivery system, and global key incrementation-mechanism (if you need to do counting or globally manage keys).  Redis is also capable of performing set operations including intersections on multiple key-value pairs.  Redis is my go-to technology when I need to cache objects or manage counters.

 Redis:  http://redis.io/

5.  CoffeeScript: I want to first make the point that CoffeeScript wouldn’t be important if we didn’t highly value JavaScript.  When I first learned about CoffeeScript, I admit I was skeptical.  I’m probably one of the few people who actually like JavaScript in its native form.  On the insistence of one my engineers, I decided to look into CoffeeScript and immediately discovered its value.  What blew me away immediately was how concise CoffeeScript was.  JavaScript itself is concise; I already felt like I can accomplish a lot in a short amount of code, but CoffeeScript makes my JavaScript feel bloated!  For productivity reasons, in addition to making JavaScript easier to read and sometimes faster on execution, CoffeeScript has become one of my emphasized technologies for this year.

 CoffeeScript:  http://coffeescript.org/


6.  OSGi:  Open Services Gateway Interface is a specification for packaging Java libraries, as well as, a service model and runtime for applications.  OSGi provides many of the features developers will admit are missing in the Java Packaging System and the J2EE specifications.  Spring has closely aligned its platform to OSGi, and there is growing support for the specification.

OSGi is important to us because it provides the consistent application structure missing in pure (non-web) Spring applications.  OSGi is also not so heavy that it is reminiscent of EJB.  In the future, it is my goal that all of our Java-based applications be written as OSGi bundles.

 OSGi Alliance:  http://www.osgi.org/
 Apache Felix:  http://felix.apache.org/
 Eclipse Equinox (RT):  http://eclipse.org/equinox/


7. RabbitMQ:  I’m astonished how overused web services have become.   There are scenarios where a REST or SOAP service is appropriate, but these technologies are not the only way to communicate in software architectures.  In fact, if you do your research, you will find that many of the giants in cloud computing have found or created higher-performance alternatives.  Probably one of the greatest travesties in the technology realm in the early 2000’s was the de-emphasis of messaging systems.  In many respects, we are rediscovering a technology that has been around for decades.  This is in part due to the adoption of the AMQP specification, which is a platform agnostic way to do messaging.

When we do AMQP, RabbitMQ is our broker implementation of choice for many reasons: security, scalability, stability, and maturity as a product.  We like RabbitMQ so much that it has become the foundation of our Event Driven Architecture platform called Reactive.

 RabbitMQ:  http://www.rabbitmq.com/

8.  Lucene/Solr:  when it comes to search, it seems like everything is a derivative of or inspired by Lucene.  But what most engineers don’t realize is that Lucene is not just for full-text indexing of news articles or websites.  If you want your users to be able to search the content of your forums, or documents uploaded your website, Lucene can make this happen.  Recent versions of Lucene include support for the indexing of geospatial content and numbers (meaning you can perform range-based searches for all sorts of content). For those who don’t know, Solr is the “enterprise wrapper” around Lucene.  Solr essentially adds the features you would need to implement to make Lucene useful in your architecture (like RESTful access to Lucene’s search and indexing functionality).

Building an application nowadays without basic search functionality is like building a car without side-view mirrors; you probably could get away with it, but you’ll upset your users in the process.  For this reason, practical knowledge of Lucene/Solr is considered vital in 2012.

 Lucene:  http://lucene.apache.org/
 Solr:  http://lucene.apache.org/solr/
9.  Node.js:  of all the technologies listed, this is probably my favorite.  Node.js is an event-driven I/O framework built on Google’s V8 engine.  What does that mean?  In short, Google’s extremely fast (sometimes faster than C++ code) JavaScript runtime was given the functionality to perform input/output operations on the file system and network.  With these capabilities, Node.js has made JavaScript a viable server-side alternative to traditional application service platforms written in Java, .NET, Ruby, PHP, and Python.  Why is server-side JavaScript important?  We now live in an era where one language can be used from start-to-finish in building web applications.  That’s one codebase shared between the server and browser.

The Node.js ecosystem is flourishing much like Ruby’s did a couple of years ago (not to say that Ruby’s has curtailed), and the adoption of the technology by major companies (Microsoft, Yahoo, Google, LinkedIn, EBay, to list a few) is a sign of where it will be in the next few years.  Simply put, if you are not learning Node.js now, you are already behind.

 Node.js:  http://nodejs.org/

10.  A New JVM Language:  if you are content with the Java language, in my very humble opinion, you are probably not that interested in writing software.  Java had a great run, taking enterprise computing to a new level.  But while the JVM has improved, the language has stagnated.  I can’t help but wonder what Java would look like if Sun weren’t as focused on being backwards compatible with the “dinoware” written on the platform 12 years ago.  In many respects, it should have looked a lot like what C# does today.

Even though Java has a roadmap for language improvement, we don’t have to wait to take advantage of new syntax on the JVM.  Languages like JRuby and Jython have been around for a while and are proven alternatives to Java.  There are even newer languages that show a lot of promise: Scala, Clojure, Groovy, Ceylon, and Kotlin.  There is no reason to abandon the JVM platform to become more productive, which is why I want my engineers to learn a Java alternative.

 Ceylon:  http://ceylon-lang.org/
 Clojure:  http://clojure.org/
 Kotlin:  http://confluence.jetbrains.net/display/Kotlin/Welcome
 JRuby:  http://jruby.org/
 Jython:  http://www.jython.org/
 Scala:  http://www.scala-lang.org/
 Groovy:  http://groovy.codehaus.org/