InfoQ

News

John Heintz on Adding Behavior to Java Annotations

Posted by Srini Penchikala on Aug 11, 2008 06:00 AM

Community
Java
Topics
AOP
Tags
AOP ,
Annotations ,
AspectJ ,
Metaprogramming

Custom annotations are a great way to add common reusable behavior to Java applications. But the developers need to follow some guidelines and best practices to identify the areas in the application where using Annotations is a better design solution than other options such as in-line code or using an Interface. John Heintz from New Aspects did a presentation at the recent No Fluff Just Stuff (NFJS) Central Ohio Software Symposium (COSS) on different design techniques for adding behavior to Java custom Annotations.

In the presentation, John gave a walk-through of byte-code and meta programming techniques and an overview of how metadata in Java applications has been managed from the earlier versions of Java, using Properties files, XML, and now Annotations. He mentioned that JSR-175 was formed to provide a metadata facility for the Java language and in Java 5, Annotations were added to the language.

Defining Annotations is similar to defining the Interfaces (Annotations are declared using @Interface type). Annotations can be applied at package level or on a class member (field, method, constructor) or even a method local parameter.

The retention policy, which is an important part of implementing Annotations, is based on how long the data needs to be kept in memory. There are three different types of retention policy:

  • Runtime (where data is retained always and accessible through reflection),
  • Class (data is kept in byte code, not accessible at runtime), and
  • Source level (not kept by compiler).

The recent versions of several popular frameworks like EJB3, Hibernate, Spring, Seam, Struts 2, RIFE and JAX-WS support the Annotations. John discussed three types of Annotation Processing Options:

Generators:
This annotation processing option works by reading the source code and generating new source code or modifying existing source code, and non-source code (XML, documentation, etc.). The generators are typically rely on container or other programming convention and they work with any retention policy.

Some of the generators examples are Annotation Processing Tool (APT) and Processors, XDoclet, Spoon (extensible compiler for Java), and APT-Jelly (which is a templating library). APT doesn't allow you to modify the source code but it's useful for generating auxiliary artifacts (like WSDL, Documentation).

Bytecode Transformers:
These annotation handlers parse the class files with Annotations and emit modified classes and newly generated classes. They can also generate non-class artifacts (like XML configuration files). Bytecode transformers can be run offline (compile time), at load-time, or dynamically at run-time (using JVMTI API). They work with class or runtime retention policy.

Bytecode transformer examples include AspectJ, Spring, Hibernate, CGLib, Javassist, ASM, and BCEL.

Runtime reflection:
This option uses Reflection API to programmatically inspect the objects at runtime. It typically relies on the container or other programming convention and requires runtime retention policy.

Runtime reflection examples are libraries like Java 5+ reflection and Commons Attributes. Testing frameworks like JUnit and TestNG use runtime reflection for processing the Annotations.

John used a sample Java application to demonstrate the implementation of custom Annotations using different design techniques like APT, Javassist, AspectJ, and Reflection (which uses java dynamic proxies). He also showed how to add behavior to classes, fields and methods and talked about annotating Types and Methods with Aspects.

John talked about the benefits of Aspect Processing like ease of implementation (good tool support), fine-grained semantics where it can influence method calls, even field access (unlike reflection and APT), integrating annotations from multiple libraries, and the support for domain-specific abstractions. He suggested that if the java code can be implemented as an interface, then the developers should go with that design instead of using Annotations. He cautioned the developers to not use custom Annotations for everything because a POJO (Plain Old Java Object) is better than a HAJO (Heavily Annotated Java Object). Other best practices mentioned in the presentation are:

  • Annotate the highest level of abstraction possible (e.g., class, not method)
  • Use sensible defaults and annotate only exceptions to a rule. Also, minimize need for parameters.
  • Implement Annotations as complementary to "Convention over Configuration" principle (e.g. in Spring).
  • Use Reflection to augment existing frameworks (e.g., testing).
  • Utilize Javassist and CGLIB frameworks for generating new objects and for low-level, highly tuned bytecode transformation.
  • Use APT for generating non-code artifacts.
Another nice option by Rodolfo de Paula Posted Aug 11, 2008 10:02 AM
  1. Back to top

    Another nice option

    Aug 11, 2008 10:02 AM by Rodolfo de Paula

    http://spoon.gforge.inria.fr/Spoon

Educational Content

Bindings, Platforms, and Innovation

This presentation focuses on the Internet and separating myth from fact, history from the future, and the mundane from the imaginative. Bob Frankston presents a vision of what could and should be.

Orchestrating Long Running Activities with JBoss / JBPM

This article explores the use of JBoss and jBPM to implement design solutions that effectively address the issue of orchestrating long running activities.

Neo4j - The Benefits of Graph Databases

This presentation covers the use of graph databases as an optimal solution for data that is difficult to fit in static tables, rapidly evolving data or data that has a lot of optional attributes.

Realistic about Risk: Software development with Real Options

This session introduces Real Options and shows how it can help in running your project. Real Options is a decision-making process that can be used to manage risk.

Communication Flexibility Using Bindings

This article discusses the use of bindings on services and references (including the instance of non-configured bindings) as the means to implement SCA communications in a Web and SOA environment.

Writing DSLs in Groovy

After a short introduction to DSLs, Scott Davis plays with the keyboard showing how to approach the creation of a DSL by typing working snippets of Groovy code that get executed.

Scaling Agile with C/ALM (Collaborative Application Lifecycle Management)

IBM Rational and InfoQ present, Scaling Agile with C/ALM, an eBook showing organizations how to become “finely tuned software delivery machines” by enabling team integration and scaling.

Concurrent Programming with Microsoft F#

Amanda Laucher presents a real life enterprise application written in F#. She shows actual code snippets, explaining design decisions and suggesting how to use some of the F# constructs.