Setting up Contracts for Java in Eclipse

On Friday, Contracts for Java was announced on the Google Open Source Blog. Learning about this at the beginning of the weekend was perfect timing for me: I had time to check it out, and while setting it up was some work, I was hooked right away.

Now something like Contracts for Java is only really useful if it is well integrated into the tools you use everyday – which in my case is Eclipse. Eclipse allows many levels of integration, and I quickly had it working by running javac as an external tool – which is OK, but not ideal, since it requires running the tool manually after every change to the annotations, and doesn’t give in-place error messages. I quickly found out Eclipse has support for custom annotation processing. I had to fiddle a little until I got that configured properly with Contracts for Java so I thought I do a quick write-up so other people can try this cool new tool in Eclipse.

Contracts for Java doesn’t provide any binary downloads yet, so my first step was to build a Jar. To use it, create a Java project, and add cofoja-latest.jar and asm-all-3.3.1.jar to the build path. Then add some code that uses contract annotations (copy and paste the code below into the src folder of the project):

import com.google.java.contract.Ensures;
import com.google.java.contract.Requires;

public class Contracts {
	public static void main(String[] args) {
		System.out.println(new Numbers().add(-10, 5));
	}
}

class Numbers {
	@Requires({ "c > 0", "b > 0" })
	@Ensures({ "result > a", "result > b" })
	int add(int a, int b) {
		return a - b;
	}
}

Next, configure the annotation processing in the project properties > Java Compiler > Annotation Processing. To make Contracts for Java work with the Eclipse Java compiler, currently some specific properties have to be set up: set the com.google.java.contract.classpath property to the location of your cofoja-latest.jar and the com.google.java.contract.classoutput property to the location of your project’s src or separate bin folder (both relative to the project root, using the %PROJECT.DIR% variable):

If your project uses multiple Jars they currently have to be given with absolute paths as the com.google.java.contract.classpath value, separated with ‘:’ on Unix or ‘;’ on Windows. Next, make sure you have set up your workspace to refresh automatically in Preferences > General > Workspace to make Eclipse see the resources generated by the annotation processor. Then, add the cofoja-latest.jar to the project properties > Java Compiler > Annotation Processing > Factory Path:

Now issues in the annotation values are reported in the editor, like variables that cannot be found, e.g. for our code above:

To have the contracts checked at runtime, add -javaagent:cofoja-current.jar to the VM arguments of your run configuration:

Now when running, we are made aware of the violated precondition in our code:

After we fix the call violating the precondition to new Numbers().add(10, 5); we now see our implementation of add does not fulfill the postcondition:

After fixing our implementation to return a + b; the code now runs without errors. For further information on using Contracts for Java check out the project wiki. General information on design by contract can be found elsewhere.


About this entry