Friday, 30 December 2005

Joda-Time subprojects released

I've just finished releasing the Joda-Time hibernate support (0.8) and Joda-Time JSP tags (0.9) subprojects.

Both these projects are still officially pre a 1.0 release, however its good to have them available properly. I had intended to release the jsptags project as 1.0, but a cunning plan ensued which caused me to go to 0.9 instead. Hopefully I can confess what I've been up to soon, its really very useful!

Thursday, 22 December 2005

Joda-Time 1.2 is released

I had hoped it might have been released before Javapolis, but time pressures came into play (no pun intended!) Anyway, Joda-Time 1.2, the replacement for JDK Date and Calendar, is now released!

This release fixes a few bugs and upgrades to the latest time zone information. It also includes two new calendar systems, Ethiopic and Islamic. I am still looking to expand the range of calendar systems though, there are numerous ones still to add.

Also added were convenience methods on properties to create an interval for a whole month/week etc (toInterval), and to set a date to the last day in a month (withMaximumValue).

The feedback from Joshua Bloch and the rest of the audience at Javapolis was useful, and I expect to enhance and clarify the API over the coming year.

Full details can be found on the website. As always, feedback welcome!

Sunday, 27 November 2005

Changing Java: Adding simpler primitive creation

So, when you're coding in Java sometimes you just have to use primitives. (We'd all love to use objects all the time, but that just isn't possible in Java). However creating primitives can be a pain on occasion, so what could we do?

Defining a variable/constant is easy and just works for short/byte (and all types):

// defining variables is easy:
double val1 = 2.1d;
float val1 = 2.1f;
long val1 = 2L;
int val1 = 2;
short val1 = 2;
byte val1 = 2;

However calling a method shows us the nasty difference between bytes and shorts compared to longs, floats and doubles:

someFloatMethod(2f);  // compiles OK
someShortMethod(2);   // doesn't compile
someByteMethod(2);    // doesn't compile
someShortMethod((short) 2);  // compiles OK
someByteMethod((byte) 2);    // compiles OK

public void someFloatMethod(float f) {
}
public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

So why do we not have a convenient shorthand for bytes and shorts like the 'f' for float or 'd' for double?

someShortMethod(2s);  // note the 's'
someByteMethod(2b);   // note the 'b'

public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

A related issue is creating a binary value (which I needed to do tonight - bonus points if you can guess the pattern I was storing!):

int binary =
    (1 << 2) + (1 << 5) + (1 << 7) + (1 << 10) +
    (1 << 13) + (1 << 16) + (1 << 18) + (1 << 21) +
    (1 << 24) + (1 << 26) + (1 << 29);

Yuck! Why could I not create it with a specialist syntax like this:

int binary = 0b00100101:00100101:00100100:10100100;

While not suitable for every case that you want to create a binary value, it definitely has value. The question is whether its too minor a use case to justify a language change?

Thursday, 24 November 2005

Adding for loop indexing to Java

When using the new for loop in JDK 1.5 do you ever need an index? What do you do, and could a language change help?

Collection coll = ...
int i = 0;
for (String str : coll) {
  System.out.println(str + ", line " + i);
  i++;
}

This isn't very friendly, and exposes the loop index outside the scope of the loop. Maybe we could have a small language change:

Collection coll = ...
for (String str : coll : int i) {
  System.out.println(str + ", line " + i);
}

Note that the extra : int i would be optional! If you don't want the index, just don't declare it.

This is really just a logical extension of the enhanced for loop change from JDK 1.5. Its main benefit is protecting against stupid errors with the scope of the index when an index is actually needed.

Something else that was lost with the new for loop was the ability to remove an item from the collection using the iterator. A variation on the index syntax would allow us to reinstate that:

Collection coll = ...
for (String str : coll : Iterator it) {
  if (str.startsWith("org.apache.")) {
    it.remove();
  }
}

There are more issues with this one however, as Iterator also exposes the hasNext and next methods which the for loop is using. This shouldn't cause a problem, but might require some more work in detailed design.

