Innovation, our reason for being
Annotations are, from my experience interviewing people, one of the perhaps most used but least understood features of Java Programming Language. On the one hand, they are the most used, because, nowadays, almost everybody is using Spring, Hibernate and all those frameworks and libraries that make magic under the hood. On the other hand, what I’ve found is that people are not able to explain properly what an annotation is, or how to make that magic on their own.
They are, in fact, related to metaprogramming. In a not very orthodox way, we could define an annotation as the ability to tag declarations (fields, methods, parameters and classes) with information which will be used by an external processor in order to control the interaction with that declaration. Perhaps this definition is obscure, and you could wonder what kind of control I’m talking about. I could suggest several use cases to you, such as:
Obviously the latter one is the more complex, and I don’t recommend you to write any custom bytecode manipulation except if you need to do it – as it was our case -, since it’s quite tricky and not very easy to test. Nevertheless, the other types of annotations (or even a proxy-based one) are not very complex, they are very valuable on their own, and they will certainly provide you with a deeper understanding of Java Programming Language (and related ones).
In order to give you a deeper understanding of annotation usage, I’m going to show you an example.
When we want to populate a database from a series of files, we have to solve several questions. Being, perhaps, the top:
For this problem we are going to answer yes to both questions. Therefore, we have to solve issues related to the storage of different object types and being able to detect if a record has been modified. Solving the first question would involve either a BLOB storage (on a relational database) or another approach as a NoSQL database.
The latter is a different problem, detecting if an object is different in a file than in the database could be resolved in different ways. I think that the simplest approach is to generate a HASH (MD5, SHA or another) of the object and to do a comparison between the source-object hash and the target one.
This hash generation isn’t complex at all, but we should consider that an object is not only comprised of properties, but also state – or temporary information - and computed fields. Obviously the state fields, or even the computed ones, are not going to be used to compute the hash, but, perhaps, these fields should be stored within the database.
For the different solutions we are going to use an interface which will be responsible of hash generation, according to the different solutions we are going to implement.
In this solution we are going to use a Gson builtin solution, using the @Expose annotation, this approach is very simple and works swiftly.
This solution has two main issues:
In this solution we are going to use a custom annotation @HashHidden within Gson, this approach is almost as simple as the previous solution, and it solves the detected issues smoothly.
Not only does Java introduce a new keyword, @interface, but it’s also demanding us to use two standard Java annotations in order to allow proper @HashHidden working: @Retention and @Target. Let me explain them a bit more.
If you wonder how this custom annotation could be used, how the magic is done and you are eager to learn some easy Java internals, this solution is the one for you. Besides, in a more complex environment with a different problem type, previous solutions probably won’t be suitable.
In this approach we will have to use some reflection to retrieve the fields, its values and its annotations.
As you can notice it’s an oversimplified example, in which values are simply transformed to strings. But I think that it’s enough for showing how annotations could be use in a more complex way.
An annotation isn’t simply an empty declaration, you can define inner fields which have some properties as these ones:
At Divisa iT we have used annotations for different utilities within our framework, such as:
Icons used are courtesy of Flaticon