Introducing JavaPoet

Square has a new library for generating Java code.

Written by Jesse Wilson.

I used to hate generated code. Early implementations of JSPs, EJBs, and protocol buffers spewed out huge, misformatted files littered with warnings and fully-qualified type names:

*     * <code>optional string error_text = 2;</code>*
*     */*
    **public** Builder **setErrorText(**
        java**.**lang**.**String value**)** **{**
      **if** **(**value **==** **null)** **{**
  **throw** **new** **NullPointerException();**
bitField0_ **|=** 0x00000002**;**
      errorText_ **=** value**;**
      **return** **this;**

But things get better. Integrating generated code into a project is easier thanks to Java’s powerful annotation processing facilities. Testing code generators has been tamed by Google’s compile-testing library. Today Square moves faster thanks to the generated code in AutoValue, Dagger, Butter Knife, and Wire.

Unfortunately the code that generates code in each of these libraries is still awkward. For example, Dagger writes each generated file top to bottom which means it needs to prepare imports as a clumsy separate step. It models the .java file as a string and doesn’t understand its structure.

Today I’m eager to announce JavaPoet, a successor to JavaWriter. JavaPoet models a .java file with types, methods, and fields and does imports automatically. Generate “Hello World” like this:

MethodSpec main **=** MethodSpec**.**methodBuilder**(**"main"**)**
    **.**addModifiers**(**Modifier**.**PUBLIC**,** Modifier**.**STATIC**)**
    **.**addParameter**(**String**[].**class**,** "args"**)**
    **.**addStatement**(**"$T.out.println($S)"**,** System**.**class**,** "Hello, JavaPoet!"**)**

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)


Get JavaPoet on GitHub. Jesse Wilson *Android and jokes.*