Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: better Constraint interface
PostPosted: Mon Sep 01, 2008 12:03 pm 
Beginner
Beginner

Joined: Thu Apr 17, 2008 5:47 pm
Posts: 26
I think that the current constraint interface
Code:
public interface Constraint<A extends Annotation> {
    /**
     * Initialize the constraint validator.
     * <p/>
     * This method is guaranteed to be called once right after the constraint is retrieved
     * from the <code>ConstraintFactory</code> and before the Bean Validation provider
     * starts using it.
     *
     * @param constraintAnnotation The constraint declaration
     */
    void initialize(A constraintAnnotation);

    /**
     * Evaluates the constraint against a value. This method
     * must be thread safe.
     *
     * @param value The object to validate
     * @return false if the value is not valid, true otherwise
     * @throws IllegalArgumentException The value's type isn't understood
     *                                  by the constraint validator
     */
    boolean isValid(Object value);
}


sets unacceptable limits to constraint objects :

1. Wasting memory instantiating the constraint class each time it is used
Solved in : http://forum.hibernate.org/viewtopic.php?p=2394200
for non-initializable constraints which need the annotation metadata: ctx.getConstraintDescriptor()

All others can be solved via introducing ValidationContext,ValidationListener and changing the Contraint interface to:
Code:
public interface Constraint {

   public void validate(ValidationContext ctx);
}


Code:
public interface ValidationContext<T> {

   public Class<T> getBeanClass();

   public Object getBean();

   public T getRootBean();

   public void setBean(Object bean);

   public void setBeanClass(Class<T> beanClass);

   public String getPropertyName();

   public void setPropertyName(String propertyName);

   public Object getPropertyValue();

   public void setPropertyValue(Object propertyValue);

   public Annotation getConstraintDescriptor();

   public void setConstraintDescriptor(Annotation constraintDescriptor);

   public ValidationListener getValidationListener();

   public ValidatorFactory getValidatorFactory();

   /**
    * Cascade validation to the current property if available.
    */
   public void cascade();

   /**
    * Cascade validation to the specified bean.
    *
    * @param bean - a new validation root bean
    */
   public void cascade(Object bean);

   public Stack<String> getPath();

   public boolean isValidated(Object bean);

   /**
    *
    * @param bean
    * @return false if the object was already validated, true - the object is added
    */
   public boolean addValidated(Object bean);

}


Code:
public interface ValidationListener {
    /**
     * Error notification sent by a Constraint.
     *
     * @param reason    a constant describing the reason. This is normally the key of the
     * feature that was violated in the object 'owner' for property 'propertyName'
     * @param context   - contains
     *      bean =         the object that contains the error (owner)
     *      propertyName = the Name of the attribute that caused the error
     */
    void addError(InvalidConstraint reason, ValidationContext context);
}


2. Type constraints error messages : http://forum.hibernate.org/viewtopic.php?t=986340
I think there is a problem with the error messages a type (class level) constraint can generate.
The field/property constraint usually has a single error message template, but a type constraint can validate more than one thing (multiple sub-constraints), so it will need to generate more then one error message.
With the current API this seems to be impossible.

solved via:
ctx.getValidationListener().addError(new InvalidConstraint(...), ValidationContext ctx);

3. Stop validation routine on first validation failure
solved via: throwing exception on the first call of the ctx.getValidationListener().addError(...)

4. Unable to delegate validation to a known validator
solved via: ctx.getValidatorFactory().getValidator(...)
Note that we need this, because each context can use differently configured validator instances!

5. Unable to cascade validation to the current property
solved via: ctx.cascade();

6. Unable to cascade validation to another object graph
solved via: ctx.cascade(bean);

7. Unable to access and manage already validated beans to prevent cycles
solved via: ctx.addValidated(bean)

8. Unable to intercept each indirect bean validation
This can be solved adding method in ValidationListener (or in a separate interface)
Code:
/**
    * Called before every constraint.validate(...) invocation.
    *
    * @param ctx
    * @return true - do validate the current property/bean, false - skips the current validation
    */
   boolean preValidate(ValidationContext<?> ctx);


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

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.