Re: Cross field validation on client

619 views
Skip to first unread message

Joseph Lust

unread,
Oct 31, 2012, 2:59:29 PM10/31/12
to google-we...@googlegroups.com
Consider a framework like GWT Validation, or roll your own (example of Editor framework. Typically, it is up to you to validate your form fields. You can use Vaadin, GXT, or SmartGWT to do this for you, but then you have to accept the rest of those frameworks which is pretty heavy if you just want to ensure those passwords match and are non-null.

Using some onChange handlers it should be pretty simple to show inline warnings on password entry. While it is more work out the gate, I often find it easier to do my own validation than to have to been the validation I want to do to someone else's framework.


Sincerely,
Joseph

Jens

unread,
Oct 31, 2012, 3:06:06 PM10/31/12
to google-we...@googlegroups.com
Haven't tried it yet but as GWT BeanValidation has implemented the JSR303 TCK tests you should be able to create custom validation annotations and a corresponding validator.

That way you would end up having something like

@ValidPassword(repeat = "repeatPassword") //custom annotation that links to the repeat password field
String password;

@NotNull
String repeatPassword;

The validator for @ValidPassword would check against your password policies and also check the "repeatPassword" field. This should work on the server too.

-- J.



Am Dienstag, 30. Oktober 2012 12:43:57 UTC+1 schrieb Hans:
Hi,

I'm building a registration form with two password fields being validated on client side using GWT Validation framework.

Is there any constraint for doing so (validating a value against another field)? Or what's the best way to implement this (should work on server, too)?

Benjamin Possolo

unread,
Oct 31, 2012, 5:22:28 PM10/31/12
to google-we...@googlegroups.com
I am not familiar with the GWT Validation framework.
I'm not really sure why people use it considering vanilla GWT supports JSR303 (the documentation is pretty bad admittedly).

Using plain GWT you would have a class-level validation annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordsEqualValidator.class)
@Documented
public @interface PasswordsEqual {
        
        String DEFAULT_MESSAGE = "Passwords must be the same";

        String message() default DEFAULT_MESSAGE;
        
        Class<?>[] groups() default {};

        Class<? extends Payload>[] payload() default {};
}

Then you would need a custom validator. Mine looks like this:

public class PasswordsEqualValidator implements ConstraintValidator<PasswordsEqual, CreateAccountBean> {

        @Override
        public void initialize(PasswordsEqual constraintAnnotation) {}
        
        @Override
        public boolean isValid(CreateAccountBean value, ConstraintValidatorContext context) {
                
                if( value == null )
                        return true;
                
                String password = value.getPassword();
                String confirmPassword = value.getConfirmPassword();
                
                if( password == null && confirmPassword == null )
                        return true;
                
                if( password != null && password.equals(confirmPassword) )
                        return true;
                
                return false;
        }
}

Then annotate the javabean class being validated with @PasswordsEqual

This works on the client and server.

Joseph Lust

unread,
Oct 31, 2012, 7:41:31 PM10/31/12
to google-we...@googlegroups.com
I'm not really sure why people use it considering vanilla GWT supports JSR303 (the documentation is pretty bad admittedly).

Good point. After digging, found the brand new 2.5 validation docs. That should help. However, I can still see how even your simple example seems rather complex to just test at A==B.


Sincerely,
Joseph

Zied Hamdi OneView

unread,
Aug 20, 2014, 8:09:17 AM8/20/14
to google-we...@googlegroups.com
Hi,

I was looking at the link http://www.gwtproject.org/doc/latest/DevGuideRequestFactory.html#validation , and it's not clear when the validation is executed. it seams it is executed each time data is sent to the server!!???. If it's the case, this could be a performance problem since we might have some complex validation processes that we want to execute only when we call some service methods (in a perfect world we would be able to decide on the client or server side if we want to execute a validation or skip it).

