Wednesday, March 10, 2010

Defining and Using Custom Java Annotations

When we look in to java annotation definition it will say like this “Annotations provide data about a program that is not part of the program itself or Annotations are java’s way to provide some information to the java compiler”. For example when we look in to @Deprecated annotation, we can see that it says to the compiler that the annotated type is deprecated. That’s fine, great but in reality where I can use my own annotations and what are the scenarios? Recently I came in to a situation where I could see the right use of Custom annotation. When I searched for this it was pretty difficult to find out the right it formation, all tutorials talk about how to write custom annotation and what are the features and syntax but the information I wanted was when to write custom annotation or why do I write a custom annotation. So I just thought of posting one of the most important use of Custom annotation.

The requirement: I have a set of classes which are of 2 types, say example “DBUpdate” classes and “DBInsert” Classes. When run time I need to do actions based on which type of class is executing

Solutions:

    1. Use a super class and do a type check in run time. But here the issue is both classes are extending  from   same super class “DataBase.”

    2. Define a marker interface “DataBaseUpdate” and implement this interface for the classes which are doing “DataUpdate”. (This works fine..!!!) But need to define 2 interfaces and should be careful about implementing right Interface etc

   3. The alternative solution is define a custom annotation “DataBase” and mark your classes with this. (We will see how to do this”)

Define the Custom Annotation:

   @Target(ElementType.TYPE)
   @Retention(RetentionPolicy.RUNTIME)
    public @interface DataBase {
        String dbTask() default “”;
    }

Use @Interface before the annotation name.(dOwe see any relationship between the solution number 2 and the keyword @iInterface!!!!!!) Note that there are 2 other annotations used for defining an Annotation .. :). @Target will define the scope of the annotation (method, class, constructor..etc. Refer Javadoc for all the Target element Types and to know the RetentionPolicy)

Process the Annotation at Runtime:

Here a method which will process when it found our annotation

@SuppressWarnings("unchecked")
public static String processAnnotation()
{
    // getting the classes in execution
   // getAllClassesInExecution definition is not added here

    Class[] classesInExecution = getAllClassesInExecution();
    for(int i=0; i<classesInExecution.length; i++)
    {
          if(classesInExecution[i].isAnnotationPresent(DataBase.class)){
               DataBase db = classesInExecution[i].getAnnotation(DataBase.class);
               String dbTask = db.dbTask();
               if (dbTask.equalsIgnoreCase(“update”) {
                          //Do db update here.
               }
               else if (dbTask.equalsIgnoreCase(“insert”) {
                        //Do db isert here.
         }
   }
}

Using the Annotation:

Now Use this Annotation at class level. (We used Target(ElementType.TYPE))
   @DataBase(dbTask =”update”)
   Public class MyDBTest{
        processSQL();
    }

Now we are ready with our own annotation when the code is executed based on the dbTask we provided the system will do the task accordingly. Now keep defining your custom annotations and start enjoying.
(Don’t forget to refer the performance issues and other things while using the runtime processing)