Apache
Home » Documentation » Bundles

Sling Validation

This documentation is still work in progress!

Many Sling projects want to be able to validate both Resources and request parameters. Through the Sling Validation Bundle this is possible with the help of validation model resources which define validation rules for a certain resourceType.

Basic Usage

To validate a resource one first needs to get a ValidationModel and then validate the resource with that model. Both functionalities are provided by the ValidationService OSGi service:

try {
    ValidationModel validationModel = validationService.getValidationModel(resource, true);
    if (validationModel != null) {
        ValidationResult result = validationService.validate(resource, validationModel);
        if (!result.isValid()) {
            // give out validation messages from result.get
        }
    }
} catch (IllegalStateException e) {
    // give out error message that the validation model is invalid!
}

Apart from that it is also possible to validate resources including all child resources having their own validation model (i.e. a merged view of the validation models is applied). The appropriate validation model is being looked up by getting the resource type for each node. Since by default the JCR will return the primary type in case there is no sling:resourceType property found on the node, either the 2nd parameter enforceValidation should be set to false or some resource types must be explicitly ignored by the given filter in the 3rd parameter filter to also properly support validation models which have children resources on their own.

try {
    final Predicate ignoreResourceType1Predicate = new Predicate<Resource>() {
        @Override
        public boolean test(final Resource resource) {
            return !"resourcetype1".equals(resource.getResourceType());
        }
    };
    ValidationResult result = validationService.validateResourceRecursively(resource, false, ignoreResourceType1Predicate, false);
    if (!result.isValid()) {
        // give out validation messages from result.getFailureMessages()
    }

} catch (IllegalStateException e) {
    // give out error message that an invalid validation model for at least one sub resource was found
} catch (IllegalArgumentException e) {
    // one of the resource types is absolute or there was no validation model found for at least one sub resource
}

All methods to retrieve a validation model support a boolean parameter considerResourceSuperTypeModels. If this is set to true, the validation model is not only being looked up for exactly the given resource type but also for all its resource super types. The returned model is then a merged model of all found validation model along the resource type hierarchy.

Validation Model Resources

The ValidationModel is constructed from resources with the resourceType sling/validation/model. Those resources are considered validation model resources if they are located below the Sling ResourceResolver search paths (/apps and /libs).

The resources should have the following format:

Property/Resource Name Property or Resource Type Description Mandatory
sling:resourceType Property String Always sling/validation/model, otherwise node will never be picked up by Sling Validation. yes
validatedResourceType Property String The resource type of the resource for which this validation model should be applied. Must always be relative (i.e. not start with a "/"). yes
applicablePaths Property String[] Path prefixes which restrict the validation model to resources which are below one of the given prefixes. No wildcards are supported. If not given, there is no path restriction. no
properties\<propertyName> Resource - This resource ensures that the property with the name <propertyName> is there. The resource name has no longer a meaning if the property nameRegex is set on this node. no
properties\<propertyName>\optional Property Boolean If true it is not an error if there is no property with the given <propertyName> or none matching the nameRegex. If not set or false the property must be there. no
properties\<propertyName>\propertyMultiple Property Boolean If true only multivalue properties are allowed with the name <propertyName> or matching the nameRegex. If not set or false, multi- and single-value properties are accepted. no
properties\<propertyName>\nameRegex Property String If set the <propertyName> has no longer a meaning. Rather all properties which match the given regular expression are considered. At least one match is required, otherwise the validated resource/valuemap is considered invalid. no
properties\<propertyName>\validators\<validatorName> Resource - The <validatorName> must be the OSGi component name of a validator. Each validators node might have arbitrarily many subnodes (one per validator). no
properties\<propertyName>\validators\<validatorName>\validatorArguments Property String[] The parametrization for the validator with the name <validatorName>. Each value must have the pattern key=value. The parametrization differs per validator. no
properties\<propertyName>\validators\<validatorName>\severity Property Integer The severity which should be set on all emitted validation failures by this validator. no
children\<resourceName> Resource - This resource ensures that the resource with the name <resourceName> is there. The resource name has no longer a meaning if the property nameRegex is set on this node. no
children\<resourceName>\nameRegex Property String If set the <resourceName> has no longer a meaning. Rather all resources whose name match the given regular expression are considered. At least one match is required, otherwise the validated resource/valuemap is considered invalid. no
children\<resourceName>\optional Property Boolean If true it is not an error if there is no resource with the given <resourceName> or none matching the nameRegex. If not set or false the resource must be there. no
children\<resourceName>\properties Resource - The properties can be configured on the child level in the same way as on the root level. no

Validation Model Inheritance

Sling Validation optionally supports the inheritance of Sling Validation Models. This means not only the model for exactly the given resource type is considered, but also the models for all resource super types. To overwrite some property or child from one of the super type models, just define a property/child on the same level and with the same name in a model for a resource type which is more specific. That way the property/child on the super validation model is no longer effective.

Usage in Sling Models

Since Sling Models 1.2.0

See Sling Models validation

Before Sling Models 1.2.0

one needs to call the validate method within the PostConstruct method of the according Sling Model

@SlingObject
protected Resource resource;

@OSGiService
protected ValidationService validation;

@PostConstruct
public void validate() {
    try {
    ValidationModel validationModel = validation.getValidationModel(resource);
    if (validationModel == null) {
        LOG.warn("No validation defined for resource '{}' with type '{}'", resource.getPath(), resource.getResourceType());

    } else {
        ValidationResult result = validation.validate(resource, validationModel);
        if (!result.isValid()) {
            // give out the validation result
        }
    }
    } catch (IllegalStateException e) {
         LOG.warn("Invalid validation model for resource '{}' with type '{}'", resource.getPath(), resource.getResourceType());
    }
}

Writing Validators

The Sling validation bundle currently comes only with one validator RegexValidator which checks that the property value matches a given pattern. That validator supports only one parameter which is called regex. The value specifies the pattern against which the resource value is matched.

To write a validator one needs to implement the Validator interface in an OSGi service. That interface defines the method validate. That is called for each property which is bound to the validator through the Validation Resources.

Each validator needs to specify one type parameter which defines upon which classes the validator can act (usually String). Array types are also supported here. Collection types are not supported. If a property value cannot be converted to the requested type from the validator (through ValueMap.get(name, type)), validation will fail.

References

  1. Apache Sling Generic Validation Framework, adaptTo 2014
Rev. 1734538 by kwin on Fri, 11 Mar 2016 11:24:09 +0000
Apache Sling, Sling, Apache, the Apache feather logo, and the Apache Sling project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.