Thursday, March 26, 2009

ARM Blocks in Scala: Revisited

Over a year ago, when I was new to Scala, I tried implementing Automatic Resource Management. I was not pleased with the result, so I ended up recommending ManagedResource from Scalax. After I came across a couple of links to my original post, I decided to point out a different approach that I have seen which seems to work well and appeals to me, personally.

Next, I'll try to figure out where I went wrong originally, but those who are only interested in the new approach can skip the next section.

Unnecessary Complication
One of my original goals was to allow multiple resources per block. This ended up making the implementation much more complicated, especially with regard to exception handling. Also, in my first approach I included an exception handling mechanism which turns out to be unnecessary if we're only dealing with one resource at a time. The biggest problem with my first attempt, however, was that the resource had to be initialized outside of the ARM block, which, when multiple resources are initialized, can lead to the very resource leaks which we are trying to avoid. It was a good effort, however, if I do say so myself, and helped me to learn the language a bit.

A Simpler Approach
Lucky for me, Scala's first expert, Martin Odersky, also thought ARM was a good example of the flexibility of the language. I don't know when he started using ARM in his talks, but the first time I saw it was at JavaOne 2008, and then again at the Scala Lift Off event the following weekend. I will not re-post Odersky's implementation here without his permission (not that I think he would object), but I recommend that you take a look at slide 21 of his FOSDEM 2009 presentation (which was hopefully posted with his permission).

Odersky's approach is much more elegant. It only allows a single resource to be managed per block, which is actually all you need since ARM blocks can be nested to support multiple resources. Exceptions are not caught so that the caller can handle them properly. Simplicity. This ends up being very similar to the approach that C# has taken, so he chose to name the method the same as the C# "using" keyword.

Here's how you use it:


//print a file, line by line
using(new BufferedReader(new FileReader("test.txt"))) {
reader => {
println(reader.readLine)
}
}

//copy a file, line by line
using(new BufferedReader(new FileReader("test.txt"))) {
reader => {
using(new BufferedWriter(new FileWriter("test_copy.txt"))) {
writer => {
var line = reader.readLine
while (line != null) {
writer.write(line)
writer.newLine
line = reader.readLine
}
}
}
}
}


I actually like this approach better than the ManagedResource from Scalax because the syntax feels more natural; it feels like you are using a language feature. I always thought ManagedResource was a bit strange because it felt like an abuse of the for-comprehension, but that's just my opinion.

Since I hadn't seen anyone point out Martin Odersky's "using" implementation, I thought I would post about it. I think ARM is great and the fact that it can be implemented as a library in Scala is phenomenal.

If we're lucky, Java SE 7 will have ARM thanks to Project Coin, but it's getting more and more obvious these days that Java is not progressing as a language. Now if only I could do my everyday coding in Scala....

Wednesday, January 7, 2009

Introducing Pojomatic

New year, new project
I'd like to start off the new year by introducing a project I've been working on for a while now along with Ian Robertson, a colleague of mine at Overstock. The project itself is actually not new at all, considering we began working on it around April of last year and it's based on something similar we've been using internally at Overstock since the early days of Java 1.5. The project is called Pojomatic, and what's new is that it's open source (Apache 2.0 license) and there's a release candidate available (1.0-RC1) on Sourceforge or the Maven central repository.

What does it do?
Pojomatic is a Java library which provides automatic and configurable implementations of the hashCode() equals(Object) and toString() methods inherited from java.lang.Object using annotations. POJOs (Plain Old Java Objects) + automatic implementations of common methods = Pojomatic.

This is a useful because it is generally a good idea to override hashCode() equals(Object) and sometimes toString(). One could manually implement these methods, but that is time-consuming and prone to error (e.g. forgetting to check for null everywhere). Instead, one could have an IDE generate implementations of these methods for you. As with a lot of generated code, this can be like slapping your code with an ugly stick. Besides, I'd often add fields and/or methods to the class later and forget to re-generate new implementations, which may have no effect or may lead to very subtle, hard to detect bugs (e.g. two objects are equal when they shouldn't be => two different people mistaken for the same person => money is deposited to the wrong account => one person is happy, while you are not because you have to work late to track down and fix the bug).

How do I use it?
The easiest way to use Pojomatic is to put one annotation (@AutoProperty) on your class and delegate the desired method(s) to the corresponding static methods in Pojomatic. For example:
@AutoProperty
public class Person {
private final String firstName;
private final String lastName;
private final int age;

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

public String getFirstName() {
return this.firstName;
}

public String getLastName() {
return this.lastName;
}

public int getAge() {
return this.age;
}

@Override public int hashCode() {
return Pojomatic.hashCode(this);
}

@Override public String toString() {
return Pojomatic.toString(this);
}

@Override public boolean equals(Object o) {
return Pojomatic.equals(this, o);
}
}

By default, @AutoProperty tells Pojomatic to automatically detect all of your fields and use them in all of the Pojomatic.* methods. We'll see the different options later, but in the above example, all of the fields will be used for hashCode() equals(Object) and toString() as shown here:
public static void main(String[] args) {
Person johnDoe = new Person("John", "Doe", 32);
System.out.println(johnDoe.hashCode());
System.out.println(johnDoe.equals(new Person("John", "Doe", 32)));
System.out.println(johnDoe.toString());
}

Outputs:
-2068529904
Person{firstName: {John}, lastName: {Doe}, age: {32}}
true

Using all fields for each of hashCode() equals(Object) and toString() is usually not advised, however, so @AutoProperty can be configured to include automatically detected properties in any (valid) combination of these methods (including something in hashCode() without including it in equals(Object) violates the contract of hashCode(), so this is not allowed). Additionally, properties can be configured individually via the @Property annotation. When both annotations are present, @Property is used since it applies only to the one property. Using @Property gives you complete control and makes @AutoProperty optional. A common practice is to have all properties included in equals(Object) and toString(), while only one or two key properties are included in hashCode() like so:
@AutoProperty(policy=DefaultPojomaticPolicy.EQUALS_TO_STRING)
public class Book {

@Property(policy=PojomaticPolicy.ALL)
private final String isbn;

private final String title;

public Book(String isbn, String title) {
super();
this.isbn = isbn;
this.title = title;
}

public String getIsbn() {
return isbn;
}

public String getTitle() {
return title;
}

@Override public int hashCode() {
return Pojomatic.hashCode(this);
}

@Override public String toString() {
return Pojomatic.toString(this);
}

@Override public boolean equals(Object o) {
return Pojomatic.equals(this, o);
}
}
Both @AutoProperty and @Property can use accessor methods (getters) instead of fields in situations where using accessors is more desirable or when a SecurityManager prevents Pojomatic from accessing private fields through reflection.

Briefly, there is also a feature which will let you customize the String representation of each property. For example, this would be useful if one of your properties contains sensitive data such as an account number, credit card number or social security number (see AccountNumberFormatter). Pojomatic provides the ability for you to define your own formatter implementations as well.

Feedback
Pojomatic has been a lot of fun to work on, and I hope you will find it useful. I'm confident that after trying it out, you will not want to go back to handcrafting equals methods or using ugly IDE-generated code instead. Any feedback is appreciated, as well as feature requests, so what do you think?