Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: Conditional or dependent Validation
PostPosted: Tue Aug 04, 2009 9:10 am 
Newbie

Joined: Tue May 29, 2007 5:00 am
Posts: 3
Location: Immenstaad/Bodensee, Germany
Hi,

I have the following problem:

Example: An order object may have different states (Offer, Invoiced, Payed...) Dependent on this state, different validation rule should be applied. In the state Offer there are no special rules, in the state invoiced, the customer must be set and in the state paid, a payment method must be set.

Other Example: Different validaiton rules for ZIP codes or telephone numbers, dependent on the country. In Germany a ZIP is a five digit number, in the UK it is a combination of digits and characters. So I'd like a rule like if country code equals 'DE' than apply the German ZIP rules, if country code is 'UK', than apply the rules for Greate Britain.

A bit more abstract: Only of a specific condition (that may involve the value of several attributes within the same class or maybe also attributes in the object graph) becomes true, specific validation rule should be applied.

Greetings
Jens


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Tue Sep 22, 2009 7:25 am 
Newbie

Joined: Thu Aug 27, 2009 8:21 am
Posts: 13
I have exactly the same problem. It would be really useful if, in a field level validation, the object being validated were to be passed as part of the validation context (ConstraintValidatorContext).

I've only been looking at the JSR and RI for a few days, so I could be talking out of my arse here, so if I am feel free to correct me -- we live to learn :-) But...

I have read the spec, the forum, and looked at the examples, and they all point at class level validation for this problem. It looks to me as if class level validation is an inelegant and inapropriate solution to this problem. I would like the validation to fail on a field level, not at the class level.

When most UIs interpret the collection of constraint violations they must indidicate to the user the fields that need attention -- I can't see how to do this with class level validation. That is, I can't see how, at class level, it's possible to create a violation for a field (or number of fields) once state based validation has failed. Also, why should I have to write a new annotation and new validation class just to perform a single, simple, state based validation of a single field? This looks like overkill to me.

This seems like a pretty basic requirement. Insisting that all fields are validated in isolation seems wrong to me.

In fact, I'd go as far as to say that if the object being validated is not passed as part of the validation context, then jsr303 will be useless. I've already decided that I can't use it on my current, huge project (£50m, >5 years, major corporation). This is a shame, as I had high hopes for this spec, and most of the other decisions that have been made on it seem quite rational.

Bryan


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Tue Sep 29, 2009 11:57 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
As we discussed on another forum and to adjust the examples to your problem:

The spec allows to add what you call violation to a field (in a class level ConstraintValidator). Actually to any element in the subpath including a particular element of an indexed collection. see the examples below.

Section 2.4 of the spec http://people.redhat.com/~ebernard/vali ... ementation Example 2.14.


Code:
class AddressValidator implements ConstraintValidator<NormalizedAddress, Address> {
    void initialize(NormalizedAddress constraint) {}
    boolean isValid(Address address, ConstraintValidatorContext context) {
        if (address == null) return true;
        boolean isValid = true;
        Country country = address.getCountry();
        if (country.getISO2Code().equals("FR")) {
            String zipCode = address.getZipCode();
            if ( zipCode.length != 5 ) {
                isValid = false;
                context.disableDefaultError();
                context.buildErrorWithMessageTemplate("{com.acme.NormalizedAddress.zipcodeInvalidFR}")
                          .addSubNode("zipCode")
                          .addError();
            }
        }
        return isValid;
    }
}


so with an address set to France and a zipcode like "1234"
we would end up with a constraint violation like that
ConstraintViolation<Address>
message: The zipcode should be of 5 characters.
messageTemplate: {com.acme.NormalizedAddress.zipcodeInvalidFR}
rootBean: address instance
leafBean: address instance
String representation of propertyPath: zipCode
invalidValue: address instance
constraintDescriptor: the @NormalizedAddress constraint descriptor.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Tue Sep 29, 2009 12:04 pm 
Newbie

Joined: Thu Aug 27, 2009 8:21 am
Posts: 13
Emmanuel has explain to me, on another forum, that the following code demonstrates cross-field validation (validation of one field within the context of another).

Code:
//default path
context.buildErrorWithMessageTemplate( "this detail is wrong" )
             .addError();

//default path + "street"
context.buildErrorWithMessageTemplate( "this detail is wrong" )
             .addSubNode( &quot;street&quot; )
             .addError();

//default path + "addresses["home"].country.name"
context.buildErrorWithMessageTemplate( "this detail is wrong" )
             .addSubNode( "addresses" )
             .addSubNode( "country" )
             .inIterable().atKey( "home" )
             .addSubNode( "name" )
             .addError();


