Retrieving Typed Configuration with Commons Configuration

Typed configuration is very straightfoward with Commons Configuration. One of my pet peeves is having to translate numeric configuration parameters from String instances to the corresponding primitive type. The following example loads configuration from the test.properties file:

       // import the necessary classes...
      import java.net.URL;
      import org.apache.commons.configuration.Configuration;
      import org.apache.commons.configuration.ConfigurationFactory;

      // Load your configuration from the classpath...
      Configuration config = new PropertiesConfiguration( "test.properties" );
   
      // Retrieve configuration parameters
      float timeout = config.getFloat("timeout"));
      String region = config.getString("region"));
      String name = config.getString("name"));
      int speed = config.getInt("speed"));

The test.properties file has the format of a standard Java properties file, with a key and value on each new line:

       timeout=12000.22
      region=Paris
      name=This is an Example
      speed=55

If you need to convert to an Object instead of a primitive, you’ll need to supply a default value to be used if the configuration parameters is not available. For example, the following code would set timeout to Float.NaN and speed to 0 if these parameters were not present in the specified properties file.

       Float timeout = config.getFloat( "timeout", Float.NaN );
      Integer speed = config.getInteger( "speed", new Integer( 0 ) );

commons-scxml and state machines

Commons SCXML is a new component in the Commons Sandbox that intends to implement a state machine representation and execution framework as deifned in the State Chart XML (SCXML): State Machine Notation for Control Abstraction 1.0 Working Draft. As this component attempts to collect itself before promotion to Commons proper, anyone interested in this subject should take a look at this component.

Codec Soundex Bug Fix

There was a trivial bug fixed in Commons Codec that affected the Soundex class. If you tried to use the static US_ENGLISH instance, you ran into problems. For example:

String code = Soundex.US_ENGLISH.soundex("Smith");

Was throwing a NPE because of the ordering of the static variables in the Soundex class. The problem was addressed by reordering the statics and adding a unit test donated by the person who identified this bug.

Credit to Reggie Riser for identifying this defect.

My article (The Hidden Gems of Jakarta Commons, Part 1) is linked to from Charles Ditzel’s Java Technology Pointers over at the Sun Developer Network.

My article (The Hidden Gems of Jakarta Commons, Part 1) is linked to from Charles Ditzel’s Java Technology Pointers over at the Sun Developer Network. Cool. Now if I could just manage to find the time to write Part 2 of that three part series…

"Filtering Collections with JXPath or JEXL"

There was another interesting question on the commons-user list today. Someone asked about using Commons JEXL to filter the contents of a Collection. There are an almost infinite number of ways to do this, but two ways pop to mind: using Commons JXPath to filter a Collection and writing a custom JexlPredicate to apply an arbitrary JEXL expression to a Collection using CollectionUtils from Commons Collections.

To demonstrate both methods, assume that you have a collection of Person objects that you created with the following code. Each Person object has two properties name and age.

       Person person1 = new Person();
      person1.setName( "Bill" );
      person1.setAge( 12 );

      Person person2 = new Person();
      person2.setName( "Amy" );
      person2.setAge( 18 );

      Person person3 = new Person();
      person3.setName( "Doug" );
      person3.setAge( 25 );

      List personList =
          Arrays.asList( new Person[] { person1, person2, person3 } );

You can filter this collection using JXPath and an XPath expression that references the age property AS IF it were an XML attribute. Create a new JXPathContext by passing the Collection to the static newContext() method. Then pass an XPath expression to the iterate() method. This will select all objects which match the XPath expression – ".[@age >= 18]". This is an unorthodox use of XPath syntax, but it works well.

       JXPathContext context = JXPathContext.newContext( personList );
      Iterator iterator = context.iterate(".[@age >= 18]");
      while( iterator.hasNext() ) {
          Object o  = (Object) iterator.next();
          System.out.println( "Person: " + ((Person) o).getName());
      }

If you don’t feel comfortable writing XPath expression to filter your objects, you can use Commons JEXL with Commons Collections and write a custom JexlPredicate that takes an expression and evaluates each element in a Collection. Here’s code that filters a collection of Person beans and returns only those instances that have an age >= 18. Note how the selection logic is encapsulated in a Predicate object which is applied to each element of a Collection through a call to CollectionUtils.select().

      Predicate predicate = new JexlPredicate( "object", "object.age >= 18" );
     Collection canVote = CollectionUtils.select( personList, predicate );

     // Using Java 1.5 syntax because I am very lazy....
     for( Object o : canVote ) {
          System.out.println( "Person: " + ((Person) o).getName() );
     }

The JexlPredicate from this example would be the following class. I not terribly happy with the lack of error handling, but it does work.

import org.apache.commons.collections.Predicate;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.commons.jexl.JexlHelper;

public class JexlPredicate implements Predicate {

  private String variable;
  private Expression e;

  public JexlPredicate(String variable, String expression) {
      this.variable = variable;
      try {
          this.e = ExpressionFactory.createExpression(expression);
      } catch (Exception e) {
          throw new RuntimeException("Error creating JEXL expression", e);
      }
  }

  public boolean evaluate(Object o) {
      JexlContext jc = JexlHelper.createContext();
      jc.getVars().put(variable, o);
            Boolean b;
      try {
          b = (Boolean) e.evaluate(jc);
      } catch (Exception e) {
          throw new RuntimeException("Error evaluating JEXL expression", e);
      }
      return b.booleanValue();
  }

}

There are a few more thing that could be done, you could modify the JexlPredicate to take a JexlContext in the constructor and call methods in a JEXL expression. There are actually a few more ways to do this, but for now, that’s all…

"Creating a Bounded/Ordered/No-duplicates Collection"

There was a good question on the commons-user list today about how to create a data structure to hold a list of items you have visited recently on a catalog site. I advised the use of either a Predicated CircularFifoBuffer or a LRUMap. The LRUMap is certainly easier, but the Predicated CircularFifoBuffer is more fun. Here’s the code for the LRUMap solution:

  import java.util.Iterator;
 import java.util.Map;

 import org.apache.commons.collections.map.LRUMap;

 // ...snip...
 public static void main(String[] args) {

   Map map = new LRUMap(5);

   map.put( "Page 1", "" );
   map.put( "Page 2", "" );
   map.put( "Page 3", "" );
   map.put( "Page 4", "" );
   map.put( "Page 5", "" );
   map.put( "Page 6", "" );
   map.put( "Page 7", "" );
   map.put( "Page 8", "" );
   map.put( "Page 9", "" );
   map.put( "Page 9", "" );
   map.put( "Page 1", "" );

   Iterator i = map.keySet().iterator();
   while (i.hasNext()) {
   String value = (String) i.next();
   System.out.println(value);
   }

This will print out “Page 1, Page 9, Page 8, Page 7, Page 6”. So, it ignored the duplicate 9 at the end of the list and it returned a series of keys from Most Recently Used to Least Recently Used. The Map takes care of key uniqueness, and the LRUMap discarded the Least Recently Used entries as it needed to.