Playframework IllegalStateException after form validation
playframework, playframework-2.0, validation
Solution
It's a bug on play. If your form implements validate just make sure the method returns null whenever there are no errors. If you return an empty map then it will fail
Problem
I tried to write a custom form validator for play 2.0.1 using JSR-303 annotation (class-level) and validator implementations. Unfortunately, when i submit the form and validation fails i get an IllegalStateException that might be a play's bug (but i would like to confirm). Please find below the relevant code extracts and the problem description (only relevant parts for clarity's sake) Part of the controller code (receiving the form submit) ``` public static Result save() { Form<UserForm> userForm = form(UserForm.class).bindFromRequest(); if (userForm.hasErrors()) { return badRequest(createForm.render(userForm)); } UserForm user = userForm.get(); ``` The validator is declared as ``` public class FieldMatchValidator extends Validator<Object> implements ConstraintValidator<FieldMatch, Object> ``` The validation annotation is declared as ``` @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = FieldMatchValidator.class) @play.data.Form.Display(name="constraint.fieldmatch") public @interface FieldMatch { String message() default FieldMatchValidator.message; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; ``` Submitting the form i get the error ``` Caused by: java.lang.IllegalStateException: No value at play.libs.F$None.get(F.java:217) ~[play_2.9.1.jar:2.0.1] at play.data.Form.get(Form.java:363) ~[play_2.9.1.jar:2.0.1] at controllers.UsersController.save(UsersController.java:40) ~[classes/:2.0.1] at Routes$$anonfun$routes$1$$anonfun$apply$25$$anonfun$apply$26.apply(routes_routing.scala:189) ~[classes/:na] at Routes$$anonfun$routes$1$$anonfun$apply$25$$anonfun$apply$26.apply(routes_routing.scala:189) ~[classes/:na] at play.core.Router$HandlerInvoker$$anon$4$$anon$1.invocation(Router.scala:1086) ~[play_2.9.1.jar:2.0.1] ``` The mentioned UsersController's line is the call UserForm user = userForm.get(); Trying to understand where the problem is i found that the offending code is probably in play's Form.java. The Form bind(Map data, String... allowedFields) contains: ``` if(result.hasErrors()) { for(FieldError error: result.getFieldErrors()) { ... } return new Form(rootName, backedType, data, errors, None()); } ``` And the hasErrors() is ``` public boolean hasErrors() { return !errors.isEmpty(); } ``` What happens is that result.hasErrors() returns true (because the validator defined at class level failed), but the built errors list remains empty (result.getFieldErrors() returns an empty list). As a consequence Form.hasErrors() returns false but Form.get() fails. Am i missing something or is it actually a bug ? Thanks and regards,