spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

ignoreResourceNotFound=true in @PropertySource doesn't work with PropertySourceFactory which uses YamlPropertySourceLoader

Open crazyk2 opened this issue 6 years ago • 3 comments

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.1.3.RELEASE</version>
    </dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

For load properties from .yaml I use YamlPropertySourceFactory Config Example

@PropertySource(
        value = ["file:\${user.dir}/1/rabbit.config.yml","file:\${user.dir}/2/rabbit.config.yml"],
        factory = YamlPropertySourceFactory::class,
        ignoreResourceNotFound = true)
class YamlPropertySourceFactory : PropertySourceFactory {
    override fun createPropertySource(name: String?, resource: EncodedResource): PropertySource<*> {
        return if (name != null)
            YamlPropertySourceLoader().load(name, resource.resource).first()
        else
            YamlPropertySourceLoader().load(getNameForResource(resource.resource), resource.resource).first()
    }

YamlPropertySourceLoader from spring-boot-2.1.1.release leads to process function which throw IllegalStateException (in my case because FileNotFound ) but catch doesn't catch such type of exception and ignoreResourceNotFound is unreachable. Here are two options: A - add IllegalStateException to catch block B - change type of exception from IllegalStateException to IllegalArgumentException. I prefer option A

crazyk2 avatar Jan 17 '19 17:01 crazyk2

Any news on this?

roxanadel avatar Dec 11 '20 13:12 roxanadel

Hitting this issue as well. Any updates? What is the workaround, catching exception in createPropertySource() is not helping.

sumedhsakdeo avatar Feb 07 '22 22:02 sumedhsakdeo

In case it helps anyone, I am working around this in two parts:

  1. Use a YamlPropertiesFactoryBean to create the property source with the resolution method set to OVERRIDE_AND_IGNORE:
   public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());
        factory.setResolutionMethod(YamlProcessor.ResolutionMethod.OVERRIDE_AND_IGNORE);

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
  1. Add a separate @PropertySource annotations for each file (the above did not work if I listed the potential file locations in a single annotation).

purple52 avatar Aug 30 '22 16:08 purple52

My workaround is to catch the exception and rethrow its cause if it fits.

So from now on, I will be living in fear of an update breaking this behavior.

      try {
         final YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
         factory.setResources(resource);
         factory.afterPropertiesSet();
         return factory.getObject();
      } catch (final java.lang.IllegalStateException illegalState) {
         if (illegalState.getCause() instanceof final FileNotFoundException e) {
            // ConfigurationClassParser wants FileNotFoundException to honor PropertySource.ignoreResourceNotFound
            throw e;
         } else {
            throw illegalState;
         }
      }

urld avatar Dec 12 '22 15:12 urld

As of Spring Framework 6.0, the issue is caused by the behavior of YamlProcessor.handleProcessError(Resource, IOException) and PropertySourceProcessor.processPropertySource(PropertySourceDescriptor).

YamlProcessor.handleProcessError converts an IOException into an IllegalStateException, since YamlProcessor.process(MatchCallback) does not declare any checked exceptions.

Whereas, PropertySourceProcessor.processPropertySource catches (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) but not IllegalStateException.

As mentioned by @crazyk2, one option would be to add IllegalStateException to the catch block in PropertySourceProcessor.processPropertySource; however, I think doing that might result in resources being ignored inappropriately.

In light of that, I am considering modifying YamlProcessor.handleProcessError so that it rethrows an IOException wrapped in an UncheckedIOException and modifying PropertySourceProcessor.processPropertySource so that it catches and unwraps an UncheckedIOException and determines if the underlying IOException is a FileNotFoundException, UnknownHostException, or SocketException in order to appropriately ignore a missing resource.

sbrannen avatar Aug 02 '23 12:08 sbrannen

In light of that, I am considering modifying YamlProcessor.handleProcessError so that it rethrows an IOException wrapped in an UncheckedIOException and modifying PropertySourceProcessor.processPropertySource so that it catches and unwraps an UncheckedIOException and determines if the underlying IOException is a FileNotFoundException, UnknownHostException, or SocketException in order to appropriately ignore a missing resource.

Instead of switching to an UncheckedIOException, we've decided to additionally catch RuntimeException and check if its cause is a FileNotFoundException, UnknownHostException, or SocketException to support ignoreResourceNotFound in more use cases.

sbrannen avatar Aug 03 '23 11:08 sbrannen

My workaround is to catch the exception and rethrow its cause if it fits.

@urld, I think that's a fine workaround in the interim.

sbrannen avatar Aug 03 '23 11:08 sbrannen

This has been addressed in 4a81814dbb54b20919154b1ed92fae657deb2223 for inclusion in Spring Framework 6.0.12.

Feel free to try it out with upcoming 6.0.x snapshots, and let us know if you run into any issues.

sbrannen avatar Aug 05 '23 07:08 sbrannen