29-09-2021
What is Java Annotation Processing?
by João Rico, Team Leader & Senior Developer @Xpand IT
Java Annotation Processing is a feature that appeared in Java 5. It is a source-level annotation processing.
What can it be useful for?
Sometimes you might encounter some minor tasks that need to be done every time you:
- Update something in your code and there are some files that need to be created that depend on that update.
- Need a few utilities to map your objects into something and you want to avoid Reflection.
That’s where Java Annotation Processing comes in handy. It’s a processor tool that looks at the annotations in your code and gives you the ability to build anything you want at compile-time, like:
- Java code.
- Some files in your application.
You might already use some libraries that use this feature. The ones that I know are Project Lombok and MapStruct.
The first one generates a lot of boilerplate code in your source code like Getters, Setters, ToStrings, Builders, etc.
MapStruct, on the other hand, is a tool that generates mappers between objects automatically without the usage of reflection (like Dozer), because it builds those mappers at compile time.
In some clients, we are using this to transform Java objects into fixed-length string formats. We used utility classes that were edited by hand, where the code was relatively large (maybe 5000 lines of code).
Now we use only annotations, and those 5000 lines of code are generated for us! The code is now much more readable in our repositories.
How can I use this?
In order to avoid showing the code we’re using on the client, I will demonstrate how to create your own annotation processor by using the examples shown in this Baeldung post.
First you set up your project using the following dependencies:
After that, you need to create your desired annotations, like this:
The most important thing to have in these annotations is the @Retention (RetentionPolicy.SOURCE) set so that the compiler is able to access them.
Then you need to create a class that extends the AbstractProcessor:
You now can make your processing logic in the process method shown above. The input of the method enables you to find the annotations in the code and be able to work through them to generate anything you want at compile time:
As a final step, you need to generate what you need, whether it’s Java code or a specific file. For Java code, the processor library contains methods for you to do that:
In our case, we are using a much simpler library for Java Code generation called Java Poet.
Since we are using the Google Auto Service library, we now just need to build our annotation processor as a library, use it in our application and use the created annotations:
The example explained here is able to create a builder pattern for the setter methods annotated with the @BuilderProperty annotation. Using the following example:
This will create a newer class, like this, automatically at compile time:
Learn more about what is Java Annotation Processing
If you want to explore more about these features, you can go to the following websites: