Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Conditional Validation
PostPosted: Wed Aug 04, 2010 9:49 am 
Newbie

Joined: Wed Aug 04, 2010 9:36 am
Posts: 1
Hi all,

First of all, thanks to Emmanuel for leading the spec. This is a major step forward for reusing business validation logic in different tiers and in a standard way. I hope there will be a 1.1 and 2.0 verion of this spec!

We read both the doc and the forum and We've not found a proper way to do conditional validation. Perhaps we missed the point how to do that.

Our business case is quite simple. We need to validate a bean containing MSISDN and IMSI (telecom industry). We need to ensure that at least one field is valid.

Code:
public class MyBean {

    private String msisdn;

    private String imsi;
}


For validating MSISDN we've created a composite annotation:

Code:
@NotBlank
@Pattern(regexp="^\\d{12}$")
@ReportAsSingleViolation
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface MSISDN {

    String message() default "{com.acme.domain.constraint.MSISDN.message}";

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

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

}


And we did the same for IMSI:

Code:
@NotBlank
@Pattern(regexp="^\\d{15}$")
@ReportAsSingleViolation
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface IMSI {

    String message() default "{com.acme.domain.constraint.IMSI.message}";

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

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


Then we created the custom constraint for validating the bean:

Code:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {AtLeastOneValidValidator.class})
@Documented
public @interface AtLeastOneValid {

    String message() default "{com.acme.interfaces.ws.constraint.AtLeastOneValid.message}";

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

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


And the related validator that we'd want to implement:

Code:
public class AtLeastOneValidValidator implements ConstraintValidator<AtLeastOneValid, Object> {

    @Override
    public void initialize(AtLeastOneValid constraintAnnotation) {
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

   String str = (String) BeanUtils.getProperty(value, "msisdn");

   // Dynamic validation of our composite constraint
        AnnotationDescriptor<MSISDN> descriptor = new AnnotationDescriptor<MSISDN>(MSISDN.class);
        MSISDN msisdn = AnnotationFactory.create(descriptor);

   // This class does not exist yet
//        CompositeConstraintValidator<MSISDN, String> validator = new CompositeConstraintValidator<MSISDN, String>();
//        validator.initialize(msisdn);
//
//        if (validator.isValid(str, context)) {
//            return true;
//        } else {
//
//
//        }
    }
}


We expected to find out a Validator class (see the code of our AtLeastOneValidValidator) in the framework for validating composite constraint (e.g. CompositeConstraintValidator) and we've not found a related class to do that. So, is this a lack of the framework? I'm quite sure the framework needs the same logic for validating composite constraints, but perhaps the code is spread out among several classes.

We know that if we implement MSISDN and IMSI validator we could use them in AltLeastOneValidValidtor. But as we define our constraints with composite constraint we want to reuse them (DRY principle).

If someone knows the trick to do the same thing in different and simplier way, we are interested in.

Any help would be greatly appreciated,

Regards,
Alexandre


Top
 Profile  
 
 Post subject: Re: Conditional Validation
PostPosted: Tue Aug 10, 2010 3:32 am 
Newbie

Joined: Tue Aug 10, 2010 1:57 am
Posts: 2
Try this one may helps you to solve out your problem # models/user.rb
validates_presence_of :password, :if => :should_validate_password?
validates_presence_of :country
validates_presence_of :state, :if => :in_us?
attr_accessor :updating_password

def in_us?
country == 'US'
end

def should_validate_password?
updating_password || new_record?
end

# in controller
@user.updating_password = true
@user.save

# or...
@user.save(false)

_________________
live casino games


Top
 Profile  
 
 Post subject: Re: Conditional Validation
PostPosted: Wed Aug 18, 2010 5:02 pm 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 176
alexandre.garino wrote:
We expected to find out a Validator class (see the code of our AtLeastOneValidValidator) in the framework for validating composite constraint (e.g. CompositeConstraintValidator) and we've not found a related class to do that. So, is this a lack of the framework? I'm quite sure the framework needs the same logic for validating composite constraints, but perhaps the code is spread out among several classes.

We know that if we implement MSISDN and IMSI validator we could use them in AltLeastOneValidValidtor. But as we define our constraints with composite constraint we want to reuse them (DRY principle).

If someone knows the trick to do the same thing in different and simplier way, we are interested in.

Any help would be greatly appreciated,

Regards,
Alexandre


Alexandre, that's an interesting scenario. I don't know how the validation routine is integrated into your app, but if your are initiating validation yourself, you might validate your bean using Validator#validate() and checking afterwards, you don't see a ConstraintViolation for msisdn *and* imsi in the result. You wouldn't need the additional class-level constraint then.

Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
 Post subject: Re: Conditional Validation
PostPosted: Sun Feb 27, 2011 11:52 am 
Newbie

Joined: Sun Feb 27, 2011 11:40 am
Posts: 8
Don't use @NotBlank on the two fields. If you think about it, that annotation is incorrect here since it says that *each* field must be nonblank.

Then, your class validation should assert only that at least one field is not null. That way, you don't need to invoke the complex ConstraintValidator. A null/empty check is simple.

Finally, the @Pattern says that *if* the field is nonnull then it must be valid. (You may have to change the pattern to allow empty string.) Per JSR 303 recommendation, custom validations should treat null/empty as valid; it's up to you to add a separate null check, in your case with the class validator. So yes, you missed the point a little bit (but not much).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 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.