This certainly looks powerful, but I don't yet understand it thoroughly. I won't go into the problems I have with the use of the term, 'error' where no such thing exists, because that's a different issue :-)

Okay, my first thought is that this doesn't seem to be refactorable. If, in your example, the field country were to be refactored to something else, then this code would appear to still be acceptable, despite the fact that there is no longer a subNode called country.

Also, is it acceptable to have many class-level constraints? I seem to remember reading somewhere that it isn't, but perhaps I'm wrong?

Thanks for your time answering these questions Emmanuel.

Bryan


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Tue Sep 29, 2009 2:56 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hi

What would be a better name than error? You have 24h to find it before we freeze the APIs

You are correct that's not safely refactorable unfortunately due to the lack of method literal in Java. I don't see any non broken solution to work around that.

I see no problem with having many class-level constraints. I am not sure where this rumor come from :)

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Tue Sep 29, 2009 3:55 pm 
Newbie

Joined: Thu Aug 27, 2009 8:21 am
Posts: 13
Hi,

As there's been no error, and the code isn't creating an error object, and (from your post above) it does seem to be configuring the ConstraintViolation, perhaps it should just be called configureWithPath(), and configureWithMessageTemplate(). And, perhaps these two things should be kept separate, or perhaps overloaded simply as configure() which could take one, or the other, or both?

And, if you don't mind me whinging on about names for a minute, why is it 'subNode'? I mean, I get it, but isn't really just node you're adding? Surely the 'sub' bit is down to context? :-)

Refactoring: A colleage suggested to me last week that we might use cglib in a similar way to Mockito and Easymock, to create a proxy that can return the java.lang.reflect.Method of the method who's path we want. Something like:

Code:
Method streetMethod = new PathGenerator(Address).getStreet();


I haven't looked into it in detail yet, but it seems like a solid approach. From the method you could generate a string, if that's what you needed.

Also, if you don't mind me saying -- that's a dreadful implementation of a French postcode validator :-p

Bryan


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Wed Sep 30, 2009 4:51 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
bryan.dollery wrote:
As there's been no error, and the code isn't creating an error object, and (from your post above) it does seem to be configuring the ConstraintViolation, perhaps it should just be called configureWithPath(), and configureWithMessageTemplate(). And, perhaps these two things should be kept separate, or perhaps overloaded simply as configure() which could take one, or the other, or both?


configure is too vague as we intend to extend the API in future revisions of the spec. We need to convey in the name that:
- we override the messageTemplate and not the message for example
- we need to say that this leads to the creation of a ConstraintViolation

buildConstraintViolationWithMessageTemplate (long) / addConstraintViolation
buildConstraintViolationWithTemplate / addConstraintViolation
buildViolationReportWithMessageTemplate / addViolationReport or addReport
buildViolationReportWithTemplate / addViolationReport or addReport
?



Quote:
And, if you don't mind me whinging on about names for a minute, why is it 'subNode'? I mean, I get it, but isn't really just node you're adding? Surely the 'sub' bit is down to context? :-)

The reason I used subNode and not node is because this path is relative to the path of the constraint currently validated and I wanted to convey this notion.
I could be convinced easily convinced "node" is a better name :)

Quote:
Refactoring: A colleage suggested to me last week that we might use cglib in a similar way to Mockito and Easymock, to create a proxy that can return the java.lang.reflect.Method of the method who's path we want. Something like:

Code:
Method streetMethod = new PathGenerator(Address).getStreet();


I haven't looked into it in detail yet, but it seems like a solid approach. From the method you could generate a string, if that's what you needed.

Nope. Though of it. It does not work for private methods or fields.
The only current solution is to use what JPA 2 is using ie generating a metamodel using an AnnotationProcessor. Let's see if that sticks before jumping this bandwagon.

Quote:
Also, if you don't mind me saying -- that's a dreadful implementation of a French postcode validator :-p

Well, it's valid :)

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Wed Sep 30, 2009 5:33 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
emmanuel wrote:
bryan.dollery wrote:
As there's been no error, and the code isn't creating an error object, and (from your post above) it does seem to be configuring the ConstraintViolation, perhaps it should just be called configureWithPath(), and configureWithMessageTemplate(). And, perhaps these two things should be kept separate, or perhaps overloaded simply as configure() which could take one, or the other, or both?


configure is too vague as we intend to extend the API in future revisions of the spec. We need to convey in the name that:
- we override the messageTemplate and not the message for example
- we need to say that this leads to the creation of a ConstraintViolation

