Sunday, March 29, 2009

Annotations for java 6
Well, this title itself is a misnomer as there is no such new feature included in java 6 (aka Mustang). However, the necessary thing is that in java 6, annotations find a heavy usage in the newer and updated API instead of just three annotations in java 5. So it is quite imperative that we understand this nifty change in the language.
Annotations do not directly affect our programs but change the way our programs are processed by other tools and libraries.
Background
The annotations facility was introduced as JSR-175 in jdk 1.5 and has been formalized through JSR-269 in jdk 1.6.
There has been a considerable debate about this addition regarding the location of the application configuration (xml vs. annotation).
Creation
Typically you would never have to create annotations in the normal course of application development but there are extensible options for this too. An annotation type is just an interface with @interface keyword.
public @interface ProjectStatus{
String status() default "[Not-Started]";
}
Now we can use it to annotate declarations as a modifier like public, static, private, etc. The annotation consists of a @ followed by its type name and optionally, a list of element-value pairs. All annotation types implicitly extend the java.lang.annotation interface. The values can be any one of the following:
A wrapper class
String
TypeMirror
VariableElement (like an enum constant)
AnnotationMirror (will further return a map of values, if any)
List< ? extends AnnotationValue > (if the value is an array)
Annotation Type Declaration (Meta Annotations)
This is the meta content for annotation itself as it provides library support for annotations. These are:
Documented :In this, annotations with a type are to be documented by javadoc and similar tools by default. Through this, annotations become a part of th public API of their elements.
Inherited :This shows that the annotation type is automatically inherited. If this is present, a query is thrown to the annotation type on a class declaration. On its unavailability, all the superclasses are searched until the top of the hierarchy, Object is reached. If no superclass in this type has the annotation, the query will indicate that the particular class has no such annotation.
Retention :This is used to set the scope of annotations(SOURCE,CLASS,etc). This is important if the meta annotation type is used directly for annotation. However, if the meta-annotation type is used as a member type in another annotation type, this will have no effect.
Target :This indicates the type of programming element(ElementType.FIELD,ElementType.METHOD,etc) where the annotation type is applicable. On its presence, the compiler will enforce a restriction upon the usage of that particular annotation
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface BookElement{
...
Processing
The annotations processing is one area which underwent a change in java 6.
In java 5, a library called as Mirror API was used which contained 2 parts – one for processor (com.sun.mirror.apt) and other for support classes that modeled the language. In java 6, the processor piece has been relocaled to javax.annotation.processing. This provides facilities for declaring and allowing annotation processors to communicate with an annotation processing tool. However, this feature is not going to be used much in normal developmental tasks.
A basic processor would be:
import java.util.Set;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
@SupportedSourceVersion ( SourceVersion.RELEASE_6 )
@SupportedAnnotationTypes ( "*" )
public class PrintProcessor extends AbstractProcessor
{
public boolean process ( Set < ? extends TypeElement > annotations, RoundEnvironment environ ){ //NOTE: these arguments would be provided by the annotation processing tool framework.
if ( !environ.processingOver ( ) ){
for ( TypeElement element : annotations ) {
//process annotations here
System.out.println ( element.getQualifiedName ( ) + "(" + element.getNestingKind ( ) + ")" );
}
}
return false;
}
}
On parsing, if we get a malformed annotation, then we'll throw a AnnotationFormatError. Likewise, if we attempt to access an annotation object whose type has changed, then it results in AnnotationTypeMismatchException. As annotations is still an evolving feature in java, the use of newer versions of certain annotation in a processor may raise a UnknownAnnotationValueException.
The javax.annotation Package
This package has 5 annotation types and although these are meant to be used in enterprise edition, these are bundled as a standard API in java 6. An overview of these annotations
Generated: Is used to mark the auto-generated code in a source file. This can be used to differentiate between human and IDE generated code.
Resource: Marks a resource that is needed by the application. This is a form of dependency injection as the container will automatically inject an instance of resource when the component is initialized. This name is the jndi name of the resource.
Resources: Similar to resource, takes an array of resource for multiple resources. This is populated using multiple Resource annotations.
PostConstruct: Used on a method that needs to be executed after dependency injection is done for further construction.
PreDestroy: Used on methods that release resources upon finalization of the object in the container.
Examples:
try{
InitialContext init=new InitialContext();
DataSource ds=(DataSource) init.lookup(“jdbc/__bookDbPool”);
Connection connect=ds.getConnection();

Same functionality with annotation reduces much of the ‘boilerplate’ code.
@Resource(name = ”jdbc/__bookDbPool”)
DataSource ds;

try{
Connection connect=ds.getConnection();

Similarly, we can use other annotations
@Resources({
@Resource(name=”jdbc/__tempDB”),
@Resource(name=”jms /__defaultFact”)
})
@PostConstruct
public void initialize(){
connect=ds.getConnection();
}
@PreDestroy
public void cleanup (){
connect.close();
}
The java.sql and javax.sql packages
Among other thoughtful additions in jdbc 4.0 api, there has been a fundamental change in the way we are going to handle data at its lowest abstraction. They simplify the object-relational mappings. Here, we create a query interface that decouples the query from the logic to some extent.
Eg:
interface CustomizedQuery extends java.sql.BaseQuery{
@Select(“SELECT * FROM OFFICE”)
DataSet getAllOfficeEmployees();
@Update(“DELETE * FROM OFFICE”)
int clearOffice();
}
Here, we are just decorating different queries using annotations from Note that we are returning a DataSet instead of a ResultSet from a @Select annotation, while the @Update simply returns the number of records affected. The java.util.DataSet is a standard data structure that can be populated/deleted and used directly in our business logic.
The usage of data items is quite easier:
....
CustomizedQuery custom = connection.createQueryObject(CustomizedQuery.class);
DataSet rows=custom.getAllOfficeEmployees();
......
rows.clearOffice();
The java.xml package
In this package and its subpackages, annotations find a heavy usage. Speaking strictly in terms of enhancements in java6, the XML Data Bindings Specification(JAXB) has been updated to its 2.0 version. Thus, a lot of change has been done in javax.xml.bind package. For instance, there are more than 30 annotations defined in javax.xml.bind.annotation package. A complete description of these, however, would merit a complete article on its own.
Web Services
The java6 has brought web services into the domain of a desktop application developer. Here too, annotations play a major role in easing the developmental process.
Eg:
import javax.jws.*;
@WebService
public class WebService1{
@WebMethod
public String method(){
return “Web service method”;
}
}
The 2 basic annotations displayed here identify this class as a web service. As the name of @WebService annotation is not specified, it defaults to the class name. The benefit of using this approach is that a lot of work gets automatically done from automated tool like wsgen.
Similarly, we can leverage annotations in javax.jws.soap package to create SOAP bindings. Through their usage, we can connect to existing web services with ease
Thus, we are observing simplification of application development through the increased use of annotations which is not just limited to javase, but in java ee as well as in other frameworks like struts2, hibernate, etc. to name just a few. This means that sooner than later we'll have to adopt this technique as it is increasingly being used.
Sumit Bisht
Revision:2.0

No comments: