227

In my web application I have to send email to set of predefined users like finance@xyz.com, so I wish to add that to a .properties file and access it when required. Is this a correct procedure, if so then where should I place this file? I am using Netbeans IDE which is having two separate folders for source and JSP files.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
sansknwoledge
  • 4,067
  • 9
  • 34
  • 56

6 Answers6

471

It's your choice. There are basically three ways in a Java web application archive (WAR):


1. Put it in classpath

So that you can load it by ClassLoader#getResourceAsStream() with a classpath-relative path:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);

Here foo.properties is supposed to be placed in one of the roots which are covered by the default classpath of a webapp, e.g. webapp's /WEB-INF/lib and /WEB-INF/classes, server's /lib, or JDK/JRE's /lib. If the propertiesfile is webapp-specific, best is to place it in /WEB-INF/classes. If you're developing a standard WAR project in an IDE, drop it in src folder (the project's source folder). If you're using a Maven project, drop it in /main/resources folder.

You can alternatively also put it somewhere outside the default classpath and add its path to the classpath of the appserver. In for example Tomcat you can configure it as shared.loader property of Tomcat/conf/catalina.properties.

If you have placed the foo.properties it in a Java package structure like com.example, then you need to load it as below

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...

Note that this path of a context class loader should not start with a /. Only when you're using a "relative" class loader such as SomeClass.class.getClassLoader(), then you indeed need to start it with a /.

ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...

However, the visibility of the properties file depends then on the class loader in question. It's only visible to the same class loader as the one which loaded the class. So, if the class is loaded by e.g. server common classloader instead of webapp classloader, and the properties file is inside webapp itself, then it's invisible. The context class loader is your safest bet so you can place the properties file "everywhere" in the classpath and/or you intend to be able to override a server-provided one from the webapp on.


2. Put it in webcontent

So that you can load it by ServletContext#getResourceAsStream() with a webcontent-relative path:

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...

Note that I have demonstrated to place the file in /WEB-INF folder, otherwise it would have been public accessible by any webbrowser. Also note that the ServletContext is in any HttpServlet class just accessible by the inherited GenericServlet#getServletContext() and in Filter by FilterConfig#getServletContext(). In case you're not in a servlet class, it's usually just injectable via @Inject.


3. Put it in local disk file system

So that you can load it the usual java.io way with an absolute local disk file system path:

InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...

Note the importance of using an absolute path. Relative local disk file system paths are an absolute no-go in a Java EE web application. See also the first "See also" link below.


Which to choose?

Just weigh the advantages/disadvantages in your own opinion of maintainability.

If the properties files are "static" and never needs to change during runtime, then you could keep them in the WAR.

If you prefer being able to edit properties files from outside the web application without the need to rebuild and redeploy the WAR every time, then put it in the classpath outside the project (if necessary add the directory to the classpath).

If you prefer being able to edit properties files programmatically from inside the web application using Properties#store() method, put it outside the web application. As the Properties#store() requires a Writer, you can't go around using a disk file system path. That path can in turn be passed to the web application as a VM argument or system property. As a precaution, never use getRealPath(). All changes in deploy folder will get lost on a redeploy for the simple reason that the changes are not reflected back in original WAR file.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 2
    "I personally prefer putting it in the classpath outside the project (add new path to the classpath)" confused, can you give an example? – Blankman Dec 18 '11 at 02:32
  • 4
    @Blankman He probably means creating a new folder, putting all your custom configuration files there, and adding that folder into the classpath. So: 1) Create a folder called 'appconfs' somewhere (might be even `/etc/appconfs` 2) Add that folder to the classpath of app server / domain. The second step is app server specific, I don't think there's generic example for that. – Tuukka Mustonen Jan 03 '12 at 15:15
  • Re : 2 : Why would both `"WEB-INF/filename.properties"` and `"/WEB-INF/filename.properties"` (notice the `/` at the beginning) work ? Is there any reason to prefer one over the other ? – Mr_and_Mrs_D Sep 07 '13 at 14:57
  • I have been fixed in this issue for the past one day. I am not able to load my properties file. I am able to load it from two places. One is system directory and one is the local drive. It works with localhost. But I want to deploy it on amazon. – Arun Raja Apr 24 '15 at 07:25
  • I am using netbeans IDE and keep the properties file in Web Pages/resources. I try to access it as "./Web Pages/resources/config.properties". I am not able to access it. Please help me. – Arun Raja Apr 24 '15 at 07:27
  • I am planning on placing a credentials.json file (for accessing an API) in the `src` folder as you recommend (for a "standard WAR project on an IDE"). I just wanted to confirm that there are no security concerns in placing such a file in this location (ie: the file should not be able to be accessed by anyone). Thanks. – theyuv Aug 16 '16 at 16:57
  • There is one more, namely putting it in _another_ web application and simply ask for the web page containing the properties when needed. This need tight security so the property page is only accessible locally but can be an option in a suitably controlled environment. – Thorbjørn Ravn Andersen Mar 06 '17 at 13:31
  • I keeping my config in (com.techguy.andFeeds.util) package. I followed same as you suggested in 2. But my instream is null. Its not loading the file. – Techguy Aug 18 '20 at 11:19
  • @Techguy: package is not part of webcontent, it's part of classpath. So follow 1. – BalusC Aug 18 '20 at 11:44
  • @BalusC : i tried 1, but inputStream is getting null. InputStream is not able to find the config.properties. I keeping by both java and config file in same package – Techguy Aug 21 '20 at 11:41
  • 1
    @Techguy: it will return null when path is invalid or resource is actually not placed there where it's supposed to be placed. – BalusC Aug 21 '20 at 14:08