this is really an issue because RequestFactory is thought as a rigid architecture : the user entered data can be reused only if the validation failed (otherwise the EntityProxy becomes frozen, and there's no easy way to duplicate an EntityProxy). So the best way to check a precondition constraint is in the validation process. The issue is that you have the choice between two scenarios: 
  • You can do your checks in a specific service method, throw an exception and handle that in the onFailure() client side method. But!!! you cannot reuse the EntityProxy anymore since it's frozen
  • You can do your checks in the validation phase, so you can keep your EntityProxy reuasable, But!!! the validation is made each time you send data to the server (which can be a hard resource consumption issue)
So the question is: is there a way to controle whether the server side validation process has to be made? (a per service method configuration or a runtime check switch)?

Any suggestions are welcome, and thanks for reading

Thomas Broyer

unread,
Aug 20, 2014, 8:54:23 AM8/20/14
to google-we...@googlegroups.com


On Wednesday, August 20, 2014 2:09:17 PM UTC+2, Zied Hamdi OneView wrote:
Hi,

I was looking at the link http://www.gwtproject.org/doc/latest/DevGuideRequestFactory.html#validation , and it's not clear when the validation is executed. it seams it is executed each time data is sent to the server!!???.

Yes.
 
If it's the case, this could be a performance problem since we might have some complex validation processes that we want to execute only when we call some service methods (in a perfect world we would be able to decide on the client or server side if we want to execute a validation or skip it).

The idea is that you only validate those things that MUST be validated (and for that, you just put them in the default group, and other constraints in other groups; or you put them in a specific group and you use a ServiceLayerDecorator with an overridden validate() method to validate only that specific group).
 
this is really an issue because RequestFactory is thought as a rigid architecture : the user entered data can be reused only if the validation failed (otherwise the EntityProxy becomes frozen, and there's no easy way to duplicate an EntityProxy). So the best way to check a precondition constraint is in the validation process. The issue is that you have the choice between two scenarios: 
  • You can do your checks in a specific service method, throw an exception and handle that in the onFailure() client side method. But!!! you cannot reuse the EntityProxy anymore since it's frozen
  • You can do your checks in the validation phase, so you can keep your EntityProxy reuasable, But!!! the validation is made each time you send data to the server (which can be a hard resource consumption issue)
So the question is: is there a way to controle whether the server side validation process has to be made? (a per service method configuration or a runtime check switch)?

I'm sure you can come up with clever tricks to pass some value down to a ServiceLayerDecorator's validate() method (e.g. through a request header, or appending data to the payload and stripping it in a servlet filter).

I'm rather supportive of RF but it doesn't fit everyone's use-case (well, using only ValueProxies makes it a good replacement for GWT-RPC with an added batching feature, at the expense of bigger payloads but without the hassle of serialization policies).
Wrt validation, RF works best if you restrict validation to "per field" (value ranges, patterns, etc.) or otherwise fast checks, and allow invalid data (wrt. other (business) constraint violations) to be persisted, along with a valid/invalid flag of some sort. Then depending on the valid/invalid flag you can decide whether some actions on the persisted data are possible or not. Actually, that's the approach that best fits "the web", because you don't want to "get in the way" of the user and risk all his "work" to be lost (browser crash, broken connectivity, etc.): when I tell you to save, just save, when I tell you to "act", feel free to refuse if the saved data is wrong. It generally requires totally rethinking the way you work with data and the way you store it, so it might only be possible in greenfield projects with enough budget and sufficiently skilled architects/developers.
The alternative is to "flush" data (and edit()) into your proxies only when needed; that way you can just "flush" again in newly-edit()ed proxies should an error happen (if you use the Editor framework, that means *not* using the RequestFactoryEditorDriver; you could use "edit on write" proxies that read from frozen RF proxies and only edit() and write into RF proxies on flush; or you could copy data from the RF proxies to "view model" objects, and then edit the RF proxies and copy back again just before fire()ing the request)

Zied Hamdi OneView

unread,
Aug 21, 2014, 4:46:49 AM8/21/14
to google-we...@googlegroups.com
Hi Thomas,

Thanks for your detailed answer, here are my thoughts:

 
If it's the case, this could be a performance problem since we might have some complex validation processes that we want to execute only when we call some service methods (in a perfect world we would be able to decide on the client or server side if we want to execute a validation or skip it).

The idea is that you only validate those things that MUST be validated (and for that, you just put them in the default group, and other constraints in other groups; or you put them in a specific group and you use a ServiceLayerDecorator with an overridden validate() method to validate only that specific group).

To be more specific, I have to check two shops don't enter the same name. This happens only when the user activates a special Ui to change his shop name (not a frequent operation by nature). Therefore I was surprized we cannot configure which group has to be associated with which service (I understand that by default it's automatically the default group that has to be triggered, it's useless to configure each service to use the default group validation), but at some point we should be able to decide that a given service has to work with another group. A better solution would be to have a single check point façade that can be configured on server side that dynamically decides whether validation must occur and with which group (the default implementation would always point to the default group, but that would be an extention point). 

Do you think I should enter a feature request with this or is there already something happening in GWT internally?
 
 
this is really an issue because RequestFactory is thought as a rigid architecture : the user entered data can be reused only if the validation failed (otherwise the EntityProxy becomes frozen, and there's no easy way to duplicate an EntityProxy). So the best way to check a precondition constraint is in the validation process. The issue is that you have the choice between two scenarios: 
  • You can do your checks in a specific service method, throw an exception and handle that in the onFailure() client side method. But!!! you cannot reuse the EntityProxy anymore since it's frozen
  • You can do your checks in the validation phase, so you can keep your EntityProxy reuasable, But!!! the validation is made each time you send data to the server (which can be a hard resource consumption issue)
So the question is: is there a way to controle whether the server side validation process has to be made? (a per service method configuration or a runtime check switch)?

I'm sure you can come up with clever tricks to pass some value down to a ServiceLayerDecorator's validate() method (e.g. through a request header, or appending data to the payload and stripping it in a servlet filter).

Sure I can come up with something, but in my opinion it's over engeneering for a small benefit (especially that this will at best "impact performance", and at worse "insert hard to detect/fix bugs to the entire app"). It's like asking a car driver to use a screwdriver to set up the position of his seat :)
 
I'm rather supportive of RF but it doesn't fit everyone's use-case (well, using only ValueProxies makes it a good replacement for GWT-RPC with an added batching feature, at the expense of bigger payloads but without the hassle of serialization policies).
Wrt validation, RF works best if you restrict validation to "per field" (value ranges, patterns, etc.) or otherwise fast checks, and allow invalid data (wrt. other (business) constraint violations) to be persisted, along with a valid/invalid flag of some sort. Then depending on the valid/invalid flag you can decide whether some actions on the persisted data are possible or not. Actually, that's the approach that best fits "the web", because you don't want to "get in the way" of the user and risk all his "work" to be lost (browser crash, broken connectivity, etc.): when I tell you to save, just save, when I tell you to "act", feel free to refuse if the saved data is wrong. It generally requires totally rethinking the way you work with data and the way you store it, so it might only be possible in greenfield projects with enough budget and sufficiently skilled architects/developers.
The alternative is to "flush" data (and edit()) into your proxies only when needed; that way you can just "flush" again in newly-edit()ed proxies should an error happen (if you use the Editor framework, that means *not* using the RequestFactoryEditorDriver; you could use "edit on write" proxies that read from frozen RF proxies and only edit() and write into RF proxies on flush; or you could copy data from the RF proxies to "view model" objects, and then edit the RF proxies and copy back again just before fire()ing the request)
I think this is not tied to RF globally but rather to RF's validation module specifically, which can be improoved. Actually since validation happens server side, it's better to configure it on the server side too, there's no need to send addition data from the client to say how something should be validated. If a special case raises, the client developer can still create a new service method for that specific need.
 

Zied Hamdi OneView

unread,
Aug 21, 2014, 4:59:32 AM8/21/14
to google-we...@googlegroups.com
The idea is :

"Since GWT is rigid in "when things should happen" (phases), it should be more permissive in how you manage each step"

Since it imposes that validation must happen only the validation phase, it should allow to better tune how you do your validation.

Don't get me wrong, it's a very great thing that GWT's RF imposes an architecture, this is suited for bigger teams and allows a faster understanding of any GWT solution for newcomers on a project. but therefore it become an enterprise solution that has to provide some enterprise services. It comes to my mind that RF is for GWT what JEE is for Spring (or for raw java). Since in Jee each EJB has its own rules and restrictions, enough stuff to cover the needs in the restricted world of each ejb must be provided (too much restriction makes the architecture unusable)

Thomas Broyer

unread,
Aug 21, 2014, 5:42:49 AM8/21/14
to google-we...@googlegroups.com


On Thursday, August 21, 2014 10:46:49 AM UTC+2, Zied Hamdi OneView wrote:
 
Do you think I should enter a feature request with this or is there already something happening in GWT internally?

Nothing's happening right now on RF.
You can file a feature request, but be aware that it's unlikely I would contribute the code (I can't tell for Manolo, the other assigned maintainer for the RF module; see https://groups.google.com/d/topic/google-web-toolkit-contributors/eq0LsmH2blw/discussion) so you'd probably have to contribute the patch.



On Thursday, August 21, 2014 10:59:32 AM UTC+2, Zied Hamdi OneView wrote:
The idea is :

"Since GWT is rigid in "when things should happen" (phases), it should be more permissive in how you manage each step"

Since it imposes that validation must happen only the validation phase, it should allow to better tune how you do your validation.

This is similar to what I proposed a couple years back about loading the entities: you could optimize your database requests if you knew which things will be needed (e.g. use different fetch groups in JPA to switch between loading relationships lazily or eagerly). It still hasn't happened, and now that I'm an entitled maintainer for RF I don't even know how that could be done "correctly". It's a can of worms. I fear that the validation case you're raising can quickly become a can of worms; and RF is almost already itself a can of worms, so I'm quite reluctant to add features to it… (remember: once introduced, features have to be maintained, and when you're an assigned maintainer, people will held you responsible for the maintenance)

Zied Hamdi OneView

unread,
Aug 21, 2014, 1:51:55 PM8/21/14
to google-we...@googlegroups.com
 Hi Thomas,

Thanks for the visibilty you gave me on what is happening. Actually I can't propose any atch since i've invested 3 years of my time on a project and i need to publish it and get back some money from it, otherwise I'll need to step back professionally and work again as a consultant (boring life :) . So sorry if I'm only complaining, without helping. It's just that I can't afford it for now

Best regards,

Thomas Broyer

unread,
Aug 22, 2014, 8:34:25 AM8/22/14
to google-we...@googlegroups.com
Oh you don't have to be sorry, and I hope you didn't take it personally or as an incentive to not file the feature request on the tracker !
I'm just trying to be frank and transparent about what's happening, absolutely not trying to discourage you in continuing to rant/complain or file feature requests (or bugs)

(note: my 10-month-old son is still taking way too much time than I'd like and I'm very busy at work too, so I can't contribute to GWT as much as I'd want, and I prioritize Google Groups, StackOverflow and issue triaging above reviewing code and above contributing code –I couldn't even attend the SC meeting yesterday–; and when I contribute, I unfortunately don't have enough time available "in a row" to be able to contribute or code-review the complex pieces that are –in increasing order of complexity– the Editor framework, AutoBeans or RequestFactory).
Reply all
Reply to author
Forward
0 new messages