How to read properties file in web application? [duplicate] - java

This question already has answers here:
Where to place and how to read configuration resource files in servlet based application?
(6 answers)
Closed 6 years ago.
Properties file location is WEB-INF/classes/auth.properties.
I cannot use JSF-specific ways (with ExternalContext) because I need properties file in a service module which doesn't have a dependency on a web-module.
I've already tried
MyService.class.getClassLoader().getResourceAsStream("/WEB-INF/classes/auth.properties");
but it returns null.
I've also tried to read it with FileInputStream but it requires the full path what is unacceptable.
Any ideas?

Several notes:
You should prefer the ClassLoader as returned by Thread#getContextClassLoader().
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
This returns the parentmost classloader which has access to all resources. The Class#getClassLoader() will only return the (child) classloader of the class in question which may not per se have access to the desired resource. It will always work in environments with a single classloader, but not always in environments with a complex hierarchy of classloaders like webapps.
The /WEB-INF folder is not in the root of the classpath. The /WEB-INF/classes folder is. So you need to load the properties files relative to that.
classLoader.getResourceAsStream("/auth.properties");
If you opt for using the Thread#getContextClassLoader(), remove the leading /.
The JSF-specific ExternalContext#getResourceAsStream() which uses ServletContext#getResourceAsStream() "under the hoods" only returns resources from the webcontent (there where the /WEB-INF folder is sitting), not from the classpath.

Try this:
MyService.class.getClassLoader().getResourceAsStream("/auth.properties");
Reading files with getResourceAsStream looks on the classpath to find the resource to load. Since the classes directory is in the classpath for your webapp, referring to the file as /auth.properties should work.

