Uploaded image for project: 'Causeway'
  1. Causeway
  2. CAUSEWAY-491

[Wish] Integrate JSR-349 validation.

Attach filesAttach ScreenshotAdd voteVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Wish
    • Status: Open
    • Minor
    • Resolution: Unresolved
    • core-1.2.0
    • None
    • 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

        Issue Links

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            Unassigned Unassigned
            danhaywood Daniel Keir Haywood

            Dates

              Created:
              Updated:

              Time Tracking

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

                Slack

                  Issue deployment