Upgrade to 13.3: UpdateDocumentValidatorsConfiguration Updater Script

Add this script to the updater editor in your local development environment. Make sure that Automatic Export is turned on, then run the script. Any update results will be exported to the yaml config files in your project. These results can then be rolled out to your production system together with the upgrade to 13.3.

The script may log some warnings: check those and see if you need to take any action to update configuration manually.

package org.hippoecm.frontend.plugins.cms.admin.updater

import org.onehippo.repository.update.BaseNodeUpdateVisitor

import javax.jcr.Node
import javax.jcr.RepositoryException
import javax.jcr.Session

import static org.hippoecm.repository.api.HippoNodeType.HIPPOSYSEDIT_TYPE
import static org.hippoecm.repository.api.HippoNodeType.HIPPO_VALIDATORS

class UpdateDocumentValidatorsConfiguration extends BaseNodeUpdateVisitor {

    boolean logSkippedNodePaths() {
        return false // don't log skipped node paths

    boolean skipCheckoutNodes() {
        return false // return true for readonly visitors and/or updates unrelated to versioned content

    Node firstNode(final Session session) throws RepositoryException {
        return null // implement when using custom node selection/navigation

    Node nextNode() throws RepositoryException {
        return null // implement when using custom node selection/navigation

    boolean doUpdate(Node node) {
        if (!node.hasProperty(HIPPO_VALIDATORS)) {
            return false

        def logLines = []
        def validatorsOriginal = readValidators(node)
        logLines << "Existing validators           : ${validatorsOriginal.toString()}"

        // replace resource-required -> required
        def validators = replaceValidator(validatorsOriginal, 'resource-required', 'required')
        validators = replaceValidator(validators, 'html', 'non-empty-html')
        logLines << "Without resource-required/html: ${validators.toString()}"

        // fix required & non-empty combination
        validators = removeNonEmptyValidator(validators)
        logLines << "Without non-empty if required : ${validators.toString()}"

        // log warning for non-empty only
        logNonEmptyWarning(validators, node.path)

        // fix non-empty for Html fields
        if (!node.getProperty(HIPPOSYSEDIT_TYPE)) {
            log.warn "Field node with validators but without type! Cannot check this node: ${node.path}"
        } else {
            def type = node.getProperty(HIPPOSYSEDIT_TYPE).string
            if (type == 'Html') {
                validators = replaceValidator(validators, 'non-empty', 'non-empty-html')
                logLines << "Fixed html fields            : ${validators.toString()}"

        // set the property
        if (!validatorsOriginal.equals(validators)) {
            log.debug "Updating node ${node.path}"
            logLines.each { log.debug "${it}" }
            String[] strings = validators.toArray(new String[0])
            node.setProperty(HIPPO_VALIDATORS, strings)
            return true

        // Uncomment these lines for more logging
        // log.debug "Unchanged node ${node.path}"
        // logLines.each{ log.debug "${it}" }
        return false

    static List<String> readValidators(Node node) {
        def validatorsProperty = node.getProperty(HIPPO_VALIDATORS)
        def values = validatorsProperty.getValues()
        def validators = []
        values.each { validators << it.string }
        return validators

    static List<String> replaceValidator(validators, target, replacement) {
        return validators.collect { item -> item == target ? replacement : item }.unique()

    static List<String> removeNonEmptyValidator(validators) {
        if (validators.contains('required') && validators.contains('non-empty')) {
        return validators

    void logNonEmptyWarning(validators, path) {
        if (validators.contains('non-empty') && !validators.contains('required') && !validators.contains('optional')) {
            log.info "Field with a 'non-empty' validator found that is not 'required' nor 'optional'. Consider using 'required' or 'optional' instead. See the field definition at node ${path}"

    boolean undoUpdate(Node node) {
        throw new UnsupportedOperationException('Updater does not implement undoUpdate method')
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?

    We rely on cookies

    to optimize our communication and to enhance your customer experience. By clicking on the Accept and Close button, you agree to the collection of cookies. You can also adjust your preferences by clicking on Manage Preferences. For more information please see our Privacy policy.

    Manage cookies
    Accept & close

    Cookies preferences

    Accept & close