ResourceBundle (http://download.oracle.com/javase/6/docs/api/java/util/ResourceBundle.html) resolve most of the problems with a relative/absotule path for Properties Files.
It uses the the Resource class and point it to a Dummy Class to make reference to a properties file.
For example:
You a have file called MAINProperties.properties and inside it there is a property:
mail.host=foo.example.com
Create a Dummy Class called MAINProperties without nothing.
Use the following code:
ResourceBundle.getBundle("com.example.com.MAINProperties").getProperty("mail.host")
And That's it. No InputStreams Required.
P.D. Apache Commons has a Library Called Apache Commons Configuration that has a lot of capabilities (reloadable files, multiple domain types) that could be used in combination of the above.

Related

Why use a ClassLoader to read a resource

I encountered a case where I need to use ClassLoader:
I have a XML file which specifies the configuration detail for sql, and I want to load it into a configuration class. The first step is to load what is in the XML into an Inputstream.
public class Resources{
public static InputStream getResourceAsStream(String path){
InputStream resourceAsStream = Resources.class.getClassLoader().getResourceAsStream(path);
return resourceAsStream;
}
}
I only know vaguely what is a classloader: It loads classes into JVM. It is not clear to me at all why one would use classLoader here. Can't we just read what is in path directly? My guess is that this might have something to do with the timing of when one wants to load the resource.
A project is composed of two things:
Code compiled into .class file
Ressources (any file such as properties, xml...)
Then it is packaged. The packaging can be mainly:
a JAR
a directory
A ClassLoader is what is capable to access to packaged projects (jars, directories...). The main ClassLoader is accessing jars and directories specified in the classpath, but additional ClassLoader may be added at runtime. For example, on an application server, where you can deploy new packaged applications at runtime, for every application a ClassLoader will be created.
That's why, to access ressources from a packaged project, you need to use a ClassLoader (even the name is not clear about ressources).
If you want to access a ressource packaged together with your class in the same project, you get the ClassLoader of your class so you are sure it can access the ressources of the same project.
The most typical ClassLoader is java.net.URLClassLoader, which takes a list of URLs (local or remote JARs, directories...) such as the classpath, and look into every URL to search for .class files or ressources files.
To sum up, you can see a ClassLoader as a list of locations where to search files, either .class to load classes, or any other type of file as ressources.

Java file path in web project

I need to access the resource files in my web project from a class. The problem is that the paths of my development environment are different from the ones when the project is deployed.
For example, if I want to access some css files while developing I can do like this:
File file = new File("src/main/webapp/resources/styles/some.css/");
But this may not work once it's deployed because there's no src or main directories in the target folder. How could I access the files consistently?
You seem to be storing your CSS file in the classpath for some unobvious reason. The folder name src is typical as default name of Eclipse's project source folder. And that it apparently magically works as being a relative path in the File constructor (bad, bad), only confirms that you're running this in the IDE context.
This is indeed not portable.
You should not be using File's constructor. If the resource is in the classpath, you need to get it as resource from the classpath.
InputStream input = getClass().getResourceAsStream("/main/webapp/resources/styles/some.css");
// ...
Assuming that the current class is running in the same context, this will work regardless of the runtime environment.
See also:
getResourceAsStream() vs FileInputStream
Update: ah, the functional requirement is now more clear.
Actually I want to get lastModified from the file. Is it possible with InputStream? –
Use getResource() instead to obtain it as an URL. Then you can open the connection on it and request for the lastModified.
URL url = getClass().getResource("/main/webapp/resources/styles/some.css");
long lastModified = url.openConnection().getLastModified();
// ...
If what you're looking to do is open a file that's within the browser-visible part of the application, I'd suggest using ServletContext.getRealPath(...)
Thus:
File f = new File(this.getServletContext().getRealPath("relative/path/to/your/file"));
Note: if you're not within a servlet, you may have to jump through some additional hoops to get the ServletContext, but it should always be available to you in a web environment. This solution also allows you to put the .css file where the user's browser can see it, whereas putting it under /WEB-INF/ would hide the file from the user.
Put your external resources in a sub-directory of your project's WEB-INF folder. E.g., put your css resources in WEB-INF/styles and you should be able to access them as:
new File("styles/some.css");
Unless you're not using a standard WAR for deployment, in which case, you should explain your setup.
Typically resource files are placed in your war along with your class files. Thus they will be on the classpath and can be looked up via
getClass.getResource("/resources/styles/some.css")
or by opening a File as #ig0774 mentioned.
If the resource is in a directory that is not deployed in the WAR (say you need to change it without redeploying), then you can use a VM arg to define the path to your resource.
-Dresource.dir=/src/main/webapp/resources
and do a lookup via that variable to load it.
In Java web project, the standard directory like:
{WEB-ROOT} /
/WEB-INF/
/WEB-INF/lib/
/WEB-INF/classes
So, if you can get the class files path in file system dynamic,
you can get the resources file path.
you can get the path ( /WEB-INF/classes/ ) by:
this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
so, then the next ...

How to resolve path of a static file in Java?

How can I find path of a xml (static myXml.xml) file that is embedded into jar? Obviously not by absolute path but I am facing same kind of problem with relative paths. I cannot get it relative to home folder as Java returns different home folder depending upon from where I am calling the accessing Java class. For instance, from:
command prompt
App server
Eclipse launcher
Eclipse remote debugger etc
Is there someway that my accessing class (packed in same jar) may access embedded xml regardless of where jar file exists and who is trying to access it?
What you need to do is use the class loader to load the file:
InputStream stream = this.getClass().getClassLoader().
getResourceAsStream("myXml.xml");
The above code assumes that the file is at the top level of your jar.
Have you tried the getResource and getResourceAsStream methods in the Class class? Usually those are what I have to resort to in these situations.
Hope this helps.
You can use ClassLoader#getResource(..) to get InputStream of a file from the classpath:
Object.class.getClassLoader().getResource().openStream()
Also there are some other methods in ClassLoader which could be useful in your case.

how to add a file to Java EE projects?

I want to add a xml file to my Java ee project and use it in my code but when I address the file from src directory it does not understand my address and search for file in bin directory of tomcat.
My project is using wicket framwork and JavaEE.
does any one know how to address the file or where should I place the file to access is from project?
If your xml file is a resource that must be accessed server-side only, then the best choice is to place it in the WEB-INF directory inside your war, or in some subdirectory inside the WEB-INF. This way you ensure the resource will not be accessible by the web.
Then you can retrieve it using ServletContext.getResource, as pointed out by Peter D.
For example, in a servlet you can retrieve it this way (exception handling omitted):
String path = "/WEB-INF/my.xml";
URL url = getServletConfig().getServletContext().getResource(path);
InputStream in = url.openStream();
// read content from input stream...
Inside your servlet you can:
this.getServletContext().getResource( path );
public java.net.URL getResource(java.lang.String path)
throws java.net.MalformedURLException
Returns a URL to the resource that is mapped to a specified path. The path must begin with a "/" and is interpreted as relative to the current context root.
This method allows the servlet container to make a resource available to servlets from any source. Resources can be located on a local or remote file system, in a database, or in a .war file.
The servlet container must implement the URL handlers and URLConnection objects that are necessary to access the resource.
This method returns null if no resource is mapped to the pathname.
Some containers may allow writing to the URL returned by this method using the methods of the URL class.
The resource content is returned directly, so be aware that requesting a .jsp page returns the JSP source code. Use a RequestDispatcher instead to include results of an execution.
This method has a different purpose than java.lang.Class.getResource, which looks up resources based on a class loader. This method does not use class loaders.
Normally src is not used at runtime. I don't use tomcat, but in my environment I have build tasks that copy non-Java files from src to the bin directory.
You may find it necessary to open the file by using the classloader getResourceAsStream() so that you are searching the same directories as your classes come from.
This assumes that you want to deliver the XML in the application. Alternatively you may prefer to have it somewhere else. URI resource references may help
Why don't you place the XML file in your resources directory. You can access it from any class with:
MyClass.class.getClassLoader().getResourceAsStream(filename);

Class.getResourceAsStream() issue

I have a JAR-archive with java classes. One of them uses some resource that is embedded into the same JAR. In order to load that resource I use
MyClass.class.getResourceAsStream(myResourceName);
One thing that bothers me though is whether it is guaranteed that required resource will be loaded from within the same JAR. The documentation for "getResourceAsStream()" method (and corresponding ClassLoader's method) is not really clear to me.
What would happen if there's a resource with the same name located somewhere in JVM classpath before my JAR? Will that resource be loaded instead of the one embedded in my JAR? Is there any other way to substitute resource embedded in JAR?
Yes. The first matching resource found on the class path is returned, just like an executable search path. This is why resources are often "namespaced" by putting them in directories that mirror the package structure of the library or application.
This behavior may be slightly different in the presence of custom classloaders (say in OSGi), but for vanilla Java apps, it is the case.
It works much the same way as for finding class files. So first try the parent class loader (recursively) then do whatever the class loader implementation does to find files.
There is no checking of the immediate caller class loader (as ResourceBundle does - see section 6.3 of the Java Secure Coding Guidelines). However, you do need permissions to open the URL, as ClassLoader.getResourceAsStream just calls URL.openStream in the default implementation.
Specify the package. Assuming you use com.yourcompany.file it SHOULD be unique. (Unless someone WANTS to override your config file via the classpath.)
If you want to read the file only from a specific JAR you can open the JarFile and read it directly.

Categories

Resources