Core Java

Annotations, Annotations Everywhere

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):

Movie.java

@Entity
@Table(name = "MOVIE_ENTITY_GRAPH")
@NamedQueries({
    @NamedQuery(name = "Movie.findAll", query = "SELECT m FROM Movie m")
})
@NamedEntityGraphs({
    @NamedEntityGraph(
        name = "movieWithActors",
        attributeNodes = {
            @NamedAttributeNode("movieActors")
        }
    ),
    @NamedEntityGraph(
        name = "movieWithActorsAndAwards",
        attributeNodes = {
            @NamedAttributeNode(value = "movieActors", subgraph = "movieActorsGraph")
        },
        subgraphs = {
            @NamedSubgraph(
                    name = "movieActorsGraph",
                    attributeNodes = {
                        @NamedAttributeNode("movieActorAwards")
                    }
            )
        }
    )
})
public class Movie implements Serializable {
    @Id
    private Integer id;

    @NotNull
    @Size(max = 50)
    private String name;

    @OneToMany
    @JoinColumn(name = "ID")
    private Set<MovieActor> movieActors;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "ID")
    private Set<MovieDirector> movieDirectors;

    @OneToMany
    @JoinColumn(name = "ID")
    private Set<MovieAward> movieAwards;
}

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:

Movie.java

@MovieEntity
@FindAll
@LoadWithActors
@LoadWithActorsAndAwards
public class Movie implements Serializable {
    @Id
    private Integer id;

    @Name
    private String name;

    @MovieActors
    private Set<MovieActor> movieActors;

    @MovieDirectors
    private Set<MovieDirector> movieDirectors;

    @MovieAwards
    private Set<MovieAward> movieAwards;
}

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

@LoadWithActors

LoadWithActors.java

@NamedEntityGraph(
        name = "movieWithActors",
        attributeNodes = {
                @NamedAttributeNode("movieActors")
        }
)
public @interface LoadWithActors {}

@LoadWithActorsAndAwards

LoadWithActorsAndAwards.java

@NamedEntityGraph(
        name = "movieWithActorsAndAwards",
        attributeNodes = {
                @NamedAttributeNode(value = "movieActors", subgraph = "movieActorsGraph")
        },
        subgraphs = {
                @NamedSubgraph(
                        name = "movieActorsGraph",
                        attributeNodes = {
                                @NamedAttributeNode("movieActorAwards")
                        }
                )
        }
)
public @interface 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:

WoWBusinessBean.java

@Named
@Stateless
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
@ApplicationPath("/resources")
@Path("wowauctions")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class WoWBusinessBean extends Application implements WoWBusiness {}

Rewritten:

WoWBusinessBean.java

@RestStatelessBean("wowauctions")
public class WoWBusinessBean extends Application implements WoWBusiness {}

@RestStatelessBean

RestStatelessBean

@Named
@Stateless
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
@ApplicationPath("/resources")
@Path("#{path}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public @interface RestStatelessBean {
    String value() default "#{path}";
}

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.

Reference: Annotations, Annotations Everywhere from our JCG partner Roberto Cortez at the Roberto Cortez Java Blog blog.

Roberto Cortez

My name is Roberto Cortez and I was born in Venezuela, but I have spent most of my life in Coimbra – Portugal, where I currently live. I am a professional Java Developer working in the software development industry, with more than 8 years of experience in business areas like Finance, Insurance and Government. I work with many Java based technologies like JavaEE, Spring, Hibernate, GWT, JBoss AS and Maven just to name a few, always relying on my favorite IDE: IntelliJ IDEA.Most recently, I became a Freelancer / Independent Contractor. My new position is making me travel around the world (an old dream) to customers, but also to attend Java conferences. The direct contact with the Java community made me want to become an active member in the community itself. For that reason, I have created the Coimbra Java User Group, started to contribute to Open Source on Github and launched my own blog (www.radcortez.com), so I can share some of the knowledge that I gained over the years.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button