Tuesday, 6 August 2013

Java User Defined Annotation and Reflection

 Annotation is about Metadata of Class.There is no Direct reflection of annotation in your logic.
 But you can add annotation to class for perform some predefined logic to validate your class, let's take an well know example,
 A JPA pojo,which have annotation like @Entity ,@Column etc. Which is used to map pojo's field with Database column name, and while we try to
 persist our pojo with EnntityManager it create some sql query which is exactly map with columnname and pojo's value respectively.

 Let's get more concept of annotation.Before we start an Example let's clear some concept about meta-annotation.

 source(http://docs.oracle.com/javase/tutorial/java/annotations/predefined.html)

 Annotations that apply to other annotations are called meta-annotations. There are several meta-annotation types defined in java.lang.annotation.

@Retention @Retention annotation specifies how the marked annotation is stored:

  • RetentionPolicy.SOURCE – The marked annotation is retained only in the source level and is ignored by the compiler.
  • RetentionPolicy.CLASS – The marked annotation is retained by the compiler at compile time, but is ignored by the Java Virtual Machine (JVM).
  • RetentionPolicy.RUNTIME – The marked annotation is retained by the JVM so it can be used by the runtime environment.

@Documented @Documented annotation indicates that whenever the specified annotation is used those elements should be documented using the Javadoc tool. (By default, annotations are not included in Javadoc.) For more information, see the Javadoc tools page.

@Target @Target annotation marks another annotation to restrict what kind of Java elements the annotation can be applied to. A target annotation specifies one of the following element types as its value:

  • ElementType.ANNOTATION_TYPE can be applied to an annotation type.
  • ElementType.CONSTRUCTOR can be applied to a constructor.
  • ElementType.FIELD can be applied to a field or property.
  • ElementType.LOCAL_VARIABLE can be applied to a local variable.
  • ElementType.METHOD can be applied to a method-level annotation.
  • ElementType.PACKAGE can be applied to a package declaration.
  • ElementType.PARAMETER can be applied to the parameters of a method.
  • ElementType.TYPE can be applied to any element of a class.

 Example.

 We create a annotation which is used to validate Class's Integer type property's Minimum and Maximum value.

 If annotation method haven't any default value, than is a mandatory while you apply annotation.


 1). We create a annotation for a Class level

        package com.test;
      
        import java.lang.annotation.Retention;
        import java.lang.annotation.Target;
        import static java.lang.annotation.ElementType.TYPE;
        import static java.lang.annotation.RetentionPolicy.RUNTIME;
      
        @Retention(RUNTIME) @Target({TYPE})
        public @interface Validation {
        }



 2). create a annotation for Field/Method Level

        package com.test;
      
        import static java.lang.annotation.ElementType.FIELD;
        import static java.lang.annotation.ElementType.METHOD;
        import static java.lang.annotation.RetentionPolicy.RUNTIME;
      
        import java.lang.annotation.Retention;
        import java.lang.annotation.Target;
      
      
        @Retention(RUNTIME) @Target({FIELD, METHOD})
        public @interface ValidInteger {
            String Label();
            int MIN() default 0;
            int MAX() default Integer.MAX_VALUE;
        }

 3). Now we use this annotation in our Class and again read the annotation and perform validation using Java Reflection API.
     for that we create a Test Class with main method and validation our class.
   
   
        package com.test;
      
        import java.lang.reflect.Field;
      
        @Validation
        public class Test  {
      
            @ValidInteger(Label="Height",MIN=10,MAX=100)
            private int a;
          
            public int getA() {
                return a;
            }
          
            public void setA(int a) {
                this.a = a;
            }
          
            public static void main(String[] args) throws ClassNotFoundException {
                Test t = new Test();
                t.a = 200;
              
                System.out.println(Validate(t));
              
            }
      
            // the method validate your class using java reflection.
            private static String Validate(Test t) {
                // find that the class have annotation present.
                boolean annotation =  Test.class.isAnnotationPresent(Validation.class);
                StringBuilder builder = new StringBuilder();
                if(annotation){
                    Field[] fields = Test.class.getDeclaredFields();
                    for (int i = 0; i < fields.length; i++) {
                        Field field = fields[i];
                        // finding of method level annotation is present
                        if(field.isAnnotationPresent(ValidInteger.class)){
                            ValidInteger integer = field.getAnnotation(ValidInteger.class);
                            try {
                                int fieldObject = (Integer) field.get(t);
                              
                                // Validation for integer.
                              
                                if(fieldObject > integer.MAX() || fieldObject < integer.MIN()){
                                    // return UserDefined Exception or Error Message
                                    builder.append(integer.Label()+" should not greter than "+integer.MAX() +" and not less than "+integer.MIN());
                                }
      
                            } catch (IllegalArgumentException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                return builder.toString();
            }
        }
 

         The output of the class is
       
         "Height should not greter than 100 and not less than 10"

Infinidb _CpNoTf_ problem

infinidb table with a varchar column insert string as a '_CpNoTf_' while using Cpimport. The Problem is occured if inserted string ...