Reputation: 1606
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
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