August 30, 2007

Are your Java projects misusing java.text.Format?

As a consultant with ThoughtWorks I get the opportunity to see many different code bases at a variety of client. A common mistake I see again and again is that developers do not realize that sub-classes of java.text.Format (e.g. NumberFormat, SimpleDateFormat) are not thread safe. If your project defines a static instance of a formatter, like so:
public static final SimpleDateFormat SIMPLE_DATE_FORMAT 
= new SimpleDateFormat("MM-dd-yyyy");

Then chances are you have a bug.

As is the case with many threading issues, this might not be easily identified because it probably doesn't happen consistently (we are at the mercy of the Thread Scheduler).

Recently on a project I created a test to prove that using such Formats can cause problems. We then fixed the issue and decided to keep the test in the code base to ensure that no developers 'accidentally' re-introduces it. NOTE: A Continuous Integration server, CruiseControl, ensures that our tests are run continuously.

Below is a simple, self-contained, test you can use to see the issue for yourself. Remember that the test might not fail every time because it is dependent on how the threads are scheduled. I have found that the test fails with more consistency when executed a single CPU (or single-core) machine.

import junit.framework.TestCase;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadSafetyTest extends TestCase {
private static final SimpleDateFormat FORMAT
= new SimpleDateFormat();

public void testSimpleDateFormat() throws InterruptedException {
for (int i = 0; i < 50; i++) {
MyRunnable[] runnables = {
new MyRunnable(new Date(-1)),
new MyRunnable(new Date(1))
};

Thread one = new Thread(runnables[0]);
Thread two = new Thread(runnables[1]);

one.start();
two.start();

one.join();
two.join();

assertFalse("Values should not be equal",
runnables[0].value.equals(runnables[1].value));
}
}

private static class MyRunnable implements Runnable {
private Date date = null;
public String value = null;

MyRunnable(Date date) {
this.date = date;
}

public void run() {
value = FORMAT.format(date);
}
}
}

August 29, 2007

Argible: testing argible-ized actions

Last week Jay Fields and I were discussing Argible and he asked, "How's testing an action that uses Argible?", the answer ... easy.

Suppose we have the following Controller with an argible-ized action:

class CalculatorController < ApplicationController

argible(:first => :to_i, :second => :to_i)
def add(first, second)
@result = first + second
end

end

And here is the associated RSpec test:

describe CalculatorController, "add action" do
controller_name :calculator

it "should add argument values" do
post :add, :first => "18", :second => "2"
controller.instance_variable_get(:@result).should == 20
end

end

You can see from the test that you do not need to do anything special to test your argible annotated action methods. Just call the action with whatever parameter name and values your action requires.

August 22, 2007

Blogger.com: unable to edit a post without publishing

Today I went back through my blog and added some labels (aka tags) to older posts. Soon afterwards I realized that adding these labels forced those post to be re-published. I found this annoying because visitors to sites like ThoughtBlogs would now have to sift through this "noise", obscuring the most recent post I'm most interested in sharing.

I think Blogger.com should provide a way to make minor edits to previously published posts without forcing these posts to be re-published. I understand that WordPress offers this functionality (right?). Is there a way this can be done that I might have missed? Or would I need to wait for such functionality to be introduced? Maybe it'll be easier if I just move my blog WordPress?

Argible: automatically set instance variables

As I discussed in my last post Argible makes it easy to resolve method argument values through simple convention. Peter Ryan had an excellent idea of using Argible to automatically set an instance variable's value through simple convention. Have a look at the example below:

class MyController < ApplicationController

argible(:foo => :@bar)
def action_one
p "Bar instance variable was set to: #{@bar}"
end

end

Notice that the action method, action_one, has NO arguments. But the argible annotation was passed :foo => :@bar. Argible will interpret that you want the resolved value of 'foo' to be set upon the instance variable named '@bar'. This happens because the symbol on the right hand side is prefixed with the character '@'. Without this Argible will raise an Error informing you that there is no such argument.

August 20, 2007

Introducing Argible: Simplifing your Ruby on Rails Controllers

Argible is a RubyForge project that was created to simplify Action methods within your Ruby on Rails Controllers. Argible annotated action methods will allow your Actions to define argument. These argument names will be used in conjunction with request parameters to automatically resolve these argument values. Have a look at the FoobarController code below:

class FoobarController < ApplicationController

argible
def action_one(alpha)
...
end

argible(:date => Date.method(:parse))
def action_two(date)
...
end

argible(:date => lambda {|v| Date.parse(v) } )
def action_three(date)
...
end

argible(:value => :to_i)
def action_four(value)
...
end
end

The first method action_one(alpha) is annotated with the method argible. When the action_one method is executed Argible will intercept the call and look up the request parameter value associated with alpha. Next the action_one method will be called with this resolved value.

The second action, action_two(date), provides an example of how more complex processing can occur on argument values. As in the first example the argument, this time named date, is resolved against the request parameters. The resulting value will then be passed to the Date#parse method. The result from Date#parse will then be used when action_two is called. **NOTE: any method can be used, Date#parse is simply used as an example.

The action action_three(date) provides an example of using a Proc (lambda) as alternative to a named method.

The fourth example action action_four(value) illustrates how you can call methods directly on the string value returned from
the request parameter.

Argible 0.1.0 is available for immediate use from http://rubyforge.org/projects/argible. RDoc can be found at http://argible.rubyforge.org.