buildConstraintViolationWithMessageTemplate (long) / addConstraintViolation
buildConstraintViolationWithTemplate / addConstraintViolation
buildViolationReportWithMessageTemplate / addViolationReport or addReport
buildViolationReportWithTemplate / addViolationReport or addReport
?


After discussing it with Hardy, we chose Error initially because it was the shortest name that conveyed the idea of violation. "report" does not so we would have to go for ViolationReport or ValidationReport which are quite long.

Also we have favored a fluent API to method overloading for clarity.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Wed Sep 30, 2009 8:45 am 
Newbie

Joined: Thu Aug 27, 2009 8:21 am
Posts: 13
Quote:
buildConstraintViolationWithMessageTemplate (long) / addConstraintViolation
buildConstraintViolationWithTemplate / addConstraintViolation
buildViolationReportWithMessageTemplate / addViolationReport or addReport
buildViolationReportWithTemplate / addViolationReport or addReport
?

After discussing it with Hardy, we chose Error initially because it was the shortest name that conveyed the idea of violation. "report" does not so we would have to go for ViolationReport or ValidationReport which are quite long.

Also we have favored a fluent API to method overloading for clarity.


If I were to be asked to choose, I'd probably go for: buildConstraintViolationWithMessageTemplate(). Because it's actually building a ConstraintViolation object.

You're right about the fluent api -- it's a good idea that makes everything easier, but that doesn't mean that we only have to have one method for building the constraint violation. As it is, if I want to only change the path, the method I'd use is buildErrorWithMessageTemplate, despite my not needing to change the message template. Perhaps two methods: buildConstraintViolationWithMessageTemplate(), which allows both message templates and paths, and buildConstraintViolationWithPath(), which behaves just like buildConstraintViolationWithMessageTemplate, except that you wouldn't start with the message template (but, I suppose you could allow it anyway).

Keep up the good work.

Bryan


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Wed Sep 30, 2009 11:15 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
bryan.dollery wrote:
If I were to be asked to choose, I'd probably go for: buildConstraintViolationWithMessageTemplate(). Because it's actually building a ConstraintViolation object.


Hardy thinks that as well, I will probably change it.

Quote:
You're right about the fluent api -- it's a good idea that makes everything easier, but that doesn't mean that we only have to have one method for building the constraint violation. As it is, if I want to only change the path, the method I'd use is buildErrorWithMessageTemplate, despite my not needing to change the message template. Perhaps two methods: buildConstraintViolationWithMessageTemplate(), which allows both message templates and paths, and buildConstraintViolationWithPath(), which behaves just like buildConstraintViolationWithMessageTemplate, except that you wouldn't start with the message template (but, I suppose you could allow it anyway).


I see your point though I don't think this use case is that common. It is solvable already can be solved as we expose the default "error" message in CVC.
If I end up being wrong we can add it in a future version. Removing would be impossible.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Wed Sep 30, 2009 3:10 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
http://opensource.atlassian.com/project ... e/BVAL-186

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Thu Oct 01, 2009 3:16 am 
Newbie

Joined: Thu Aug 27, 2009 8:21 am
Posts: 13
Nice one. Thanks for the help Emmanuel. I've refactored my application back to using the jsr now. The major benefit to me is that my service API will, now, only expose entities with references to standard libraries, so that a client needent use any third-party libraries.

Loving the hibernate RI too. I'm looking forward to the first release.

BTW: I'm working right now for a large multi-national, and we've got a big team writing their new core order management and processing system that will be used by the majority of the 80,000 strong global team. It's a big project that will take us five years to complete and which is costing in excess of £50m. It's all cool-tech (spring, hibernate, SOA, Mockito, etc.). We're now planning to use your jsr, and the hibernate RI, for all our validation needs.

Thanks,

Bryan


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Thu Oct 01, 2009 10:32 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Sweet. Glad I could help.
PS: how can you dare say that Spring is cool when JSR 299 is about to go out ;)

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Conditional or dependent Validation
PostPosted: Thu Dec 10, 2009 1:58 pm 
Newbie

Joined: Thu Dec 10, 2009 11:45 am
Posts: 1
Hi,

First thanks a lot for the quick response concerning my comment on the Jira issue HV-38, about conditional validation.

http://opensource.atlassian.com/project ... tion_34899

it seems the conditional validation using @NotNull(apply-if) wont be implemented in hibernate validators 4.x.
I'd like to know if conditional validation using annotations will be standardize in JSR-303, or if there exists, or if there are specs for a generic solution(i-e performing conditional validation without having to implement a specific validator)

Thanks a lot


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 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:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.