This blog is number 4 in a series on possible language enhancements to remove boilerplate code - see code blocks, nulls and casts. Opinions welcome as always :-)

Wednesday, 23 November 2005

Adding auto casts to Java

OK, so after auto null checks and code blocks what else would make Java that little bit clearer to read and write? What about casts?

Once again, here is an example use case:

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return ((Person) obj).getAge();
  }
  return -1;
}

Note, I've deliberately kept the use case 'stupid'. There are many good OO solutions to this kind of problem, but I believe that the vast majority of Java developers still end up writing nasty casts all the time.

So, what do I propose could be changed in Java 1.6?

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return obj.getAge();
  }
  return -1;
}

The compiler can easily figure out that obj must be an instance of Person in the if statement. So why do we need the cast? The code without the cast is more readable and just as safe.

I still believe that casts have a useful role to play in Java, when you want to emphasise a point in conversion, or to cast without an instanceof. But when we've already checked with the instanceof, why are we have to repeat ourselves? Thats just boilerplate code.

Opinions welcome, as always.

Tuesday, 22 November 2005

Adding auto null checks to Java

So, after considering code blocks yesterday, what about another bane of Java life, nulls. How could they be simplified in a Java-friendly style?

Here's the use case I'm trying to solve:

public isFromBritain(Profile profile) {
  if (profile != null) {
    Person person = profile.getPerson();
    if (person != null) {
      Address address = person.getAddress();
      if (address != null) {
        return "GB".equals(getCountry());
      }
    }
  }
  return false;
}

And here is my proposed solution for JDK1.6:

public isFromBritain(Profile profile) {
  return profile#getPerson()#getAddress()#getCountry()#equals("GB");
}

A bit surprising at first glance, yet much much simpler to read and understand. I'm using # to indicate "ignore null for now and continue processing". I used # as javadoc already uses it instead of a dot. Implementation-wise, the compiler would expand it to the former use-case, so no big issues there.

By the way, this series of entries is inspired by Graham Hamilton's blog about boilerplate Java code. I'm just trying to show what gets in my way, and provide a Java-style (not Ruby/c#/python/... style) solution. As always, opinions welcome :-)

Monday, 21 November 2005

Adding closures to Java, or not...

There has been a lot of talk on Javalobby recently about adding closures to Java. But how can this be done without destroying the style of Java?

Groovy shows one way to add closures. But groovy has the ability to create syntax, change classes and do other strange stuff that is just too way out for Java itself. So I though I'd do an experiment to see if I could figure out a way to add closures to Java following a more java style.

I started with a use case I wanted to solve, the dreaded resource close:

InputStream in = null;
try {
  in = new FileInputStream(file);
  in.read();
  ...
} finally {
  if (in != null) {
    try (
      in.close();
    } catch (IOException ex) {
    }
  }
}

I then played around with some ideas.

My preferred solution was:

do.CloseAfter (InputStream in) {
  in = new FileInputStream(file);
  in.read();
  ...
}

I saw the main benefits as being more readable, shorter, removing the common close code, scoping the variable and reducing errors. Importantly, a current Java programmer would grok the new way of woring very quickly (no complex syntax).

The key was using the do keyword to identify the special code. I believe that this keyword-usage is much more Java-style than arbitrary symbols like ->.

CloseAfter would just be a regular Java class, just limited to have one method:

public class CloseAfter implements ClosureManager {
  public void execute(InputStream in) {
    try {
      call(in);
    } finally {
      if (in != null) {
        try (
          in.close();
        } catch (IOException ex) {
        }
      }
    }
  }
}

For this common case, it would be a JDK class.

Once I'd done all this and convinced myself that the compiler could implement it easily (by copying the CloseAfter code directly into the original method) I had a sudden realisation - this wasn't really closures, but surrounded code blocks.

Nevertheless, it could be very, very useful, for example to do commit and rollback...

do.DBTransaction (Connection con) {
  ...
}

Kind of like AOP-lite :-)

