5

I have one custom field annotation class with two attributes like below:

public @interface Field {
    String type();
    int order();
}

I wanted to validate order, it should not be a negative value and should not repeat, for example:

class User {
    @Field(uiType = "TEXT", order = 1)
    private String fName;

    @Field(uiType = "TEXT", order = 2)
    private String lName;
}

Can anyone help me to do it?

Jonathan
  • 20,053
  • 6
  • 63
  • 70
Venu Annaram
  • 287
  • 2
  • 8
  • 16
  • Are you trying to ensure variables are returned in a specific order during reflection? Please give more info on problem. – William Morrison Jul 01 '13 at 15:42
  • 1
    Use Java`s [apt](http://docs.oracle.com/javase/1.5.0/docs/guide/apt/GettingStarted.html), Annotation Processing Tool. For compile time checks. [Java 7](http://docs.oracle.com/javase/7/docs/technotes/guides/apt/) – Joop Eggen Jul 01 '13 at 16:09

4 Answers4

4

Although this isn't quite what the Bean Validation API is for, you can perform this validation with it. I'm assuming you'd use Hibernate Validator, the reference implementation of the BV API.

You can get the negative check out of the way using a simple validator. Modify @Field to

@Constraint(validatedBy = MyFieldValidator.class)
public @interface Field {
    String type();
    int order();
}

and create a MyFieldValidator class as follows

public class MyFieldValidator implements ConstraintValidator<Field, Object> {

    private int order;

    @Override
    public void initialize(Field annotation) {

        this.order = annotation.order();

        if (this.order < 0) {
          // blow up
        }
    }

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintContext) {

        return true;
    }
}

If you then put the object through a validator, e.g. using Validation.buildDefaultValidatorFactory().getValidator().validate(someUser), any negative order annotation attributes will fail.

Preventing repetition is trickier. The sanest option is to put a validation annotation at the User class level, then use reflection to get the annotations one by one. The advantage of using the class level annotation is that it gives you a simple way to tell Hibernate Validator which classes to check. The not-so-great part is that you might forget to annotate the class.

Emerson Farrugia
  • 11,153
  • 5
  • 43
  • 51
  • Thanks Emerson. I have done negative order validation as you described. – Venu Annaram Jul 02 '13 at 10:04
  • Glad it helped. You also tagged Spring in this question. If you don't want to do bean validation for the repetition check, another option is to create an @OrderedFields annotation and put it on User, and in some PostConstruct, call ApplicationContext.getBeansWithAnnotation(OrderedFields.class) to get the beans, iterate through the classes, and check the Field annotations with reflection. – Emerson Farrugia Jul 02 '13 at 12:16
0

ConstraintValidator should help you.

Ryan M
  • 18,333
  • 31
  • 67
  • 74
user902691
  • 1,149
  • 4
  • 20
  • 46
  • Please elaborate why this answers the question. think about adding link to documentation and maybe some code examples. – Yotam Omer Jul 01 '13 at 16:22
0

As Philipp Sanders said you can use a singleton which runs a method at startup of the application context that uses reflection on a class. Thats for the validation part.

To get all classes in a given package implementing an interface, have an annotation or extend a class you can use the component scanner of spring.

Check out this link for a scanner possibility:

http://javaasylum.blogspot.fr/2011/05/annotation-scanner-with-spring.html?m=1

Martin Frey
  • 10,025
  • 4
  • 25
  • 30
-1

you could write a validator that checks the values via reflection. you run this validator at first in your application.

Philipp Sander
  • 10,139
  • 6
  • 45
  • 78