dagblog.
← Archive

Annotation hell?


I do not know whether you already use or have at least seen JSR 175, the Metadata Facility for Java, otherwise known as annotations, in action. So far I have only used standard SE annotations such as @override to add metadata for the compiler. There were big plans and high hopes for annotations in the enterprise world. If you have not seen an EJB 3.0 example, metadata there is used to annotate both session and entity beans.

While studying Seam, a framework built around annotations, I began to feel that XML hell might give way to annotation hell. Seam connects EJB 3.0 and JSF. One benefit is that it connects JSF components directly to session beans as action listeners and entity beans as the model, without writing a controller. Annotations take over the controller's role.

If you use Seam, your code will soon be teeming with Seam annotations as well as the EJB ones. They cover things such as component definitions, setting and reading component attributes, validation and transactions. A simple bit of code might look like this (copied from the Seam documentation).

@Stateful
@Scope(SESSION)
@Name("messageManager")
public class MessageManagerBean implements Serializable, MessageManager
{
@DataModel                                   (1)
private List messageList;

@DataModelSelection (2)
@Out(required=false) (3)
private Message message;

@PersistenceContext(type=EXTENDED) (4)
private EntityManager em;

@Factory("messageList") (5)
public void findMessages()
{
messageList = em.createQuery("from Message msg order by msg.datetime desc").getResultList();
}

public void select() (6)
{
message.setRead(true);
}

public void delete() (7)
{
messageList.remove(message);
em.remove(message);
message=null;
}

@Remove @Destory (8)
public void destroy() {}
}
  • The @DataModel annotation exposes an attibute of type java.util.List to the JSF page as an instance of javax.faces.model.DataModel. This allows us to use the list in a JSF with clickable links for each row. In this case, the DataModel is made available in a session context variable named messageList.
  • The @DataModelSelection annotation tells Seam to inject the List element that corresponded to the clicked link.
  • The @Out annotation then exposes the selected value directly to the page. So ever time a row of the clickable list is selected, the Message is injected to the attribute of the stateful bean, and the subsequently outjected to the event context variable named message.
  • This stateful bean has an EJB3 extended persistence context. The messages retrieved in the query remain in the managed state as long as the bean exists, so any subsequent method calls to the stateful bean can update them without needing to make any explicit call to the EntityManager.
  • The first time we navigate to the JSP page, there will be no value in the messageList context variable. The @Factory annotation tells Seam to create an instance of MessageManagerBean and invoke the findMessages() method to initialize the value. We call findMessages() a factory method for messages.
  • The select() action listener method marks the selected Message as read, and updates it in the database.
  • The delete() action listener method removes the selected Message from the database.
  • All stateful session bean Seam components must have a method marked @Remove @Destroy to ensure that Seam will remove the stateful bean when the Seam context ends, and clean up any server-side state.
I should add that this is a genuinely simple example. Altogether, Seam defines more than thirty annotations! Add the EJB annotations, particularly the JPA (Java Persistence API) ones, and we probably end up with something like a hundred pieces of runtime metadata. That’s a hell of a lot to contend with. What do we do with it?
  • We need development tools that offer a sensible way to visualize metadata and support development activities such as refactoring.
  • Developers will need design patterns for using annotations.
With the Spring Framework, for example, I prefer good old XML to annotations, mainly for two reasons.
  • Centralization. I have related metadata in one place, such as the definition of the DAO or web layer. That makes it easier to find and change things.
  • Independence. Changing metadata does not necessarily require changing application code. For instance, I can test the DAO layer in isolation with its own transaction settings entirely at the metadata level.
Annotations have many uses. Let's just hope we do not end up in another kind of hell...

Medium version

Related articles

Related CZ Podcast episodes