-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Contextual Validation
PostPosted: Mon Aug 18, 2008 12:17 pm 
Newbie

Joined: Tue Aug 14, 2007 8:01 pm
Posts: 4
I put this question to Emmanuel via email, and he suggested we continue the conversation here. My original question is quoted below:
Quote:
Hi Emmanuel,

I have a question about JSR-303. One of Jason Carreira's original goals was to support contextual validation - where different validations would apply to a domain object depending on the context (e.g. UI versus batch processing). Having looked over the public draft, its not clear to me if this is possible. I see that groups could be used for this purpose, however that forces the domain object to know about all contexts in which it is to be used. There are plenty of use cases where this is not possible. For example, if I use a library containing JSR-303-annotated domain objects whose code I cannot alter, but I wish to overlay additional validations - I can't see how to do that with JSR-303.

I use the Stripes Web Framework, and the way it achieves contextual validation is allow a bean to define validations for nested properties. Examples here.

Does JSR-303 support this use-case? Am I missing something?

Thanks,

Chris.


Top
 Profile  
 
 Post subject: Contextual Validation
PostPosted: Mon Aug 18, 2008 12:20 pm 
Newbie

Joined: Tue Aug 14, 2007 8:01 pm
Posts: 4
Emmanuel's response:
Quote:
Hi Chris

The problem with Stripes is that their @Validation annotation is not extensible. I cannot write my own constraint @MyEmail. To allow custom constraints they have to rely on marking some methods as @ValidationMethod on their ActionBean.

Stripes approach would work if Java annotations were not so constrained but unfortunately you cannot do
@ValidationOverride(property="address.email", validations = { @NotNull, @MyEmail } )
This would not compile.

Groups is the best solution to your problem and assumes that you can changes those classes (ie add the annotations). If you cannot change the classes (usually for political reasons), the XML descriptor is your fallback option. XML is certainly not as sexy but if you think about it, you cannot override the actual classes: if you need to put your declations out of the domain model, why not in XML (you lost the domain model centric approach already anyway).

PS: there are a lot of bad reasons to have different set of constraints between batch and UI. This usually creates problems down the road. The obvious one is: should I raise a validation exception if a batch-inserted data set is subsequently edited by the UI?

PPS if you want to continue this conversation, let's go to http://forum.hibernate.org/viewforum.php?f=26, to get more pairs of eye :)

--
Emmanuel Bernard


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 18, 2008 1:14 pm 
Newbie

Joined: Tue Aug 14, 2007 8:01 pm
Posts: 4
Emmanuel,

The problem with the groups approach is that, for a typical application, it forces some of the responsibilities (or at least knowledge) of the View/Controller layers down into the Model layer. In my original question I talked about the scenario where the domain objects could not be modified due to being part of a 3rd party library. But even if I do have the ability to modify the domain objects, the groups approach increases coupling and causes additional development traffic through popular domain objects such as a User class.

I think the clash here is the difference between data invariants and business rules. I don't think anybody would disagree that invariants are ideally built-in to the data, but requiring the embedding of business rules into the data is a problem. You mentioned that XML is a way to externalize the validation metadata, and yes, the XML approach is not that sexy. However it does imply that other external representations of validation metadata could be used - so why not do this with JSR-303 annotations that support a separation of concerns?
Quote:
The problem with Stripes is that their @Validation annotation is not extensible. I cannot write my own constraint @MyEmail. To allow custom constraints they have to rely on marking some methods as @ValidationMethod on their ActionBean.

Actually Stripes does allow this and its a common practice. I don't want to makes this thread a Stripes comparison, but for interest's sake, Stripes supports this by allowing the developer to specify a TypeConverter in the validation annotation. A TypeConverter either converts a string to an instance of the required class, or it produces validation errors. To write my own "MyEmail" constraint, I create a MyEmailTypeConverter, and then I can use it within a Stripes ActionBean like so:

Code:
public class UserRegistration implements ActionBean {
    @ValidateNestedProperties({
        @Validate(field = "emailAddress",
                  required = true,
                  converter = MyEmailTypeConverter.class)})
    private User user;
    // ...
}

So Stripes ActionBeans can overlay contextual validation rules onto their bean properties. The domain objects don't know anything about the validation rules. Stripe's weakness in this area, in my opinion, is that it doesn't easily allow these validation rules to be reused, and its something I hoped JSR-303 would make possible. What I hoped for was the ability to mix domain invariants (annotated within the domain classes) with business rules (defined within non-domain classes that make use of the domain classes).
Quote:
PS: there are a lot of bad reasons to have different set of constraints between batch and UI. This usually creates problems down the road. The obvious one is: should I raise a validation exception if a batch-inserted data set is subsequently edited by the UI?

