I have an endpoint where a user can register with her email/password. However I, want to check that the password is not empty, but I also want to only deserialize the password, because I do not want to send it back to the client.
Domain
public class User {
@NotEmpty
private String email;
@JsonProperty(access = Access.WRITE_ONLY)
@NotEmpty
private String password;
// Getters and setters
...
}
Endpoint
@Path("/register")
@POST
public Response register(@Valid User user) {
...
}
Instead of the Access.WRITE_ONLY
I've also tried @JsonIgnore
on the getter and @JsonProperty
on the setter.
The problem is Hibernate Validator keeps complaining that the password is empty, even when I POST a user with password set:
"{"errors":["password may not be empty"]}"
How can I fix this? Or do I have to implement my own NotEmpty validation logic in the endpoint?
This can be done using validation groups. Here is how you would achieve this:
public class GroupValidationTest {
public static void main(String[] args) {
Validator v = Validators.newValidator();
Model m = new Model();
m.user = "Harry";
m.password = "Potter";
Set<ConstraintViolation<Model>> validate = v.validate(m, INPUT.class);
System.out.println(validate.size());
validate = v.validate(m, INPUT.class, OUTPUT.class);
System.out.println(validate.size());
validate = v.validate(m, OUTPUT.class);
System.out.println(validate.size());
m.password = null;
validate = v.validate(m, INPUT.class, OUTPUT.class);
System.out.println(validate.size());
validate = v.validate(m, OUTPUT.class);
System.out.println(validate.size());
}
public static class Model {
@NotEmpty(groups={INPUT.class, OUTPUT.class})
public String user;
@NotEmpty(groups={INPUT.class})
public String password;
}
public interface INPUT {}
public interface OUTPUT {}
}
This outputs:
0 -> Full object, validate INPUT
0 -> Full object, validate INPUT + OUTPUT
0 -> Full object, validate OUTPUT
1 -> null password, validate INPUT + OUTPUT
0 -> null password, validate OUTPUT
Explenation:
Hibernate validator framework supports groups for validation constraints. They are used to tell the validator which groups to validate in a specific validation attempt. You can read all about it here:
What I did in my code example is:
INPUT
and OUTPUT
For the REST aspect (different question), usually validation of input and ouput is done by an interceptor, typically the MessageBodyReader and Writer class. These are responsible for reading user input and writing it out. You can read about that on the jersey docs page.
You can then implement your own validation reader/writer that knows to only validate INPUT
when reading user input, while only validating OUTPUT
when writing the serialised body back.
I hope that helps,
artur