Annotations, Annotations Everywhere

posted by Roberto Cortez on
tags:

Annotations became available with Java 1.5 in 2004, ten years ago. It’s hard to imagine our code without this feature. In fact, annotations were first introduced to relieve developers from the pain of writing tedious boilerplate code and make the code more readable. Think about J2EE 1.4 (no annotations available) and Java EE 5. Annotation adoption considerably simplified the development of a Java EE application by getting rid of all the configuration XML. Even today, more annotations are being added to the newest version of Java EE. The idea is to unburden the developer and increase productivity. Other technologies and frameworks use them extensively as well.

Annotations Everywhere

Annotations Everywhere

Let’s see an example on how annotations have simplified our code (from my post about JPA Entity Graphs):

Wait a minute! Simplified? Really? Aren’t annotations supposed to make my code more readable? This example has more annotations than actual code. To be fair, I’m not including getters and setters. Also, some of the annotated code could be better condensed, but it would make the code harder to read. Of course, this is an extreme case. Anyway, I’m happy since I won the title Annotatiomaniac of the Year. Thanks Lukas!

Annotatiomaniac of the Year

We rely in annotations so much that we end up abusing them. It’s funny that annotations in some cases are causing the same problems that they intended to solve.

What if?

Let’s rewrite the previous sample like this:

It sure looks more readable. But these annotations do not exist. Where do they come from?

@LoadWithActors

@LoadWithActorsAndAwards

And so on for the rest. You get the feeling. The idea would be to extract and group annotation metadata into your own custom annotations. Your annotation could then be used to represent all the annotated data in your code, making it easier to understand. It’s like Java 8 Lambdas, read like the problem statement.

Just another example:

Rewritten:

@RestStatelessBean

Usually, I write these annotations once to define the behaviour of my POJO and never look into them again. How cool would be if I could just reuse one annotation for all my Stateless Rest Services?

Another nice effect, is that annotation configuration metadata is not directly tied in the code. Instead it’s abstracted away into a different annotation. In this case, it would be possible to override or replace the values in compile / runtime.

Meta Annotations

I first heard about this concept by David Blevins. He wrote a very good post about these ideas in his Meta-Annotations post and even wrote a possible implementation.

It would be convenient to have plain Java SE support to annotation inheritance, abstraction and encapsulation. It’s a major shift in the way annotations are handled by all the technologies out there. This only makes sense if everyone starts supporting this kind of behaviour.

One might ask, do we really need this feature? Let’s try to weigh in some pros and cons:

Pros

  • Simplified Code.
  • Annotation Reuse.
  • Annotation configuration not directly tied to the code. Values could be overridden.

Cons

  • Another layer of abstraction.
  • Freedom to create custom annotations could obfuscate the real behaviour.
  • Possible to run into some kind of multiple inheritance pitfall.

Conclusion

It’s unlikely that this Meta-Annotations are going to be available in Java SE for the foreseeable future. In Java 9, most of the focus is in Jigsaw. We don’t have much information yet on Java 10, other than Value Types and Generic Specialization. In fact, all these annotation concerns are not really a problem for plain Java SE.

The amount of annotations present in our source files is becoming a problem regarding readability and maintainability. This is especially true for Java EE and other similar technologies. Think about HTML and CSS. If you’re developing an HTML page and you only need a couple of CSS styles, you usually inline them in the elements or include them directly in the page. If you start to have too many styles, then you proceed to extract them into an external CSS file and just apply the style. I do believe that something must be done either by adopting Meta-Annotations or something else. Do you have any other ideas? Please share them!

Resources

Don’t forget to check David Blevins post about Meta-Annotations. He explains this much better than me, including the technical details.

Also a presentation JavaOne EJB with Meta Annotations discussing these ideas by David Blevins.

And what better than to listen David Blevins himself? Java EE 7, Infinite Extensibility meets Infinite Reuse.

