Given the following stripped-down demo application:
@SpringBootApplication
public class InjectedPathDemoApplication implements ApplicationRunner {
@Value("${dir}")
private Path dir;
public static void main(String[] args) {
SpringApplication.run(InjectedPathDemoApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(dir);
}
}
When run using a JDK in Windows:
$ java -jar demo.jar --dir=..
..
$ java -jar demo.jar --dir=./test
test
$ java -jar demo.jar --dir=.
C:\■■■■■■■■\injected-path-demo\bin\main
When run as native binary compiled with GraalVM:
$ ./demo-native --dir=..
..
$ ./demo-native --dir=./test
test
$ ./demo-native --dir=.
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'injectedPathDemoApplication': Unsatisfied dependency expressed through field 'dir': Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: resource:/
Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'injectedPathDemoApplication': Unsatisfied dependency expressed through field 'dir': Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: resource:/
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:194)
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveAndSet(AutowiredFieldValueResolver.java:167)
at com.example.demo.InjectedPathDemoApplication__Autowiring.apply(InjectedPathDemoApplication__Autowiring.java:17)
at org.springframework.beans.factory.support.InstanceSupplier$1.get(InstanceSupplier.java:83)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1162)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
at com.example.demo.InjectedPathDemoApplication.main(InjectedPathDemoApplication.java:17)
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: resource:/
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:87)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:71)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1381)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:188)
... 21 more
Caused by: java.lang.IllegalArgumentException: Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: resource:/
at org.springframework.beans.propertyeditors.PathEditor.setAsText(PathEditor.java:115)
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439)
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80)
... 25 more
Expected result for the third call: returns either "." or "", and does not throw an error on native
Comment From: sbrannen
Hi @ewoerner,
Congratulations on opening your first issue for the Spring Framework! 👍
What happens if you introduce the file:
prefix as follows?
@Value("file:${dir}")
Comment From: ewoerner
@sbrannen that causes injection to fail with any value, with the following stacktrace:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'injectedPathDemoApplication': Unsatisfied dependency expressed through field 'dir': Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; URI is not hierarchical
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:787) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.10.jar:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.10.jar:6.1.10]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.1.jar:3.3.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.1.jar:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.1.jar:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.1.jar:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.1.jar:3.3.1]
at com.example.demo.InjectedPathDemoApplication.main(InjectedPathDemoApplication.java:17) ~[main/:na]
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; URI is not hierarchical
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:87) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:71) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1381) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.10.jar:6.1.10]
... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
at java.base/sun.nio.fs.WindowsUriSupport.fromUri(WindowsUriSupport.java:123) ~[na:na]
at java.base/sun.nio.fs.WindowsFileSystemProvider.getPath(WindowsFileSystemProvider.java:98) ~[na:na]
at java.base/java.nio.file.Path.of(Path.java:203) ~[na:na]
at java.base/java.nio.file.Paths.get(Paths.java:98) ~[na:na]
at org.springframework.beans.propertyeditors.PathEditor.setAsText(PathEditor.java:86) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80) ~[spring-beans-6.1.10.jar:6.1.10]
... 23 common frames omitted
Comment From: sbrannen
How about @Value("file://${dir}")
?
Comment From: ewoerner
That also throws, but with a different root cause:
[...]
Caused by: java.lang.IllegalArgumentException: URI path component is empty
at java.base/sun.nio.fs.WindowsUriSupport.fromUri(WindowsUriSupport.java:133) ~[na:na]
at java.base/sun.nio.fs.WindowsFileSystemProvider.getPath(WindowsFileSystemProvider.java:98) ~[na:na]
at java.base/java.nio.file.Path.of(Path.java:203) ~[na:na]
at java.base/java.nio.file.Paths.get(Paths.java:98) ~[na:na]
at org.springframework.beans.propertyeditors.PathEditor.setAsText(PathEditor.java:86) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161) ~[spring-beans-6.1.10.jar:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80) ~[spring-beans-6.1.10.jar:6.1.10]
... 23 common frames omitted
Comment From: sbrannen
Thanks for trying out both of those variants and providing feedback!
I unfortunately don't work on a Windows machine, so I don't have an easy way to test this. Though, perhaps one of my colleagues can test this on Windows.
In the interim, please let us know which versions of the following you are using.
- MS Windows
- JDK
- GraalVM
From the stack trace, I can deduce that you're using Spring Boot 3.3.1 with Spring Framework 6.1.10.
Comment From: snicoll
There's not much Spring is doing around that call stack. Since you can easily reproduce, it would be helpful to see if the raw Java API usage throws that exception as well. Can you please replace the @Value
injection by the following in your run
method?
Paths.get(URI.create("."));
If this fails as well, we know we can close this in favour of a report in GraalVM itself.
Comment From: ewoerner
Version info, as requested: Windows 11 OpenJDK Runtime Environment GraalVM CE 17.0.9+9.1 (build 17.0.9+9-jvmci-23.0-b22) OpenJDK Runtime Environment Temurin-21.0.2+13 (build 21.0.2+13-LTS)
Turns out I did not test properly (I ran it from Eclipse), the exception is also reproducible without GraalVM when built as a JAR file:
$ java -jar .\injected-path-demo-1-0.0.1-SNAPSHOT.jar --dir=.
[...]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'injectedPathDemoApplication': Unsatisfied dependency expressed through field 'dir': Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/C:/■■■■■■■■/injected-path-demo-1/build/libs/injected-path-demo-1-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:787) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.10.jar!/:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.10.jar!/:6.1.10]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.1.jar!/:3.3.1]
at com.example.demo.InjectedPathDemoApplication.main(InjectedPathDemoApplication.java:17) ~[!/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[injected-path-demo-1-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[injected-path-demo-1-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[injected-path-demo-1-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/C:/■■■■■■■■/injected-path-demo-1/build/libs/injected-path-demo-1-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:87) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:71) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1381) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.10.jar!/:6.1.10]
... 26 common frames omitted
Caused by: java.lang.IllegalArgumentException: Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/C:/■■■■■■■■/injected-path-demo-1/build/libs/injected-path-demo-1-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.propertyeditors.PathEditor.setAsText(PathEditor.java:115) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80) ~[spring-beans-6.1.10.jar!/:6.1.10]
... 30 common frames omitted
So the chain seems to be as follows: * Since the value does not start with a "/" and has no scheme, the PathEditor directly delegates its work to the ResourceEditor * The ResourceEditor resolves the resource to a DefaultResourceLoader.ClassPathContextResource * The PathEditor checks whether the resource exists; this is true for "." * Since the resource exists, the PathEditor calls AbstractFileResolvingResource.getFile() which only supports "vfs" and "file" protocol. However, the protocol is "jar" (with JAR) or "resource" (with GraalVM native binary).
The error also happens with any other value that resolves to an existing resource, so --dir=application.properties also throws an Exception.
Comment From: jhoeller
Without a prefix, PathEditor
tries to resolve a given path as context-relative which typically means the classpath. And in the classpath, we cannot resolve jar-contained resources as a file system reference and therefore not expose them as a java.nio.file.Path
. As a consequence, resolving application.properties
or any other existing classpath resource cannot work that way in any case. From that perspective, the behavior is as expected.
Now, with a "." reference specifically, we may debate what that semantically means. According to the PathEditor
algorithm with a classpath-first search, it effectively means the nearest classpath root - and if that happens to be in a jar file, we cannot resolve it in the file system either. On the other hand, resolving the nearest classpath root as a java.nio.file.Path
arguably never makes practical sense, not even for classpath layouts in the file system.
PathEditor
acquired quite a few twists for plain paths over the years, and I suppose we could add one more for directory references which never make sense in the classpath. That said, generally speaking, it is preferable to specify a concrete path with a prefix so that the resolution algorithm reliably knows what it is supposed to mean.
Comment From: snicoll
I thought we did try to reproduce before asking you to change anything. Turns out that it fails on MacOS as well:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoPathApplication': Unsatisfied dependency expressed through field 'dir': Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/Users/snicoll/Downloads/demo-path/build/libs/demo-path-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:787) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.10.jar!/:6.1.10]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.10.jar!/:6.1.10]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.1.jar!/:3.3.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.1.jar!/:3.3.1]
at com.example.demopath.DemoPathApplication.main(DemoPathApplication.java:18) ~[!/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[demo-path-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[demo-path-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[demo-path-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.nio.file.Path'; Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/Users/snicoll/Downloads/demo-path/build/libs/demo-path-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:87) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:71) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1381) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.10.jar!/:6.1.10]
... 26 common frames omitted
Caused by: java.lang.IllegalArgumentException: Could not retrieve file for class path resource []: class path resource [] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/Users/snicoll/Downloads/demo-path/build/libs/demo-path-0.0.1-SNAPSHOT.jar/!BOOT-INF/classes/!/
at org.springframework.beans.propertyeditors.PathEditor.setAsText(PathEditor.java:115) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161) ~[spring-beans-6.1.10.jar!/:6.1.10]
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80) ~[spring-beans-6.1.10.jar!/:6.1.10]
... 30 common frames omitted
Sorry about that @ewoerner. So yeah, the bottom line is that you can't get a Path
from a classpath resource because there's no such file to begin with on the file system.
Comment From: jhoeller
In general, the proper solution is to specify a "file:" prefix for an explicit file system reference there. That should also work for "file:." (as suggested above) but unfortunately doesn't, in contrast to java.io.File
references processed by FileEditor
. We might turn this issue into a bug ticket for that "file:." purpose, making it consistently work across File
and Path
.
Comment From: jhoeller
We're catching the IllegalArgumentException
for non-hierarchical URIs now, letting the regular resource resolution apply which is capable of resolving file:.
already. Also, we're providing a more meaningful exception for our own file-resolution IllegalArgumentException
now.