Leveraging annotations in Java code


In the last few days it I happened to two short discussions on Twitter with Adam Bien (not really a discussion) and Keith Donald (slightly more intesive) on distinct but yet somehow related topics regarding the use of annotations in Java.

Using the right tool for the job

Keith answered my following tweet i posted after revisiting the reference docs regarding JSR-303 (Java Bean validation API) implementaton in latest Spring 3.0 RC1:

“Am I the only one that does not feel good implementing constraints on a class wit JSR-303 annotations? Looks inherently wrong to me…”

Okay, this of course raises the question, what feels wrong to me. This is the code snippet presented there:

public class Person {

    @NotNull
    @Max(64)
    private String name;

    @Min(0)
    private int age;
}

As the getters and setters are left out I assume they simply hand out the appropriate values and receive new values to be set. What’s wrong with this? What you want to express with the annotations are inherent properties of the class. To me it looks crucial for the class not to care about the enforcement of these constraints itself. Here are the problems:

If you annotate field they do not appear anywhere in the Javadocs except you additionally document them at the appropriate getters or something. Why maintain two places of the same information? This can be avoided by annotating the getter methods instead but first IMHO annotation regarding the fields better belong to them and second the pure option to lose this information is dangerous if someone does not remember this problem. Especially if this regards a key responsibility of the class, this is crucial.

This is the key problem IMHO. Suppose you wrote the class as presented above and also wrote some client code that expects the restrictions fulfilled. Now your college also writes some code, that does not use the validation API to prevalidate the object (where should he know from? he just scanned the Javadoc…), forgets to set the name and boom, an ugly NullPointerException flies in your face. To me, the problem in its core lies in the fact that as client developer to the domain class you cannot code against a restriction spec (even if it’s documented) and be sure the class fulfils the restrictions documented. As developer of the Person class I felt even worse, if I’d document something to the outside I have not under control myself.

Wait, you might say? Is that not already the case if you use @Transactional, @Autowired and so on? Definately but there is a crucial difference between both types of usages of annotations. @Transactional e.g. is meta information regarding a technical concern not directly related to the business domain. When using @Autowired you definately should use constructors receiving mandatory collaborators to document the necessity of them on the type level. So these annotation pretty much work as a hint or helper.

Explicitness

Adam Bien wrote a post on his blog regarding on how much code @Stateless saves you over implementing transactions programatically. I am totally with him that annotations can do a great job factoring out not directly related functionality from a class or act as trigger and description of crosscutting aspects of a software system. My reply to his announcing tweet was the following:

“Do not agree entirely. Sometimes more explicitness adds value by helping communicating intent…”

Yet again, what’s behind this statement. For a moment try to forget everything you know about EJB spec (I wish I could sometimes… =). Now imagine you discover a class annotated with @Stateless, only knowing this represents something the container will manage for you. What would you expect, does the container enforce for you? Statelessness of the class? Okay, how could you find out? Consult the Javadocs? Here it is. Well, not much of enlighterment there. Of course the main benefit is that this will make the class an EJB component and add transactions to it. Of course…

Call me biased but IMHO in general the Spring folks do a much better job at naming annotations and therefore communicate intent. I’d really favour @Transactional at my class over a @Stateless because others can dig what I intended to expess much quicker. Call me a pedant but in my role I very often have to provide sample code fellow developers look at and have to grasp it. So I tend to be as concrete as possible in expressing what I intended. Spring is a great help doing that.

The same applies to the JSR-299 VS JSR-330 debate. In the comments to Adam’s blog post someone mention large overlaps between the standards an documents this using a direct comparison:

“@Qualifier is equivalent to @BindingType,
@Scope is equivalent to @ScopeType,
@Singleton is equivalent to @ApplicationScoped,
@Named is just a built-in binding type, and
Provider<X> interface is equivalent to Instance<X>.”

Which side communicates more clearly what is inteded? Let me know what you think…

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts

Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Hey Oliver,
My point is in many cases other colleagues will not / should not use my code outside of the bounded context I use it in. And in the context of a webapp where I’m defining a model that backs a HTML form, I’m comfortable also defining constraint annotations enforced by the framework.

Keith

Hey Keith,

this is a pretty valid approach and I didn’t want to doom the way validation is applied in general. Neither is it my goal to blame Spring framework to implement JSR-303 integration. In fact I really like the easy approachability of how you integrated executing validation into MVC. I just thought I needed to express my concerns as JSR-303 is a very general JSR and thus probably too easily applied. Furthermore I could not find anything one web casting a more critical light on the consequences.

Anyway, thanks for the comment.
Ollie

I totally agree that the documentation of JSR 303 is a problem. You know I am a fan of Javadocs[1], so it’s great that somone thinks alike. IMHO in your Person example the @NotNull annotated field should be replaced by a constructor argument [2]. Everything that must be there for the object to do its work, pass it in by constructor.

On the explicit part: I can only agree with you! The more code you save writing @Stateless – the more time it might take to understand the code! The value of Java is that it’s code can be quite easy to understand. The more magic that happens under the hood – the harder it might be. [3]

[1] http://dlinsin.blogspot.com/2008/06/does-your-api-docs-leave-users-in-dark.html
[2] http://dlinsin.blogspot.com/2009/03/final-or-not-final.html
[3] http://dlinsin.blogspot.com/2007/12/reading-code-or-writing-code.html

Hi Oliver,

nice post. Some remarks:
1. @Stateless means “Stateless”. With that you get some conventions like transactionality.
2. In EJB 3 you can use @TransactionAttribute to set up transactions. This is not always needed – because of 1.
I agree you entirely in theory. In practice I’m bit more pragmatic and don’t even try to reuse domain classes across projects. Then JSR-303 is just perfect. Keith Donald is right with: “… many cases other colleagues will not / should not use my code outside of the bounded context I use…”

thanks for mentioning my posts / tweets. And: don’t take my tweets too seriously – its only 140 characters…..:-)

adam