Vaibs
Vaibs

Reputation: 1606

Custom annotation not working for nested object field

I have created small custom annotation which is for validation. If the field is annotated with custom annotation, it will throw the exception.

Below is the code

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD})
public @interface NotRequired {
    public boolean value() default true;
}

Models::

public class Profile implements IProfile{
    @NotRequired
    private Integer id; 
    private String fName;    
    private IAddress add;
  //setter and getter

public class Address implements IAddress{
    @NotRequired
    private String address;

Test class::

public class CustomAnnotationTest {

    public static void main(String[] args) {
        IProfile profile = new Profile();      
        //profile.setId(123);  // in this case it is working fine
        IAddress address= new Address();
        address.setAddress("Aus"); // not working, expected exception should be thrown
        profile.setAdd(address);
        try {
            if (CustomAnnotationNotRequired.validateForNotRequirdField(profile)) {
               System.out.println("Validation Successful");
            }
        } catch (Exception e) {        
            e.printStackTrace();
        }
    }
}

ValidatorClass:

public class CustomAnnotationNotRequired {
    public static boolean validateForNotRequirdField(Object objectToValidate)
            throws Exception {

        Field[] declaredFields = objectToValidate.getClass().getDeclaredFields();

        for(Field field : declaredFields) {

            Annotation annotation = field.getAnnotation(NotRequired.class);

            if (annotation != null) {

                NotRequired notRequired = (NotRequired) annotation;

                if (notRequired.value()) {
                     field.setAccessible(true); 
                     // annotated field is having value 
                     if (field.get(objectToValidate) != null) {
                         throw new Exception();
                     }
                }
            }
        }
        return true;
    }
}

Test case: 1)

 IProfile profile = new Profile();     
        profile.setId(123); 

// For this input getting correct result

2)

IProfile profile = new Profile();      
            //profile.setId(123);
            IAddress address= new Address();
            address.setAddress("Aus");
            profile.setAdd(address);  

// Expected exception.Field of Address class is annotated with @NotRequired annotation but not giving correct result.

Upvotes: 1

Views: 1473

Answers (1)

samabcde
samabcde

Reputation: 8114

The validation is not applied to the address field because the validateForNotRequirdField method only validate the field of profile, and does not inspect into the @NotRequired annotation of Address. Suppose the @NotRequired is only applied to some common value class, the following changes to validateForNotRequirdField method will produce desired result.

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;

public class CustomAnnotationNotRequired {
  public static boolean validateForNotRequirdField(Object objectToValidate)
      throws Exception {

    Field[] declaredFields = objectToValidate.getClass().getDeclaredFields();

    for (Field field : declaredFields) {

      Annotation annotation = field.getAnnotation(NotRequired.class);
      if (!isValueClass(field.getType())) {
        field.setAccessible(true);
        if (field.get(objectToValidate) != null) {
          // validate nested field
          validateForNotRequirdField(field.get(objectToValidate));
        }
        continue;
      }
      if (annotation != null) {

        NotRequired notRequired = (NotRequired) annotation;

        if (notRequired.value()) {
          field.setAccessible(true);
          // annotated field is having value
          if (field.get(objectToValidate) != null) {
            throw new Exception();
          }
        }
      }
    }
    return true;
  }

  private static boolean isValueClass(Class<?> fieldType) {
    // Add other class if needed.
    return fieldType.equals(String.class) || fieldType.equals(Integer.class)
           || fieldType.equals(Short.class) || fieldType.equals(Long.class)
           || fieldType.equals(BigDecimal.class)
           || fieldType.equals(Date.class);
  }
}

Upvotes: 1

Related Questions