Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do client side validation with annotated rules on domain classes (RequestFactory)?

I've been developing a project with GWT 2.4 and looking for a way to validate (JSR 303) my client (proxy) classes without recreate annotations from my domain classes (server side). I know that there is an example suplied with GWT trunk code (validation), but it doesn't use RequestFactory, it uses RPC.

Is it possible to take validations from domain classes on client side? Would it be the best strategy share my domain model with client code??

As far as I know, GWT team was working on this feature on 2.3 and 2.4. Is it already done, or should I wait for GWT 2.5?

This was already posted on GWT Forum, but it is still without answer.

https://groups.google.com/forum/#!msg/google-web-toolkit/au_GCy_9WZQ/6296p5TcWdoJ

Thanks.

Edit: This is how would it be validation on client side (not tested)...

@UiHandler("save")
void onSave(ClickEvent event) {
    Modulo modulo = new Modulo(); //domain class
    Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    Set<ConstraintViolation<Modulo>> violations = validator.validate(modulo, Default.class);
    delegate.saveClicked();
}
like image 852
André Salvati Avatar asked May 11 '12 18:05

André Salvati


2 Answers

Best option that I've found is to wait. GWT team is still working on client side validation and it's due end of summer.

http://code.google.com/p/google-web-toolkit/wiki/BeanValidation

Comment by project member [email protected], Apr 10, 2012:

"I have a plan to finish implementing the spec this summer."

As this application does not have much input data, I have chosen to do the validation only on the server.

like image 64
André Salvati Avatar answered Oct 17 '22 12:10

André Salvati


Found a (temporary) solution to use the same validation annotations on the client and on the server with RequestFactory:

Put the JSR 303 annotations in a separate interface that is implemented by both the proxy interface (client) and the domain classes (server). This interface must be in the shared package, of course.

Since the validation annotations will automatically be passed down the inheritance hierarchy, validation should now work on the client as well as on the server.

Example

Here is an example of an object used when a User attempts to register:

UserProxyValid is the common interface containing the JSR 303 validation annotations:

public interface UserProxyValid  {

  @NotBlank(
      groups = {ClientGroup.class, ServerGroup.class})
  @UniqueEmail(
      groups = {ServerGroup.class})
  String getEmail();

  @NotBlank(
      groups = {ClientGroup.class, ServerGroup.class})
  @Size(
      min = 4, max = 25,
      groups = {ClientGroup.class, ServerGroup.class})
  String getPassword();
}

User is the domain class on the server:

public class User implements UserProxyValid {

  private String email;
  private String password;

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }
}

And finally the UserProxy for the client:

@ProxyFor(value = User.class)
public interface UserProxy extends ValueProxy, UserProxyValid {

  String getEmail();
  void setEmail(String email);

  String getPassword();
  void setPassword(String password);
}

Groups

With groups we can make shure that individual validations are either done on the client or on the server only or on both. (As in the example above, validation on uniqueness of email can only be done on the server.)

This is how you would validate an object on the client:

Validator clientValidator = Validation.buildDefaultValidatorFactory().getValidator();
    Set<ConstraintViolation<UserProxy>> violations = clientValidator.validate(userProxy, ClientGroup.class);

And here is how validation is done on the server:

Validator serverValidator = Validation.buildDefaultValidatorFactory().getValidator();
    Set<ConstraintViolation<User>> violations = serverValidator.validate(user, ServerGroup.class);

Hope for the Future

Of course, it would be better without the additional UserProxyValid class. So as soon as Google provides an update on BeanValidation, we might be able to eliminate that class and move the annotations to the domain class.

like image 25
Marco Jakob Avatar answered Oct 17 '22 13:10

Marco Jakob