Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing properties file in a JSF application programmatically

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.

like image 628
ustun Avatar asked Oct 31 '11 09:10

ustun


People also ask

How do I load a properties file in spring at runtime?

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}.

How read properties file in Spring XML?

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.

Where do I put the properties file in war?

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.

For what properties file used in Java?

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.


2 Answers

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)

See also:

  • Where to place and how to read configuration resource files in servlet based application?
  • ExternalContext#getResourceAsStream() returns null, where to place the resource file?
like image 100
BalusC Avatar answered Nov 16 '22 03:11

BalusC


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);
like image 36
ustun Avatar answered Nov 16 '22 04:11

ustun