10

Word of warning: if you put config files in your WEB-INF/classes folder, and your IDE, say Eclipse, does a clean/rebuild, it will nuke your conf files unless they were in the Java source directory. BalusC's great answer alludes to that in option 1 but I wanted to add emphasis.

I learned the hard way that if you "copy" a web project in Eclipse, it does a clean/rebuild from any source folders. In my case I had added a "linked source dir" from our POJO java library, it would compile to the WEB-INF/classes folder. Doing a clean/rebuild in that project (not the web app project) caused the same problem.

I thought about putting my confs in the POJO src folder, but these confs are all for 3rd party libs (like Quartz or URLRewrite) that are in the WEB-INF/lib folder, so that didn't make sense. I plan to test putting it in the web projects "src" folder when i get around to it, but that folder is currently empty and having conf files in it seems inelegant.

So I vote for putting conf files in WEB-INF/commonConfFolder/filename.properties, next to the classes folder, which is Balus option 2.

Ahmed Ashour
  • 4,209
  • 10
  • 29
  • 46
Ed Pike
  • 789
  • 8
  • 9
  • 1
    if you put your config file in a sub folder of WEB_INF then how do you reach it? I have not had luck with say 'configFiles/prop.properties' – JesseBoyd Sep 08 '17 at 21:00
  • ok this does work putting the property file under 'Java Resources/src/' it does not work from within one of my packages and needs to be at the root of src. your warning about the classes folder getting nuked is a valid concern. – JesseBoyd Sep 08 '17 at 21:03
6

Ex: In web.xml file the tag

<context-param>
        <param-name>chatpropertyfile</param-name>
        <!--  Name of the chat properties file. It contains the name and description                   of rooms.-->     
        <param-value>chat.properties</param-value>
    </context-param>

And chat.properties you can declare your properties like this

For Ex :

Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
Vikdor
  • 22,825
  • 9
  • 55
  • 81
5

It just needs to be in the classpath (aka make sure it ends up under /WEB-INF/classes in the .war as part of the build).

Taylor Leese
  • 46,410
  • 27
  • 106
  • 138
  • hi thanks for the idea, but it tells me that cannot find the file specified, yes its the path problem how to give the path – sansknwoledge Jan 29 '10 at 10:32
3

You can you with your source folder so whenever you build, those files are automatically copied to the classes directory.

Instead of using properties file, use XML file.

If the data is too small, you can even use web.xml for accessing the properties.

Please note that any of these approach will require app server restart for changes to be reflected.

Bill the Lizard
  • 369,957
  • 201
  • 546
  • 842
Kalpak
  • 3,262
  • 4
  • 19
  • 21
2

Assume your code is looking for the file say app.properties. Copy this file to any dir and add this dir to classpath, by creating a setenv.sh in the bin dir of tomcat.

In your setenv.sh of tomcat( if this file is not existing, create one , tomcat will load this setenv.sh file. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

You should not have your properties files in ./webapps//WEB-INF/classes/app.properties

Tomcat class loader will override the with the one from WEB-INF/classes/

A good read: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Thar
  • 1,048
  • 1
  • 6
  • 6