10 tricks to write Annotations in JAVA

Julien Veneziano
Fueled Engineering
Published in
3 min readJun 5, 2017

This piece is not intended to be an How-to, there are already many great ones on the internet. I will list the tricks I used and those I should have used to make your annotation processor development as smooth as possible. The directing principle is to tackle one complexity at the time.

1. Write a sample class in your project

It might seems like a no-brainer but before jumping into code generation, you need to make sure the generated code works. The other advantages to write such class is to figure out the best package location, validate the annotation approach is the proper solution and have it reviewed.

2. Load your class with the reflection API

Now that you know the class works, it is time to lay down the foundation for handling generated class in your code. Remember, the annotation processor will only be called if your code contains annotations, therefore a class may or may not be generated. By loading the class with the reflection API it allows you to catch ClassNotFoundException and such, preventing crashes and guarantees compilation.

3. Save your Annotations in a separate module

I recommend to locate the annotations in a separate module from the compiler module and the library or application module. The principal reason is to guarantee interoperability between the compiler (JAVA module) and the library/application that can by an Android module.

4. Make your annotation module a Maven dependency

If you are planning on distributing your generator as a maven dependency, don’t forget to make the annotation module one too. Because the annotations won’t be packaged in the library dependency nor in the compiler dependency.

5. Don’t waste your time using a template, it won’t work

The annotation compiler will be packaged in a jar located in the Build/intermediate of the module that uses the annotations. Therefore the template file will be left behind out of reach.

6. Use JavaPoet

JavaPoet is a nifty library that helps you generate classes, methods, fields etc… programmatically taking care of the hassle of managing import and writing the output JAVA file.

7. 1 generating method = 1 generated method

JavaPoet has a fluent interface making it easy to use. However, when writing a complex class encapsulating Builder upon Builder can quickly make the code hard to read and hard to track the progress. I recommend to create static method that will return a MethodSpec or FieldSpec object and to give it the name of the generated method.

8. Use $T, $S, $L

JavaPoet has some useful placeholder that do more than just format the code block:

  • $T is my favorite, it is use to declare types and manage the import for you!!. You should always use it when declaring variables in the codeBlock.
  • $S is used to represent a String in the generated code. You should always use it as it will handle the quote and escaping of quote for you.
  • $L is great when you need to dynamically set an int and other primitives.

9. Write Unit Tests for your compiler

Testing your compiler by running gradle assembleDebug is a lengthy process and hard to debug. Save yourself some time and write Unit Tests.

10. Learn to use the remote debugger

Unit Tests are not always enough to debug your compiler. Because the compiler run during the build, you cannot just set some Breakpoint and click Debug. You need to setup a remote debugger in the IDE to be able to catch those breakpoints.

--

--