private void validateProp(final Prop prop, final List<Result<T>> resultList) {

        if (Collection.class.isAssignableFrom(prop.getValueClass())) {
            ((Collection<?>) prop.getValueFromConfigObject()).forEach(item -> {
                // we already know the items in the collection are config objects
                // so recurse into each one.
                PropertyUtil.walkObjectTree(
                        item,
                        childProp ->
                                canValidateProp(configSuperType, childProp),
                        childProp ->
                                validateProp(childProp, resultList));
            });
        } else {
            final T configObject = (T) prop.getValueFromConfigObject();
            final Result<T> result = validate(configObject, configSuperType);
            if (result.hasErrorsOrWarnings()) {
                resultList.add(result);
            }
        }
    }
Walks the config object tree validating each branch regardless of whether they have @Valid
annotations.
stroom-util/src/main/java/stroom/util/config/ConfigValidator.java