Reputation: 4607
I am trying to load a properties file using Spring, that is located in my WEB-INF
folder.
I am receiving the following error:
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.elastictest.config.ProdConfig]; nested exception is java.io.FileNotFoundException: \WEB-INF\config\prod.properties (The system cannot find the path specified)
Here is my Production Configuration file:
@Configuration
@Profile("prod")
@PropertySource("file:${prodPropertiesFile}")
public class ProdConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Here is my web.xml declaration:
<context-param>
<param-name>prodPropertiesFile</param-name>
<param-value>/WEB-INF/config/prod.properties</param-value>
</context-param>
I have opened the war and verified that the properties file is there under WEB-INF/config folder. Any ideas?
Upvotes: 1
Views: 2973
Reputation: 280174
The locations you specify within the @PropertySource
annotation are processed by a ResourceLoader
. In this case, that will be your AnnotationConfigWebApplicationContext
, since this is a web application and you want to use an annotation configuration.
As a ResourceLoader
implementation, AnnotationConfigWebApplicationContext
knows how to resolve location values to find and initialize Resource
objects. It uses these to create ResourcePropertySource
objects which are used in property resolution.
The location value resolution follows a few steps:
If it starts with a /
, it's interpreted as a servlet context resource and Spring attempts to retrieve it through ServletContext#getResourceAsStream
.
If it starts with classpath:
, it's interpreted as a classpath resource and Spring tries to retrieve it through ClassLoader#getResourceAsStream
, given an appropriate ClassLoader
.
Otherwise, it defers resolution to a UrlResource
which uses the URL
to locate a resource. Its javadoc states
Supports resolution as a
URL
and also as aFile
in case of the"file:"
protocol.
In your case, you prefixed your location with file:
so Spring tried to use the UrlResource
. Your path had a leading /
which the file system will consider as the beginning of an absolute path. You obviously don't have a file at that location, /WEB-INF/config/prod.properties
.
If you use a classpath:
prefix as suggested in this answer, then you must make sure that /WEB-INF/config/prod.properties
is on the classpath. That's a very uncommon thing to put on the classpath, so I don't recommend it.
Finally, as you've found out, you could use
@PropertySource("/WEB-INF/config/prod.properties")
// or to support your property
@PropertySource("${prodPropertiesFile}")
which will attempt to retrieve a resource through the ServletContext
. Its javadoc states
The path must begin with a
/
and is interpreted as relative to the current context root
Your WEB-INF
folder will be in the context root (basically a directory chosen for your Servlet container as the root of your web application) and so the resource will be found and used.
You can read more about Resource
in the official documentation, here, and about the ResourceLoader
process, here.
Upvotes: 7
Reputation: 4607
It turned out to be simpler than I was making it:
@PropertySource("/WEB-INF/config/prod.properties")
Upvotes: -2
Reputation: 6738
No need web.xml declaration. Try like this
@PropertySource(name="prodPropertiesFile", value="classpath:/WEB-INF/config/prod.properties")
public class ProdConfig {
}
Upvotes: -1