Skip to main content

Still Thinking About Annotations..

Posted by eitan on November 24, 2005 at 10:20 AM EST

It has taken me a while to get into java 5 annotations. The reason partly was how late java 5 distributions arrived to the macosx platform (and it's still not the default version). About six months ago this stopped being an issue for me as i am now developing on ubuntu. I can't say enough wonderful things about ubuntu but we'll save that discussion for another blog entry.

I tried out writing my own annotation. The scenario in question was the idea of modeling a method as an action. So metadata about a method might include the caption for the action, the mnemonic character to bind to that action and more such metadata. Essentially, the idea is to invoke the method when the action is performed from the UI. Here's a simple example of how an annotation might be bound to some methods in a ficticious class, Waiter:

public class Waiter
{
   private String _name;
   public Waiter(String name) { _name = name; }

   public void aplainmethod()
   {
      System.out.println("this is a plain method");
   }

   @CommandAt(
         mnemonic='g',
         caption="Greet Customer",
         parameterCaptions={"Enter Name: ", "Specify Greeting: "}
   )
   public String greet(String name, String greeting)
   {
      String msg = _name + " says: " +
            "Hello " + name + ": " + greeting;
      System.out.println(msg);
      return msg;
   }

   public String toString() { return _name; }
}

There's no denying the elegance of the solution. I particularly like the ability to place information about the method right next to it, though this may prove unwieldy. Aspects for example place code about methods somewhere else and use selectors to bind the code dynamically to methods based on some criteria. That's much more powerful.

The reason I'm inclined to prefer aspects is simply that the the meta-stuff is a block of code, whereas annotations are declarative in nature. This is just a feeling at the moment but I think the reason I prefer the former case is that in order to arrive at a solution we're not employing any new concepts: the concept of a block of code existed in Java. Things are more self-similar, more minimalistic. Also, one might wonder how far one can describe meta-work declaratively. I think that's essentially the difference between annotations and aspects: aspects are meta-code whereas annotations are meta-data.

I recently went through the short exercise of developing a basic issue manager (similar to bugzilla or scarab). The most fascinating aspect of the exercise was discovering a piece of metadata about methods: its owner. That is, the person who is assigned a bug is the bug owner and only him/her should be allowed to invoke the 'accept()' method to signal that they've taken ownership of the bug. Similarly, only the person who opened the bug should be allowed to verify and close the bug, not the developer responsible for fixing it. So I decided to model accept() and close() as methods on the same object (Issue) but to specify the owner of the method to relate who (what logged-in user) is allowed to invoke them (from the ui of course).

For better or for worse, this is what I came up with:

   static
   {
      ComplexType type = ComplexType.forClass(Issue.class);
      type.command("Accept", AssignedState.class).setOwner(type.field("assignedTo"));
      type.command("Fix", AcceptedState.class).setOwner(type.field("assignedTo"));
      type.command("RejectFix", FixedState.class).setOwner(type.field("openedBy"));
      type.command("Close", FixedState.class).setOwner(type.field("openedBy"));
   }

So the way you should read/interpret the code is:

For Issues:

for the command "Accept" in AssignedState, set the owner to the value of the assigneTo property (that is call getAssignedTo() when you need to know). etc..

Sure enough, that did the trick. Now when I assign a bug to a user, only that user can accept it (what I'm not showing you is the framework that produces the ui from the model objects).

My main question at the moment, is: would it be possible to define such meta data using annotations? I don't have the answer yet. This bit of code is declarative in nature so we should be ok. The only complication might arise from the limitation that annotation property values can only be of type: primitive, String, Class, enum, annotation, or an array thereof. In the above case, the owner is of type Field (not java.lang.reflect.Field, but another Field). There are other issues to consider as well, and they're not necessarily insurmountable.

I don't yet have extensive experience with annotations to say for sure, but I have a feeling that it would be nice to be able to traverse from an annotation to its associated programming element; in this case: to go from the CommandAt annotation to its associated method. Looking at the javadocs for java.lang.annotation.Annotation, this relationship does not appear to be defined.

I find it would be very interesting to also discuss this whole issue of metastuff from the point of view of aspects. Maybe it's just me but having to weave in aspects into bytecode seems to be a hurdle high enough to block mass adoption of this powerful technology. My feeling on this point at the moment is that aspects have not yet reached their peak; that we will have to wait for a manifestation of aspects implemented for a scripting/non-compiled environment before that can happen. Indeed there already appears to exist a working prototype implementation of aspects for ruby.

Related Topics >>