Uploaded image for project: 'Isis'
  1. Isis
  2. ISIS-491

Integrate JSR-349 validation.

    XMLWordPrintableJSON

    Details

    • Type: New Feature
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: core-1.2.0
    • Fix Version/s: 2.10.0
    • Component/s: Core
    • Labels:
      None

      Description

      as per http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/

      The reference implementation (Hibernate Validator) is Apache licensed [1].

      ~~~
      Implementation: should not be too difficult; mostly a matter of writing some FacetFactories.

      It may not make sense to use every feature of JSR-349...

      • constructor parameters
      • constraint groups

      1. In Isis bootstrapping, get hold and cache the Validator. (This is thread-safe, so could perhaps be global; maybe as a new top-level component cf AuthorizationManager etc).

      ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
      validator = factory.getValidator();
      

      and also

      executableValidator = validator.forExecutables();
      

      Validating a property change can be done using:

      Set<ConstraintViolation<Car>> constraintViolations = validator.validateValue(
              Car.class,
              "manufacturer",
              null
      );
      
      assertEquals( 1, constraintViolations.size() );
      assertEquals( "may not be null", constraintViolations.iterator().next().getMessage() );
      

      (nb: using validator.validateProperty(...) would mean that the value has been applied already).

      eg this would be a facet that implements ValidatingInteractionAdvisor and acts on a ValidityContext of type PropertyModifyContext. (eg subclass PropertyValidateFacetAbstract)

      2. Validating a parameter of an action can be done using:

      Car object = new Car( "Morris" );
      Method method = Car.class.getMethod( "drive", int.class );
      Object[] parameterValues = { 80 };
      Set<ConstraintViolation<Car>> violations = executableValidator.validateParameters(
              object,
              method,
              parameterValues
      );
      
      assertEquals( 1, violations.size() );
      Class<? extends Annotation> constraintType = violations.iterator()
              .next()
              .getConstraintDescriptor()
              .getAnnotation()
              .annotationType();
      assertEquals( Max.class, constraintType );
      

      This would be in a Facet that implements ValidatingInteractionAdvisor and acts on a ValidityContext of type ActionInvocationContext (eg subclass ActionValidationFacetAbstract)

      ~~~
      There are also some new features that could be implemented:

      3. validating the return value of an action:

      Car object = new Car( "Morris" );
      Method method = Car.class.getMethod( "getPassengers" );
      Object returnValue = Collections.<Passenger>emptyList();
      Set<ConstraintViolation<Car>> violations = executableValidator.validateReturnValue(
              object,
              method,
              returnValue
      );
      
      assertEquals( 1, violations.size() );
      Class<? extends Annotation> constraintType = violations.iterator()
              .next()
              .getConstraintDescriptor()
              .getAnnotation()
              .annotationType();
      assertEquals( Size.class, constraintType );
      

      This would need to be done after the action has been invoked; if the constraint failed, then an exception would be thrown causing the transaction to be aborted. This might require a new subclass of ValidityContext, eg ActionReturnValueContext.

      4. cf ISIS-479, all dirtied objects should be validated prior to commit.
      a) we re-validate all properties (using the value of the property as the proposed value). This would be done using InteractionUtils, called from isAssociationValid with a ValidityContext of PropertyModifyContext.
      b) we validate the object, ie InteractionUtils, with all with a ValidityContext of ObjectValidityContext.

      We would then have a new facet, implementing ValidatingInteractionAdvisor and acting on an ObjectValidityContext (eg subclass ValidateObjectFacetAbstract); which should perform:

      Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );
      

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              danhaywood Daniel Keir Haywood
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:

                Time Tracking

                Estimated:
                Original Estimate - 72h
                72h
                Remaining:
                Remaining Estimate - 72h
                72h
                Logged:
                Time Spent - Not Specified
                Not Specified