General Advice

We find that the best way to use Ductile is to set up a separate compilation target that compiles with Ductile enabled. That way you can fluidly switch between compiling your program with the type checker and without. The same goes for unit tests. Often you'll want to run some particular unit test via Ductile so that you can check some particular code path even though the rest of your code isn't currently type checking. Thus the examples below target such a configuration.

Compiler Plugin

Ductile is a javac compiler plugin. You can build the plugin from source, or you can download detyper.jar, the pre-built plugin.

Limitations

There are a couple of limitations of Ductile that we want to own up to straight away:

Ant Integration

Suppose you have a compilation task that looks something like the following:

<target name="compile" depends="...">
  <javac srcdir="${src.dir}" destdir="${classes.dir}">
    <classpath refid="classpath"/>
  </javac>
</target>

Creating a target that compiles using Ductile requires just a few simple changes:

<target name="dcompile" depends="...">
  <delete dir="${classes.dir}/detyped"/>
  <mkdir dir="${classes.dir}/detyped"/>
  <javac executable="PATH/TO/1.7/javac" fork="true"
         srcdir="${src.dir}" destdir="${classes.dir}/detyped">
    <classpath>
      <path refid="classpath"/>
      <fileset dir="SOMEWHERE" includes="detyper.jar"/>
    </classpath>
  </javac>
</target>

Configuring a separate JUnit task to run with your Ductile compiled code is also easy. Here's an example JUnit task configuration:

<target name="tests" depends="compile">
  <junit printsummary="yes" haltonfailure="yes">
    <classpath>
      <pathelement location="${classes.dir}"/>
      <pathelement path="${java.class.path}"/>
    </classpath>
    <formatter type="plain"/>
    <test name="my.test.TestCase" haltonfailure="no" outfile="result"/>
  </junit>
</target>

Just a few small changes are necessary:

<target name="dtests" depends="dcompile">
  <junit printsummary="yes" haltonfailure="yes">
    <classpath>
      <pathelement location="${classes.dir}/detyped"/>
      <pathelement path="${java.class.path}"/>
      <fileset dir="SOMEWHERE" includes="detyper.jar"/>
    </classpath>
    <formatter type="plain"/>
    <test name="my.test.TestCase" haltonfailure="no" outfile="result"/>
  </junit>
</target>

Other Build Systems

We don't currently have detailed instructions on how to integrate Ductile with other build systems, but hopefully the Ant instructions give you an idea of the necessary steps. Simply set up a target where you compile with the 1.7 javac and where detyper.jar is on the classpath during compilation. Then execute that code directly or instruct JUnit (or any other testing framework) to reference that code when running unit tests. detyper.jar must be on your classpath when executing the code either standalone or via a testing framework.