Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large files throw YAML exceptions #23617

Closed
bencalegari opened this issue Oct 7, 2020 · 2 comments
Closed

Large files throw YAML exceptions #23617

bencalegari opened this issue Oct 7, 2020 · 2 comments
Labels
status: invalid An issue that we don't feel is valid

Comments

@bencalegari
Copy link

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 7, 2020
@wilkinsona
Copy link
Member

wilkinsona commented Oct 8, 2020

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.

@wilkinsona wilkinsona added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 8, 2020
@bencalegari
Copy link
Author

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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

3 participants