Google App Engine adds Java support (Review)

Last night Google announced Java support on Google App Engine.

After a bit of toying around, here are my findings.

The Eclipse plugin is pretty slick. Deploying and build is simple.

The dev server that you spin up locally looks to be jetty under the hood.

Objects intended for storage are JDO annotated and after compiling, you run the .class files through the DataNucleus Enhancer which adds additional metadata so Google can map it to BigTable. The Eclipse plugin automatically performs this step for you after compiling. The examples provide a bunch of ant macros to help facilitate building/deploying.

One issue that I had was that the project was building with Java 1.6 and I would get an error after compiling:

Caused by: java.lang.UnsupportedClassVersionError: Bad version number in .class file

Even though they say they support Java 1.5 and 1.6, I guess this doesn’t work on the Java 1.6 for the Mac. Switching the build to 1.5 allows the DataNucleus Enhancer to run successfully.

Even though they are using JPA, some features have not yet been implemented or supported ( see http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA)

Overall, I like what I see so far and think this would be great for quick prototypes of web apps/services.

Going through the tutorial, my awesome Guestbook application has been created and deployed.

Eclipse Ganymede + Subclipse = Unable to load default SVN client???

I like Shiny New Things. So when I heard Eclipse Ganymede SR1 was available, I proceeded to replace the Stream Stable Build I was currently running.

This, of course, ended up causing me problems. After installing Subclipse and attempting to pull up any SVN history, I get an error dialog box that states:
“Unable to load default SVN client”

Confused, I RTFM and saw that “Subclipse 1.4.x requires Subversion 1.5.0 version of JavaHL/SVNKit”

Seeing the SVN I was running was in fact not 1.5,

  theo@notedpath~ $ svn --version
svn, version 1.4.4 (r25188)
   compiled Nov 25 2007, 08:20:33

I went here, downloaded and installed Subversion 1.5, restarted Eclipse and things are looking good now.

Stupid shiny new things.

Breaking Java Habits: Ruby increment/decrement operators

My background in C++ and Java has instilled in me some programming habits that don’t play nice in Ruby. When I want to increment or decrement a number, my fingers instinctively go to ‘++’ and ‘–’’.

Unfortunately, this syntax is not supported by Ruby. As a language design choice, Ruby opted to not support this syntactic sugar to increment/decrement a variable.

I will have to break my habit and start going with:

// increment x
x+=1
// decrement x
x-=1

Another thing to note is that the prefix increment/decrement operators like ‘–x’ or ‘++x’ do nothing. The signs are interpreted as unary operators.

Java WTF: Reflection API and Annotations

I got some exposure to custom Java 5 Annotations today and came across a noobie mistake.

Here’s my annotation:

public @interface Annotated {
}

Pretty simple, right?

Here’s a test class that uses the annotation:

import java.lang.annotation.Annotation;

@Annotated
public class Main {
    public static void main(String[] args) throws Exception {
        for(Annotation ann: Main.class.getAnnotations()) {
            System.out.println(ann);
        }
    }
}

What does this print?

Nothing!

Well, WTF?

Turns out Annotations are not run-time accessible unless you declaratively specific it via @Retention. The updated annotation looks like this:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Annotated {

}

By default, the Retention is specified with RetentionPolicy.CLASS which, per the javadocs, “Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.”

RetentionPolicy.RUNTIME allows the annotation “to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.”

File this one under, RTFM.

Java WTF: Calendar vs Date

I’ve been doing some date math at work and I came across something I thought was wack.

Check this out:

Calendar cal1 = Calendar.getInstance();
Thread.sleep(500);
Calendar cal2 = Calendar.getInstance();
Thread.sleep(500);
Date now = new Date();

System.out.println(cal1.before(cal2));
System.out.println(cal1.before(now));

What do you think this snippet prints (It compiles, I promise!)?

Looking at the code, it shows that we are getting three snapshots in time, waiting half a second between snapshots, and assigning those values to cal1,cal2, and now, respectively. I put in the Thread.sleep() to illustrate the point more clearly. The first print statement compares the first and second snapshots in time, returning true if the first is before the second. The second print statement returns true if the first is before the third snapshot.

Logically, we would expect both print statements to prints true. However, this outputs:

true
false

But, how could the first snapshot be before the second snapshot but not the third?

Putting up the javadocs, gives us our answer. The Calendar before and after methods always returns false if you don’t pass it a Calendar object. Why? I have no idea. Why not just have the method signature take a Calendar object? I mean, I guess this allows you to extend Calendar to be able to call after/before on whatever kind of classes you want to support…but does it really make sense to compare a Calendar to a Monkey class? This is what I call a Java WTF.