Agreed. I just brought it up because Jason used this example for contextual validation in one of the early JSR-303 announcements.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 21, 2008 8:44 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Sorry for the delay in replying.
I would like to state a few things though. At the end of the day, constraints are different than business rules and unfortunately the frontier is not clear between the two. I would hate to see people shoehorn too much into validations.

To answer you use case, as long as your controller is a POJO, you can apply the Bean Validation logic to it (as opposed to your domain model). In your case the UserRegistration could get its user field validated by bean validation (probably through an interceptor). In addition to that, Bean Validation will try to provide an API to validate method parameters (we need to sit down and design that though)

Code:
public class UserRegistration implements ActionBean {
    @Email(property="email") //validate user.email as an email
    private User user;
    // ...
}


The drawback of this method is that your @Email annotation has to manually go apply the constraint to the property: there is no built-in system for it.

But I really don't full understand why a controller or a view should apply more rules than the model knows. What are the fundamental reason for doing so? It's not as elegant as you cannot reuse it in a different controller / view (duplication). And let's imagine that a valid reason exists, it sounds that it would awfully look like a traditional business rule. A classing service class would serve this purpose quite well.

PS in your stripes example, it seems you are hijacking the converter infrastructure to do validation. That does not sound right :)

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 22, 2008 1:14 am 
Newbie

Joined: Tue Aug 14, 2007 8:01 pm
Posts: 4
Quote:
To answer you use case, as long as your controller is a POJO, you can apply the Bean Validation logic to it (as opposed to your domain model). In your case the UserRegistration could get its user field validated by bean validation (probably through an interceptor). In addition to that, Bean Validation will try to provide an API to validate method parameters (we need to sit down and design that though)

The code example (with the property attribute) is closer to what I'm getting at. Contextual beans with domain model beans as properties could superimpose validations down onto those beans. The contextual bean might be a Struts FormBean, a Stripes ActionBean or a Swing PresentationModel class.
Quote:
The drawback of this method is that your @Email annotation has to manually go apply the constraint to the property: there is no built-in system for it.

It would be fair to assume that this responsibility would be part of the UI framework, whether it be Spring MVC, Struts or a rich client platform shell like those derived from Eclipse or NetBeans. The UI framework would leverage validation annotations by evaluating them automatically and take care of mapping the errors to form fields etc.
Quote:
But I really don't full understand why a controller or a view should apply more rules than the model knows. What are the fundamental reason for doing so?

Encapsulation. I'd be keeping the validation rules for a certain context close to the place where they're relevant. And I'm not arguing that these additional validation rules should specifically go in the controller or view, just that there would be value in being able to superimpose them from some external bean. I already mentioned other reasons this would be desirable:
1. You might not have any control over the domain object in question.
2. The domain object might be a central part of a complex system where it is used in so many contexts that maintaining many different annotations and groups within that one class becomes too difficult.
Quote:
It's not as elegant as you cannot reuse it in a different controller / view (duplication). And let's imagine that a valid reason exists, it sounds that it would awfully look like a traditional business rule. A classing service class would serve this purpose quite well.

Let's be clear, I'm talking about things like "Not Null", "Valid Email" etc. and I'm arguing that groups should not be the only way to achieve contextual validation. For reuse, you would create a contextual shell bean that might represent, say, a commonly used form, or abstract parent to a set of similar forms. To make this work, the JSR-303 spec would need to explicitly include the "property" attribute as an optional parameter. The implementation would take the property string and apply the validation to the (arbitrarily deep) property.
Quote:
PS in your stripes example, it seems you are hijacking the converter infrastructure to do validation. That does not sound right :)

That is how it works with Stripes. The Stripes TypeConverter interface defines a means to collect validation errors and that is how all of Stripes standard validations work, and user-defined ones plug in the same way. Because Stripes maps strings from the HTTP request to bean properties, there will be times when a given type cannot be fulfilled because the string that's being converted is invalid. I didn't design it, but I presume this is why type conversion and validation are intertwined in Stripes.
Code:
public interface TypeConverter<T> {
   // ... snip ...
   T convert(String input, Class<? extends T> targetType,    Collection<ValidationError> errors);
}

One last question: If I have a string property where in one context it must be at least 5 characters long, and in another context it must be at least 10 characters long, is JSR-303 as it currently stands able to support that?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.