mardi 25 août 2015

Custom annotation on method argument is not being executed

I have implemented a custom annotation @Password to perform validation on an argument of my method setPassword(). The annotation is defined like this:

// Password.java
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import javax.validation.*;

@Target({METHOD, FIELD, PARAMETER, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
@Documented
public @interface Password {
    String message() default PasswordValidator.message;
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

And the current implementation of the validator is this:

// PasswordValidator.java
package utils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class PasswordValidator implements ConstraintValidator<Password, String> {

    /* Default error message */
    final static public String message = "error.invalid.password";

    /**
    * Validator init
    * Can be used to initialize the validation based on parameters
    * passed to the annotation.
    */
    public void initialize(Password constraintAnnotation) {
        System.out.println("in initialize()");
    }

    public boolean isValid(String string, ConstraintValidatorContext constraintValidatorContext) {
        System.out.println("in isValid()");
        return false;
    }
}

Note that in the current implementation isValid() always returns false. The reason will be apparent shortly.

My usage of the validator is in a class User. For brevity I won't post the whole source here, but the relevant parts are:

package models;

import utils.Password;
// other imports omitted


@Entity
@Table(name = "users", schema="public")
public class User {

    @Required
    private String password;

    ...

    public void setPassword(@Password String clearPassword) {
        try {
            this.password = HashHelper.createPassword(clearPassword);
        } catch (AppException e) {
            e.printStackTrace();
        }
    }

    ...
}

The basic idea is that I use the User class to store a hashed password for a user, but before setting the hashed password, I (would like to) run validation on the unhashed password (i.e. clearPassword).

The problem I am having is that this validation is not taking place. In the current implementation, it should (according to my understanding) always throw a ConstraintViolationException because isValid() always returns false, but this is not the case.

I have checked that the annotation is being attached to the method argument by calling (in another part of the application) something along the lines of:

Method method = user.getClass().getMethod("setPassword", new Class[] { String.class });
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
System.out.println(method.getName() + ": " + parameterAnnotations[0][0]);

which produces the following output:

setPassword:@utils.Password(message=error.invalid.password, payload=[], groups=[])

So this tells me the annotation is being applied to the method argument. But I can't understand why I'm not getting the ConstraintViolationException when I actually call the method. I also never see the output "in initialize()" or "in isValid()" that I added to these methods as a check to see if they're being fired.

As another test, I also added the @Password annotation to the member variable password in User.class. This causes the ConstraintViolationException to be thrown as expected, e.g. when I try to persist a User object.

Can anyone shed light as to why the annotation on the method argument is not working properly? Thanks in advance!



from Newest questions tagged java - Stack Overflow http://ift.tt/1LynrdF
via IFTTT

Aucun commentaire:

Enregistrer un commentaire