Saturday, May 22, 2010

All you need to know about java annotations - brief

1) What are annotations?

Annotations are tags (@) that you insert into your source code which acts as information to an external tool that process them.
Example:

@Log(logLevel="Debug")
public void someAPI(){...}


@Log is an annotation here which informs the external tool which processes @Log to start logging in debug mode when someAPI method is executed.

2) Why do we need Annotations?

Some of the uses of annotations could be
#) Provide information to the tools so that the tools can generate auxiliary files such as deployment descriptors.
#) Provide information to the tools so that the tools can automatically generate code for testing, logging, transaction, security etc.


3) How of Annotations?

#) Defining Annotations -
Considering the above log example, this is how @Log can be defined

import java.lang.annotations.*;

@Target (ElementType.METHOD)
@Retention (RetentionPolicy.RUNTIME)
public @interface Log
{
String logLevel() default "info";
}

The @Target and @Retention are annotations provided to another annotations and hence called meta annotations.

@Target annotation helps in specifying the target element on which @Log annotation can be used. In this example the METHOD is used as the target which indicates that @Log is applicable to only methods in a class.

You can add annotations to the following items
# Packages
# Classes (including enums)
# Interfaces (including annotation interfaces)
# Methods
# Constructors
# Instance Fields
# Local Variables
# Parameter Variables

Example: -

public @interface BugReport
{
enum Status {FIXED, NOTABUG};
boolean showStopper() default false;
String assignedTo() default "[None]";
Status status() default Status.UNCONFIRMED;
Reference ref() default @reference;
String[] reportedBy();
Class testCase() default Void.class
}


and annotation looks like this


@BugReport(showStoppre=true, assignedTo="xyz", testCase=TestClass.class,
status=BugReport.Status.CONFIRMED, ...)


@Retention meta annotation specifies how long an annotation is retained. You can specify atmost one of the following values.

SOURCE - Annotatoins are not included in class file.
CLASS - Annotations are included in class file, but the virtual machine need not load them.
RUNTIME - Annotations are included in class file and loaded by the virtual machine. They are available throu the refelection API.

4) Annotation Processing

Annotation can be processed at three levels
#) In the source code [SOURCE]
You process annotation at the source level if you want to produce other source files, such as XML descriptor files, stubs/skeletons, remote interfaces etc. For source level annotations u need to parse java source file. Java provides an annotation process tool (apt) which processes annotations in source files and feeds them to annotation processor that you supply.

#) In bytecode files [CLASS]
If you want to process annotations at the bytecode level then you need to analyze class files. BCEL is the library which helps in processing class files and modifying class files. This type of processing can be used to modify class files to add byte codes for logging etc.
You can run a bytecode engineering tool in two modes.You can simply write a tool that
reads a class file, processes the annotations, injects the bytecodes, and writes the modified class file. Alternatively, you can defer the bytecode engineering until load time, when the class loader loads the class.

#) At Runtime, in the virtual machine [RUNTIME]
This is the easiest way of processing an annotation which can be done by reflection api's at runtime.