Spring Boot Version: 2.3.4

Issue:

As referenced in #23096, trying to load our app (which uses quite a lot of big yaml files) still causes the following stack trace:

Caused by: org.yaml.snakeyaml.error.YAMLException: Number of aliases for non-scalar nodes exceeds the specified max=50
    at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:147)

Downgrading the version of snakeyaml to 1.25 as suggested in the old issue fails as well since these functions in OriginTrackedYamlLoader no longer exist:

java.lang.NoSuchMethodError: 'void org.yaml.snakeyaml.LoaderOptions.setMaxAliasesForCollections(int)'
    at org.springframework.boot.env.OriginTrackedYamlLoader.createYaml(OriginTrackedYamlLoader.java:67)

The branch of our app with this version is here. For an example of how we use yaml, see this test (which is failing on 2.3.4), the class that's using the yaml, and the yaml the test is using.

Comment From: wilkinsona

Thanks for the sample. You aren't using any Spring Boot code to load the YAML so, unfortunately, there's nothing we can change here to help you.

The problem is your YamlPropertyFactoryBean that's using Spring Framework's YamlPropertiesFactoryBean to load the YAML without configuring the limits. I believe you could do that by overriding the createYaml() method so that you can customise the loader options. You may want to open a Spring Framework enhancement request to asking for it to be easier to customise the LoaderOptions.

Alternatively, you may want to move away from using @PropertySource with a custom factory to allow it to load YAML. For example, you could set spring.config.additional-location to point to your custom YAML file so that it's read by Spring Boot's config file infrastructure rather than your custom factory.

Comment From: bencalegari

Thanks for the suggestions, that seemed to work! For others looking to solve this, we overwrote createYaml from YamlPropertiesFactoryBean:

public class UnlimitedYamlPropertiesFactoryBean extends YamlPropertiesFactoryBean {
    @Override
    protected Yaml createYaml() {
        LoaderOptions loaderOptions = new LoaderOptions();
        loaderOptions.setAllowDuplicateKeys(false);
        loaderOptions.setMaxAliasesForCollections(Integer.MAX_VALUE);
        loaderOptions.setAllowRecursiveKeys(true);

        return new Yaml(loaderOptions);
    }
}

Then referenced this new class from our overwritten createPropertySource from PropertySourceFactory:

public class YamlPropertySourceFactory implements PropertySourceFactory {
    @SuppressWarnings({"NullableProblems", "ConstantConditions"})
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
        YamlPropertiesFactoryBean factory = new UnlimitedYamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());
        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

We then referenced that factory when loading our yaml into a configuration:

@Configuration
@PropertySource(value = "classpath:pages-config.yaml", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "shiba-configuration")