-->
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.  [ 2 posts ] 
Author Message
 Post subject: extra validation context information
PostPosted: Thu Jun 19, 2008 3:31 pm 
Newbie

Joined: Thu Jun 19, 2008 1:18 pm
Posts: 1
Location: San Francisco, CA
I have to collect extra information from my Constraint<A ext Ann> implementations. Why?
Because, I want to deal with complex objects and be able to report validation parameters using those objects.

Code:
class Measurement {
   ...
   Context context;   // duration, distance, so on
   Unit unit;
   double value;
}


Now, suppose, I have a validation annotation that wants to validate a Measurement for a particular Measurement context.
Provided that ContextKeys and UnitKeys are enums.

Code:
@ContextRange(context = ContextKeys.DISTANCE, unit = UnitKeys.MILE, min = 1 , max = 100)
Measurement measurement;


Moving on to the constraint implementation. This is where I translate the annotation and do some useful work.

Code:
class ContextRangeConstraint<ContextRange> impl Constraint<ContextRange
   Measurement min;
   Measurement max;
   
   public void initialize(ContextRange ctxRange) { // translate into the min and max }

   public boolean isValid(Object o) {
      ... // check the range using Measurement convenience methods
      ... // o.lessThan(min) and o.greaterThan(max)
   }
}


My messages are personalized based on user preferences. In other words, my business constraints might be
specified in 'miles' but that's not very useful to the end user who's from Germany. I need to personalize
my measurement objects at the presentation tier (web services). That's the only place, I will actually know
who that user is and the adequate locale. Hence, I want to pass along with my ValidationException not just what
failed the validation (InvalidConstraint<T> which has its own problems, since Throwable can't be extended by anything
generic), but also the reasons for failure such as the constraints of a particular validation instance.
Code:
@ContextRange(context = ContextKeys.DISTANCE, unit = UnitKeys.MILE, min = 1 , max = 100)
Measurement measurement;


But I'm a user who enters his measurements in kilometers. Hence, I shouldn't get miles in error messages.
Quote:
"Distance measurement range exceeded. Should be between 1.6 and 160.0 km."
Never-mind the silly rounding.

Since, I need to form the final message away from the validation framework, in the presentation tier. I need the
converted Measurement min, max. So that my Personalizer can convert and display them properly.
Clearly, I need some kind of hook back to the ContextRangeConstraint that contains those objects.

Currently, I use the property name from InvalidConstraint to go back and look through all the Constraint implementations
inside which I declare what should be considered a part of the ValidationContext using a custom @MesssageParameter
annotation and reflection.

Code:
class ContextRangeConstraint<ContextRange> impl Constraint<ContextRange
   @MessageParameter(key = "min")
   Measurement min;
   @MessageParameter(key = "max")
   Measurement max;
   
   // but these keys get fully qualified "org.p7k.example.ContextRangeConstraint.min"
}

In the end I have a Map<String,Object> with which I can do work now.
If I have a message that has "{org.p7k.example.ContextRangeConstraint.min}" I can replace
that placeholder with a personalized Measurement.

------------

This works but is very cumbersome (the degree of this post factum ValidationContext collection cumbersomeness depends on
the implementation). For example I can't do something like:

Code:
@ContextRanges({@ContextRange(context = ContextKeys.DISTANCE, ...),
            @ContextRange(context = ContextKeys.DISTANCE, ...)})


Since, my Map<String, Object> will contain the 'min' and 'max' for the last ContextRange checked not the one that actually
failed.

However, I feel that the spec creates some fundamental limitations.

InvalidConstraint despite its name only describes the property that failed. The reason for failure is only conveyed
through the message. I would like to see a hook to get the Constraint implementation from which I could ask for more
contextual information (similar to how StatdardConstraintDescriptor works).

Perhaps, the internal reporting using a boolean instead of some validation report:

Code:
public ValidationReport validate(Object o){}
instead of
Code:
public boolean isValid(Object o){}
could help.

Please, let me know your thoughts and ask follow-up questions.

BTW, I've been working with the agimatec implementation (Thank you!).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 15, 2008 11:15 am 
Beginner
Beginner

Joined: Thu Apr 17, 2008 5:47 pm
Posts: 26
Hi, here http://forum.hibernate.org/viewtopic.php?t=986340 I have already mentioned about the limitation for the invalid constraints..

I have combined some ideas from the hibernate and agimatec validator and currently my validation framework is based on these interfaces:

Code:
public interface Constraint<A extends Annotation> {

   public void validate(ValidationContext<?> ctx);
}


Code:
/**
*
* Initializable constraint. Needs to be instantiated for each constraint
* annotation descriptor.
*
  */
public interface ExtendedConstraint<A extends Annotation> extends Constraint<A> {

   public void initialize(A constraintDescriptor);
}


Code:
public interface ValidationListener {
    /**
     * Error notification sent by a Constraint.
     */
    void addInvalidConstraint (InvalidConstraint reason, ValidationContext context);
}



So that when a constraint wants to report an error it does it this way:

Code:
public void validate(ValidationContext<?> ctx) {
   //...
   invalidConstraint = ...
   ctx.getValidationListener().addInvalidConstraint (invalidConstraint, ctx);
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.