Comments ( 17 )

  1. Replyivan_stefanov

    Roberto, I cannot agree that all the focus of Java SE 9 is on Jigsaw. Yes, this is the biggest topics, but JEP-wise, it’s just 4 JEPs, out of ~20 that are approved to enter Java 9 (for now). And the game is not over yet.

    But you are right, this topic is not in Java SE yet and I don’t see it discussed to go there. 🙂

    P.S. Another awesome blog from you! 🙂

    • ReplyRoberto Cortez

      Thank you for the feedback Ivan 🙂

      Yeah I was just trying to emphasise that this topic is far from reaching the Java SE discussion.

  2. ReplyLukas Eder

    Man, this post was so overdue on our blog… You beat us to it. Nice one 🙂

    • ReplyRoberto Cortez

      Ops… sorry about that 🙁

      Got this one on my TODO list since JavaOne.

  3. Replycblin

    I sometimes feel that annotations are used for the sake of being used.

    For ex, JAX-RS without annotation is possible like in http://sparkjava.com/, and you really loose nothing.

    For ex, validation is possible without annotation like in https://github.com/JeremySkinner/FluentValidation and you really loose nothing.

    Some annotations like @override or the one of lombok project seems good to me since you can not achieve the same in pure java. Even JPA seems ok since it would be tedious to do that separately from the fields.

    For the rest I far too often feel like I’m writing annotations and not code.

    The worst (to me) is DI annotation like @Inject or @Autowire that leads to object with tens of collaborators (who would write a constructor with 10 args ?)

    Well, this is just my 2c

    • ReplyRoberto Cortez

      Hi cblin,

      Thank you for your comment.

      Yes, that’s the feeling. Writing annotations and not meaningful code. By the way, the github validation code that you sent is for .NET apparently. Wrong link?

      Cheers,
      Roberto

  4. Replyolivergierke

    @Roberto – You should’ve better picked Antonio’s (to really serious) example of the Java EE monster component. 😉

    Fun aside, annotations can (and will) be overused. I even think that the validation JSR is more dangerous in a way that people think they should rely on annotations to assure consistency in their domain model instead of value objects. See this one for a frightening example. All of these annotations should be value objects instead. An IBAN is an IBAN is an IBAN, not a String with an annotation. Anyway, I digress…

    The concept of meta-annotation has been a first class citizen in Springs since the early days it leveraged annotations in general (2.5.6, read: 2008). So pretty much all Spring annotations can be used that way. The standards have been pretty hesitant in that regard, although they actually leveraged annotations even earlier than Spring did. Only a very few of them (I only know about some in the @Inject but would be happy to find out about other ones as well) support that kind of style.

    For JPA named entity graphs it’s a particular pity as I pointed out that the declarations might quickly get out of hand in the early design phase within the expert group. Especially as the specification (and also your example) usually only deal with very simplistic examples. Now imagine what this looks like if you use that in a real-world application where you list 10 out of 15 properties.

    The feedback I got was that a simplification step (I suggested just alternatively taking a String-array to be able to easily whitelist the properties to be included but still provide the more verbose way for more complex scenarios) could be added if people would really complain. So I suggest to create a ticket in the spec’s bugtracker if you think it’s worth simplifying. I already raised one to add the ability to use the annotations as meta-annotations a while ago.

    @cblin – It’s not really an issue with DI, but field injection. But agreed, if the annotations would not have been allowed to be used on fields in the first place, the world would be a better place today. See my rant on this one here :).

    • Replyolivergierke

      That should’ve read: “not really serious”, not “to really serious”…

    • ReplyRoberto Cortez

      Hi Oliver,

      Thank you for your comment.

      Yes. I’m aware of António’s Java EE Monsters component. Me and a few other people were talking about it on twitter a few days ago. There are other annotations that you could add there 🙂

      It’s a good idea to create a ticket to consider simplification on @NamedEntityGraphs annotations. I’ll do it!

  5. Replyasd

    Is this the first time when DSL language becomes overcomplicated? Look what happens in JEE: dependency injection everywhere. Annotations, DI and reflections are ugly hacks.

  6. Replymcclellanmj

    Meta annotations are not fixing the problem, just treating the symptoms.

    There are many things we annotate that could just as easily be defined in a .java file using some library api, for instance Spring bindings vs Guice bindings. Guice has significantly less annotations than Spring.

    The problem is annotations have become our crutch for everything config. We forget that plain jane java code is the best config of all, it can loop, it can connect to external sources and anything else we can dream of. Give people a proper api to configure your library and they can accomplish all sorts of problems they can’t with just some annotations.

    • ReplyRoberto Cortez

      Hi mcclellanmj,

      Thank you for your comment. Maybe meta annotations are not the perfect solution, but something must be done. At least they could shield the average developer with the ridiculous amount of annotation that you have to know and type each day. Even today I was looking into a Spring file which had @Configuration and @EnableAutoConfiguration. I know they are different, but also confusing.

      Plain java configuration also haves the advantage of being more readable, since you can just follow a stack of execution. Annotations are a pain in that department.

  7. ReplyMike

    Hi Roberto, thanks for the tutorial. However could you provide an example of how you created any of the @MovieDirectors, @MovieAwards or @MovieActors custom annotations? I’ve been trying something similar where I want to group a number of JPA annotations into my own custom annotation i.e.

    @OneToMany
    @JoinColumn(name = “ID”)
    public @interface TestAnnotation{
    }

    However I get an error stating “‘@OneToMany’ not applicable to annotation type”.

    • ReplyRoberto Cortez

      Hi Mike,

      Unfortunately the standard JPA annotations cannot be used into other annotations because they don’t have the @Target(ElementType.ANNOTATION_TYPE). This post was just an idea on how to improve these annotations and remove annotations from the code.

  8. ReplyKen

    I’m confused about the part with @Path(“#{path}”). Are you somehow passing the value given to your custom annotation to the @Path annotation??

    • ReplyRoberto Cortez

      Ah no. That was just a sample. It could have been “foobar” instead.

Leave a reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>