Friday 20 August 2010

Joda-Convert

Type conversion to and from a String is a very common application problem. To aid in the process, I've created a small library - Joda-Convert.

Joda-Convert

There are many libraries designed for converting from one object to another, so why create another. Well, partly because I wanted something focussed on the task of Object to String rather than the larger problem of Object to Object. See this list (bottom of the page) for other projects.

The second reason I wanted to write Joda-Convert was to experiment with annotation based conversion. This is an extension of the principles in JSR-311 (RESTful API) where type conversion is performed by looking for a valueOf static method or a constructor that takes a String. While this approach is very useful, it doesn't support some of my projects like JSR-310, where the static method is named of or parse.

This leads into the third reason. If the annotation based approach is successful, then Joda-Convert is ideally placed to be moved into the JDK. It would be wonderful to see the JDK classes annotated to indicate which methods should be used to convert to and from String.

Using Joda-Convert is easy:

// conversion to String
String str = StringConvert.INSTANCE.convertToString(foo);

// conversion from String
Foo bar = StringConvert.INSTANCE.convertFromString(Foo.class, str);

There are built in converters for many JDK types. It is also possible to create an instance of StringConvert to allow application converters to be registered.

When searching for a converter, if one is not already registered, then the system will search the class for annotations:

public class Distance {

  @FromString
  public static Distance parse(String str) { ... }

  @ToString
  public String getStandardOutput() { ... }

}

As can be seen, adding the annotations to a class is very simple. The Joda-Convert system will parse the class, find the annotations and create a suitable converter that calls the annotated methods by reflection. The key point is that they can be used on any method, rather than the convention approach used by JSR-311. Consider a class like TimeZone to understand why this is important.

One little known point about annotations is that the annotation class is not needed at runtime. This means that a library like Commons-Lang could add the annotations to their Mutable* classes without actually adding a runtime dependency. If a user chose to not use Joda-Convert then there would be no impact. If a user did choose to use Joda-Convert, then the conversion would just work.

If I can release Joda-Convert soon, then I will add the annotations to Joda-Time and Joda-Money. Hopefully other projects will consider the idea too! (If you're interested, let me know, as it gives an incentive to get the project to v1.0)

Summary

Joda-Convert is currently an untested Alpha that exists to test out the annotation idea (although as far as I know it does work). I'd welcome participants that want to help test and finish the JDK conversions. I'd also like to see 'helper objects' added, so a DateTimeFormatter can be used to help convert a DateTime, or a ClassLoader to convert a Class.

Feedback welcome as always!

Tuesday 17 August 2010

Java generics migration compatibility

A quick call for help on generics.

Joda-Time has the following non-generic interface, with an example dummy implementation:

public interface ReadableInstant extends Comparable {
  ...
  int compareTo(Object readableInstant);
  ...
}
public class Dummy implements ReadableInstant {
  ...
  public int compareTo(Object readableInstant) { ... }
  ...
}

I've been trying to generify this and maintain backwards binary and source compatibility without success. The following naive implementation works fine for new code:

public interface ReadableInstant extends Comparable<ReadableInstant> {
  ...
  int compareTo(ReadableInstant readableInstant);
  ...
}

This doesn't work fine when the old code is combined (unaltered and without recompilation) with the new library.

Firstly, the old code is not source compatible. Dummy does not implement the altered method in the newly generified interface, thus the old code doesn't compile without change.

Furthermore, it is not binary compatible. Imagine a second class Foo that implements the generified version of ReadableInstant. Now consider a class which loads Dummy (unaltered and without recompilation) by reflection as a ReadableInstant and calls compareTo to compare. This will throw an AbstractMethodError. This is because Foo expects there to be a method of the generified form, taking ReadableInstant.

So, its basically a mess. I can't come up with a way to preserve backwards compatibility while adding generics. But I thought the whole point was to allow migration compatibility!

So, I thought that perhaps I'm missing something stupid. If so, please let me know! All the code is in svn (1.6 branch and TRUNK) for anyone wanting to play with real code.

Friday 13 August 2010

Power corrupts. Absolute power corrupts absolutely.

Today, Oracle proved the old phrase to be true - "Power corrupts. Absolute power corrupts absolutely." They also reminded us why we hate Friday the Thirteenth.

Oracle, Google and the politics of money

Todays announcement that Oracle was suing Google somehow isn't a great surprise. Oracle are, at heart, a large enterprise with a track record of sweating purchased assets to make money. Why would Sun and Java be any different?

At no stage could I say I've been entirely comfortable with the notion of Oracle as owner of Java technology. When the takeover was announced I highlighted some of the risks. It looks like those risks are coming into play.

On the specifics of the lawsuit I have little to say. Google undoubtably have sailed close to the wind. But did they cross the line? Well, thats for lawyers now. The problem I have is not that there was something to discuss, but that Oracle thinks that this approach will improve their position. For me it shows how out of touch they are with how community and sentiment works outside CxO level politics.

The lawsuit is likely to shine a bright light on the OpenJDK too. Anyone who has contributed to the project known as "OpenJDK 7" should now be concerned about whether their work will ever be freely available as open source. (Of course their work can be released by Oracle in a proprietary manner, as the contributor agreement allows that.)

We also have our answer on the Apache Harmony dispute, the JCP and the lack of Java SE 7.

I see no feasible way to resolve the Apache Harmony dispute at this point. Harmony is the basis of the Google approach which is being targetted, so any recognition of Harmony would be fatal to the lawsuit.

Furthermore, Google is a key player in the JCP. And all the other members of the JCP back Apache's position. And since only the JCP is currently entitled to produce a Java SE 7, there is absolutely no way out of the deadlock. I think it is only right and proper at this point to consider the JCP as terminated at this point.

(The "Power corrupts. Absolute power corrupts absolutely" quote is a reference to the fact that Oracle supported the position of Apache Harmony until they bought Sun. There position has changed somewhat since.)

The implications of this for version 7 of Java are serious. Part of the concept of an open specification is that others may implement it. These include IBM's JVM, Excelsior JET ahead of time compiler, Eclipse Java compiler and many others. For version 7, how will these other organisations be able to continue? Will we see an Oracle JDK released that cannot be used from Eclipse?

And the implications don't just stop at the Java SE platform. All the specifications that enterprise Java is built on are produced by the JCP. And all of them have up until now been able to be implemented as open source due to the agreements in the JCP contracts. Oracle effectively served notice on that today.

It would therefore be wise to consider there to be no guarantees that open source implementations of other JCP specifications can continue. This includes the whole of Java EE, including JPA, JMS, JSF, Servlets, JAXB, JAXRS and high profile projects including Tomcat, Geronimo, HornetQ and Hibernate.

Would Oracle be crazy to block these open source implementations? Yes!
But being crazy seems to be the order of the day.

Oh, and JavaPosse? I'd recommend renaming your podcast pronto!

Summary

Shortly after the merger I spoke to a Sun employee who was now employed by Oracle. Their view was that Oracle had no idea what they had really bought with Java. The meaning was that Oracle did not understand the role of the wider community in the success of Java. Today that lack of understanding was made crystal clear.