I just have this sense that a syntax like this would be easy to add to Java, and solve 80% of the issues that full-blown closures tackle (with 20% of the complexity). Opinions welcome :-)

Tuesday, 11 October 2005

Commons IO 1.1 done and dusted

Yay! I've successfully navigated the long drawn out process of releasing code from Apache, and Commons-IO 1.1 is now available for download.

(For those of you wondering, Apache demands way more security checks and file updating than a sourceforge release. Thats why, I try and avoid being release manager at Jakarta Commons if possible.)

Anyway, enough of my whining... just go and get the new release! It makes coding any kind of simple IO just a whole lot easier!

Sunday, 21 August 2005

Spot the 'deliberate' mistake...

I was coding in commons lang earlier tonight when I found one of my test cases wasn't passing. It took a few minutes to realise my stupid error. So here's the test! Can you spot it too???

public int readToken(char[] chars, int start) {
  int pos = start;
  while (pos < chars.length) {
    if (chars[pos++] == '"') {
      return pos;
    }
  }
  return start++;
}

(By the way, there are lots of possible errors here like NPE and this is a very simplified version of the actual method, however somewhere here is a particular 'weird' error.












Did you find it?
Its the return statement. You might think on glancing at the code that the method would return the value of start plus one. But it doesn't. It returns the value of start, as the ++ occurs after the return statement. Obvious really - yet in a non-obvious way. The fix of course is to do return ++start; ;-).

(Sorry if you got it straight away, but it amused me for a minute or two...)

Thursday, 11 August 2005

Joda-Time 1.1 is released

It took a while, but version 1.1 of Joda-Time, the replacement for JDK Date and Calendar, has been released!

This release does fix a few bugs, however these were mostly relatively minor. It does however include a number of useful new methods and usability enhancements. For example:

  • a new Partial class, allowing any group of datetime fields to be defined. A typical use might be to create a YearMonth object for a credit card
  • new convenience methods for adding periods, such as plusDays(n) or minusHours(n)
  • YearMonthDay and TimeOfDay are now comparable
  • new methods to create a Period from two YearMonthDay or two TimeOfDay objects
  • new methods on Interval - gap, abuts and overlap
  • better handling of two digit years in formatting/parsing
  • added ISO formats for ordinal (dayOfYear) dates

And stay tuned for announcements about Hibernate and JSP integration!

Full details can be found on the website.

Oh, and if anyone wants to help develop another calendar systems, such as Hebrew, Islamic, Chinese, etc. then please contact me!!!

Sunday, 26 June 2005

Compiling for older JDKs

Most developers seem to assume that they can simply set the javac setting to output 1.2 or 1.3 compatible bytecodes, and they can then compile using JDK1.4 or 1.5. But, this doesn't work.

The problem is that the Java class libraries have changed between JDK1,3 and 1.4 (and so on). Each change provides the potential to break the build.

For example, in JDK1.4 a new method was added to StringBuffer - append(StringBuffer). In itself, this was not newsworthy. However, this method overloads (not overrides!) other methods, notably append(Object).

If you compile using JDK1.4, and you are appending a StringBuffer to a StringBUffer, javac will choose the nice JDK1.4 append(StringBuffer) method. When you use this JAR on JDK1.3 however, you will get a NoSuchMethodError (not Exception!). This is because overloaded methods are bound into the bytecode at compile time.

Oh, and that 'use 1.3 bytecodes' flag in javac? Well that makes no difference. It just avoids writing bad bytecodes, and doesn't check for valid methods.

I'm writing this because it has come up twice recently on commons-dev. Firstly, during the release of Jelly 1.0, where it took quite some effort to convince people of the problem. Secondly, during ongoing work on Email 1.0, where exactly this issue occurred.

The only safe solution is to:

  • compile the JAR file using the lowest JDK supported by your open source library
  • make sure that is the JAR file released to ibiblio's maven repository
  • include that jar file in the source distribution as well as the binary
  • make sure that the manifest file correctly references the lowest JDK version
And to achieve this I use ant and not maven.

Its not a maven issue per se, but maven does require a higher JDK to run itself than most of the libraries I release. Now, I am told that maven can build using a different JDK version to that which it runs on (maven.compile.executable). Well, great if that works. But, I'm not sure that I trust it to actually do all the necessary steps.

Hence my appoach - all compilation steps are done with ant. All website steps are done with maven. Just using the right tool for the right problem in my book.

Friday, 4 March 2005

So where next with Joda-Time? A JSR?

Releasing a v1.0 can be a strange experience. Once its done, the stress can just disappear, and you take a bit of a rest (assuming there was no great heap of new bugs discovered, which there wasn't).

And its a bit like that with Joda-Time. v1.0 is done and out in the wild. There was quite a bit of positive feedback, but I've no idea how popular it really was because Sourceforge statistics are up the spout.

The main question then becomes well what next? v1.1 would be the obvious answer, but I need to gather some energy to add more code. And until and unless I get feedback on Joda-Time in use its difficult to know what people are missing.

The other possible direction is a JSR. Various people have suggested this, but I am a little skeptical. JDOM, Jade (scientific units) and Groovy haven't exactly been good indicators of what JSRs do to open source projects.

So, what do people reading this think. Are you not using Joda-Time because its not in the JDK? Is a JSR a good direction to go? Have you got your own ideas for what java.time should look like?

Tuesday, 22 February 2005

Joda-Time 1.0 released

Yes, its finally here! Joda-Time, the replacement for JDK Date and Calendar (and much more) has reached 1.0!

Full details can be found on the website. However, let me draw out a few key features:

- Easy to Use - Calendar makes accessing 'normal' dates difficult, due to the lack of simple methods. Joda-Time has straightforward field accessors. And the index of January is 1!

- Extensible - Joda-Time supports multiple calendar systems via a plugin mechanism, which is much more extensible than the subclasses of Calendar. Currently supported calendars are ISO8601, GregorianJulian, Buddhist (Thai) and Coptic.

- Comprehensive - Joda-Time includes classes for datetimes, dates without times, times without dates, intervals and time periods.

- Advanced formatting - An advanced and extensible formatting mechanism is included, allowing input and output to string in a thread-safe manner.

- Well documented. There is documentation in the form of a quick and full user guide, plus reference pages, FAQs and javadoc.

- Tested. There is good test coverage, see the website, providing an assurance of quality.

- Built in security. Advanced operations that could prove a security risk (like changing the current time) are protected by standard JDK security.

And if you learn best by an example:

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = Period.days(2);
  return datetimeRented.plus(rentalPeriod).isBeforeNow()
}
public boolean isJoinedInLastThreeMonths(DateTime datetimeJoined) {
  Interval last3Months = new Interval(Period.months(3), new DateTime());
  return last3Months.contains(datetimeJoined);
}
public boolean isBirthdayInLeapYear(YearMonthDay dateOfBirth) {
  return dateOfBirth.year().isLeap();
}

So, now its released, what next? Well I hope that some of you reading this will want to help add some other calendar systems, such as Hebrew, Islamic, Chinese, etc. Any takers?

Wednesday, 16 February 2005

Joda-Time 0.99 done, 1.0 on its way...

Yes, after lots of late nights, version 0.99 of Joda-Time (the replacement for JDK Date and Calendar, and much much more) is out in the wild.

The plan is to get a few days feedback on 0.99, remove the deprecated methods, then release as 1.0 next week (and definitely before the end of February).

By the way, if you used version 0.98, you'll need to read the release notes, as there were a few last minute changes between 0.98 and 0.99. But I'm determined to let nothing stop 1.0 ;-)

Oh, and if you want to help out by developing another calendar system, Hebrew, Islamic, Chinese, Thai, Japanese,... just drop me a line !