I am trying to access the i18n properties file I'm using in my JSF application in code. (The idea is to have a page that displays its keys and values as a table actually.)
The project is a maven project, and in the src/resources/localization folder, and deployed in the war file in WEB-INF\classes\localization\
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
But the variable foo turns out to be null whatever I set the path variable to, /WEB-INF/classes/localization/stat_codes.properties, "localization.stat_codes.properties" etc. A similar question is here, but there is no helpful answer there as well.
To change properties in a file during runtime, we should place that file somewhere outside the jar. Then we tell Spring where it is with the command-line parameter –spring. config. location=file://{path to file}.
This page shows how to load property file from the classpath using xml based configuration. Declare your property file in your xml based configuration file using "context:property-placeholder" tag, and refer property key any where in the xml based configuration file using ${db. host. url} syntax.
These properties files are in the WEB-INF/config directory inside the WAR. You can configure alternative file names and locations by setting the magnolia. initialization.
Properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application. Java Properties files are amazing resources to add information in Java. Generally, these files are used to store static information in key and value pair.
The Class#getResourceAsStream()
can take a path which is relative to the location of the Class
which you're using there as starting point. So, for example, if the class is located in the com.example
package and you request the path foo/filename.properties
, then it will actually load the com/example/foo/filename.properties
file. But if you use /foo/filename.properties
, then it will actually load foo/filename.properties
from the classpath root.
So, your code
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
will actually look for java/util/localization/stat_codes.properties
file.
But in applications with a complex multiple classloader hierarchy, the one classloader isn't the other. The classloader which loaded the core Java classes does not necessarily have knowledge about files which are in the webapp's /WEB-INF/classes
. So prefixing the path with /
will not necessarily be the solution, it would still return null
.
If you can guarantee that the current class is visible by the same classloader as the properties files (because they're in the same sub-root of the classpath, e.g. /WEB-INF/classes
, then you should indeed use
String path = "/localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
But if at some point, the properties files will be externalized because of more easy maintenance/editing during runtime so that you don't need to rebuild/redeploy/restart the webapp whenever you want to edit the files, then the above line of code will likely fail as well. The externalized location would be only accessible by a different classloader. The canonical solution is to use the thread's context classloader as starting point instead, it has access to all resources in the classpath.
String path = "localization/stat_codes.properties";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream foo = loader.getResourceAsStream(path);
(note that this one cannot take a path starting with /
, it's always relative to the common root)
It seems that the culprit is the prop
object, I supposed any object would work, but it has to be the current object (this
) on which the method getClass()
is invoked, it seems. Also, the path should start with a /
since the localization
directory resides in WEB-INF/classes
.
String path = "localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With