GWT 2.5 RC2 EntityProxy Validation

235 views
Skip to first unread message

Daniel Mauricio Patino León

unread,
Oct 12, 2012, 11:29:10 PM10/12/12
to google-we...@googlegroups.com
Hello there.

I have a question of wich is the best option to validate my domain objects on the client side with RequestFactory.

It's posible to validate a Proxy with the new Validation of 2.5 RC2 ?

If i do a validation of my proxy don't get any constraints violations.

What i did to get a work arround of this was move the anoations to my proxy:

@ProxyFor(value=Employee.class, locator=EntityLocator.class)
public interface EmployeeProxy extends EntityProxy {
@NotNull(message="Cannot be empty.")
@Size(min = 4, message = "Name must be at least 4 characters long.")
public String getFirstName();
        /* ......................   */
}

Then i implemented that interface on my domain object.


@Entity
public class Employee extends EntityBase implements EmployeeProxy {
      @Column(nullable = false)
      private String firstName;
      @Override
public String getFirstName() {
return firstName;
}
       /* ......................   */
       @Override
public EntityProxyId<?> stableId() {
return null;
}
}


Now i get validation on the client side with:

EmployeeRequest request = requestFactory.employeeRequest();
EmployeeProxy employeeProxy = request.create(EmployeeProxy.class);
request.addNewEmployee(employeeProxy);
driver.edit(employeeProxy, request);
Set<ConstraintViolation<EmployeeProxy>> violations = validator.validate(employeeProxy);
System.out.println(violations);


and also on the server side when i click on save button with this:


driver.flush().fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
Window.alert("Succeed");
}
@Override
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
//ConstraintViolation<?> violation = violations.iterator().next();
//Window.alert(violation.getMessage() + " " +violation.getPropertyPath().toString());
for(ConstraintViolation<?> violation: violations){
if(violation.getPropertyPath().toString().equals("age")){
ageError.setText(violation.getMessage());
}else if(violation.getPropertyPath().toString().equals("firstName")){
firstNameError.setText(violation.getMessage());
}else if(violation.getPropertyPath().toString().equals("lastName")){
lastNameError.setText(violation.getMessage());
}
}
// ... others
}
});


I this correct?

This can cause problems ?


thank you.

Jens

unread,
Oct 13, 2012, 9:03:52 AM10/13/12
to google-we...@googlegroups.com
Doesn't look that wrong. You need to add validation annotations to the proxy class if you want to do client side proxy validation. 

As you want to reuse the validation annotations on the server I would think about defining an additional interface IEmployee so that your server Employee class do not have to implement the EmployeeProxy. Your server Employee is not an EmployeeProxy so it should not implement that interface. I guess its better to do:

interface IEmployee {
  //methods with validation annotations, probably with client and server validation groups.
}

interface EmployeeProxy extends EntityProxy, IEmployee {
  EntityProxyId<EmployeeProxy> stableId();
}

class Employee implements IEmployee {
 //implement methods.
}

Downside is that your EmployeeProxy now always has the same methods as your server Employee and sometimes that is not desired as a proxy could only represent be a subset of the server class. But in that case you could create an additional lite interface:

interface IEmployeeLite {
  //subset of methods with validation annotations
}

interface IEmployee extends IEmployeeLite {
  //rest of the methods with validation annotations
}

interface EmployeeProxy extends EntityProxy, IEmployeeLite {
  //now only contains subset of employee methods.
}

class Employee implements IEmployee {
 //implementation
}


Thats not tested by myself, but I think RequestFactory and the Validation framework should be able to handle this.

-- J.

Alex opn

unread,
Nov 5, 2012, 1:10:34 PM11/5/12
to google-we...@googlegroups.com
I just tried to implement clientside validation like that and ran into the problem that I get "Incompatible return types" for @OneToMany etc. associations as one has to use the Proxy types as return types in the Proxy interfaces and the Entity interfaces in the Entity interfaces. Anyone has an idea how it could be possible to get around that? :)

Jens

unread,
Nov 5, 2012, 3:31:30 PM11/5/12
to google-we...@googlegroups.com
Ouch! Totally forgot that you have to return the proxy on client side :( Well in that case you probably have to duplicate your validation annotations or implement the proxy interface in your entity as mentioned above. I would go with duplication as the entity shouldn't be a proxy. It should be relatively easy to write a small generator tool that generates proxies for your entities and copies all validation annotations to the proxy interface. Maybe someone has already done it on github/google code.

-- J.

Thomas Broyer

unread,
Nov 6, 2012, 4:13:59 AM11/6/12
to google-we...@googlegroups.com


On Monday, November 5, 2012 9:31:30 PM UTC+1, Jens wrote:
Ouch! Totally forgot that you have to return the proxy on client side :( Well in that case you probably have to duplicate your validation annotations or implement the proxy interface in your entity as mentioned above. I would go with duplication as the entity shouldn't be a proxy. It should be relatively easy to write a small generator tool that generates proxies for your entities and copies all validation annotations to the proxy interface. Maybe someone has already done it on github/google code.

Couldn't you simply override the methods and refine the return type? (Java has covariant return types)

interface Employee {
  Employee getBoss();
}

interface EmployeeProxy extends Employee, EntityProxy {
  EmployeeProxy getBoss();
}

class EmployeeEntity implements Employee {
  @Override
  public EmployeeEntity getBoss() { … }
}

Jens

unread,
Nov 6, 2012, 4:47:05 AM11/6/12
to google-we...@googlegroups.com
Sounds like the rescue ;-) Indeed that works.

-- J.

Chris Lercher

unread,
Nov 6, 2012, 6:55:33 AM11/6/12
to google-we...@googlegroups.com
On Tuesday, November 6, 2012 10:13:59 AM UTC+1, Thomas Broyer wrote:

Couldn't you simply override the methods and refine the return type? (Java has covariant return types)

interface Employee {
  Employee getBoss();
}

interface EmployeeProxy extends Employee, EntityProxy {
  EmployeeProxy getBoss();
}

class EmployeeEntity implements Employee {
  @Override
  public EmployeeEntity getBoss() { … }
}


It gets more difficult for setters though:

  interface Employee {
    ...
    void setBoss(Boss boss);
  }

can't be implemented in Java by

  class EmployeeEntity implements Employee {
    @Override
    public void setBoss(BossEntity boss) { … }
  }

So you could use generics

  interface Employee<B extends Boss> {
    ...
    void setBoss(B boss);
  }

  class EmployeeEntity implements Employee<BossEntity> {
    @Override
    public void setBoss(BossEntity boss) { … }
  }


However, once I tried this (with GWT 2.5.0), it led to an Exception (only when I define setters) - sorry, I don't exactly remember which Exception it was, and I'm a little bit short of time at the moment to pursue it further. (Maybe related to http://code.google.com/p/google-web-toolkit/issues/detail?id=5762 ?)
Reply all
Reply to author
Forward
0 new messages