You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Igor Drobiazko <ig...@gmail.com> on 2010/01/07 20:07:27 UTC

Re: svn commit: r896767 - in /tapestry/tapestry5/trunk: tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ tapestry-beanvalidator/src/main/resourc

Hi Thiago,

ValidationConstraintGenerator is invoked when the default binding for
validators is created.The generated validation contraints are used for both
server-side and client-side validation.Because of some differences between
JSR-303 validators and Tapestry validator you can't invoke a JSR-303
validator when default bindings are created. It's just too early.

In contrast client-side validation constraints should be created very early
in order to render the javascript. That's why we need some mechanism to map
constraint annotations to javascript methods. ValidationConstraintGenerator
is not appropriate for JSR-303 validators. First of all because of the
differences between @Vaidate and a bunch of JSR-303 validators.

In Tapestry we have a single annotation (@Validate) that has the only one
attribute 'value'. In JSR-303 there is a bunch of annotations,
each with *several* attributes. A Tapestry validator can only have a
*single* constraint: e.g. maxlength=1 or min=5 whereby JSR-validator can
have
several constraints. The annotation @Size for example has 'min' and 'max'
attributes, the annotation @Digit has attributes 'integer' and 'fraction',
etc. These different attributes have to be passed to the client-side
validator. If you examine the annotation of a property you can detect it as
a JSR-303 annotation but you don't know which attributes you need to pass to
javascript. For this purpose there is the 3rd parameter in
ClientConstraintDescriptor's constructor (which is an ellipsis). For example
in case of @Size one would create such a contribution:

    public static void contributeClientConstraintDescriptorSource(
            final Configuration<ClientConstraintDescriptor> configuration)
    {
        configuration.add(new ClientConstraintDescriptor(Size.class, "size",
"min", "max"));
    }

The error message of the JSR-303 constraint is also defined inside the
annotation. You have to interpolate (MessageInterpolator#interpolate) the
message and pass the result to the javascript function in order to have the
same error message for server-side and client-side validation.

All this is just impossible inside ValidationConstraintGenerator and
FieldValidatorSource.

In summary I would say that the validation mechanism of Tapestry and JSR-303
differ more than I would expect. I tried many things and experimented a lot.
You can believe me that I tried to prototype different approaches to come up
with the best possible solution. The current implementation is the result of
these experiments.


On Thu, Jan 7, 2010 at 12:19 PM, Thiago H. de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> Hi, Igor!
>
> Aren't you recreating ValidationConstraintGenerator here? If you associate
> the @NotNull with the required validation through a contributed
> ValidationConstraintGenerator, for example, it will automatically add this
> validation at the client side. What do you think?
>
> --
> Thiago H. de Paula Figueiredo
> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,
> and instructor
> Owner, software architect and developer, Ars Machina Tecnologia da
> Informação Ltda.
> http://www.arsmachina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Best regards,

Igor Drobiazko
http://tapestry5.de/blog

Re: svn commit: r896767 - in /tapestry/tapestry5/trunk: tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/ tapestry-beanvalidator/src/main/java/org/apache/tapestry5/internal/beanvalidator/ tapestry-beanvalidator/src/main/resourc

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
Em Thu, 07 Jan 2010 17:07:27 -0200, Igor Drobiazko  
<ig...@gmail.com> escreveu:

> Hi Thiago,

Hi!

> ValidationConstraintGenerator is invoked when the default binding for
> validators is created.The generated validation contraints are used for  
> both server-side and client-side validation.

Ok!

> Because of some differences between
> JSR-303 validators and Tapestry validator you can't invoke a JSR-303
> validator when default bindings are created. It's just too early.

I have a package in the Ars Machina Project that integrates Hibernate  
Validator 3 annotations by implementing ValidationConstraintGenerators  
that look at the property annnotations.

> In contrast client-side validation constraints should be created very  
> early in order to render the javascript. That's why we need some  
> mechanism to map constraint annotations to javascript methods.  
> ValidationConstraintGenerator is not appropriate for JSR-303 validators.  
> First of all because of the
> differences between @Vaidate and a bunch of JSR-303 validators.

The out-of-the-box ValidationConstraintGenerators use the @Validate  
annotation, but you can add more implementations that take a look at other  
annotations.

> In Tapestry we have a single annotation (@Validate) that has the only one
> attribute 'value'. In JSR-303 there is a bunch of annotations,
> each with *several* attributes. A Tapestry validator can only have a
> *single* constraint: e.g. maxlength=1 or min=5 whereby JSR-validator can
> have several constraints.

You can generate more than one Tapestry validation for a single property.  
And don't forget that the ValidationConstraintGenerator is a pipeline  
service.

> The annotation @Size for example has 'min' and 'max'
> attributes,

In this specific case, you can implement it as a single  
ValidationConstraintGenerator:

final public class SizeValidationConstraintsGenerator implements  
ValidationConstraintGenerator {

	@SuppressWarnings("unchecked")
	public List<String> buildConstraints(Class propertyType,  
AnnotationProvider annotationProvider) {

		List<String> validations = null;
		Size size = annotationProvider.getAnnotation(Size.class);
		
		if (size != null) {
			
			validations = new ArrayList<String>();
			validations.add(String.format("min=%d", size.min()));
			validations.add(String.format("max=%d", size.max()));
			
		}
		
		return strings;

	}

}

> The error message of the JSR-303 constraint is also defined inside the
> annotation. You have to interpolate (MessageInterpolator#interpolate) the
> message and pass the result to the javascript function in order to have  
> the same error message for server-side and client-side validation.

Now you've convinced me. :)

> In summary I would say that the validation mechanism of Tapestry and  
> JSR-303 differ more than I would expect. I tried many things and  
> experimented a lot. You can believe me that I tried to prototype  
> different approaches to come up with the best possible solution. The  
> current implementation is the result of these experiments.

I believe you. ;) Keep up the good work!

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, software architect and developer, Ars Machina Tecnologia da  
Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org