14

I am reading a properties file from the Tomcat\conf\somename.properties directory using

String demo = System.getProperty("catalina.base") +
                  File.separator + "conf" + File.separator + "somename.properties";

This is working perfectly fine with Tomcat. But, there can be scenario where client may use any other server like Glassfish or Websphere, in that case I won't be able to get System.getProperty("catalina.base").

How should I solve it properly? I'm able to do that using ResourceBundle but for that I have to keep my properties file in my build, which I don't want. I just want to read my properties file from outside my build.

mwilson
  • 1,234
  • 12
  • 17
vivekj011
  • 1,069
  • 3
  • 13
  • 23

3 Answers3

17

There are basically two ways.

  1. Just add its path to the runtime classpath so that you can get it from the classpath the usual way. In case of Tomcat, you can add external folders to the runtime classpath by specifying it in the shared.loader property of /conf/catalina.properties. E.g.

    shared.loader = ${catalina.home}/conf

    Or better, don't be server-specific

    shared.loader = /path/to/folder

    Other servers also supports adding external folders to the classpath, consult their documentation.

    This way you'll be able to get an InputStream of it from the classpath as follows:

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

  2. Add another server-independent system property yourself, you can set as a VM argument.

    -Dconfig.location=/path/to/folder

    In case of Tomcat, you can set it as JAVA_OPTS environment variable, or edit the catalina.bat startup file or edit the Windows Service settings (when it's installed as Windows Service), etc. Other servers supports similar constructs as well.

    This way you can obtain it as follows

    File file = new File(System.getProperty("config.location"), "config.properties");
    InputStream input = new FileInputStream(file);
    Properties properties = new Properties();
    properties.load(input);
    // ...
    

Either way you choose, when distributing your application, you should document it properly so that the serveradmin can configure it accordingly.


Unrelated to the problem, the ResourceBundle is not the right way to read configuration properties files. It's intented for localized content for internationalization.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • I discovered in your question history that you've already asked a similar question before: http://stackoverflow.com/questions/6082180/property-file-in-tomcat-bin-folder-getting-java-util-missingresourceexception How exactly was the answer unclear? – BalusC May 24 '11 at 16:06
  • i was not able to set shared.loader = ${catalina.home}/conf But thanx a ton for your this answer....... – vivekj011 May 24 '11 at 16:18
  • I prefer Suraj's answer because it can work without any configuration, whereas here we must set the location in some environment variable. –  Sep 11 '15 at 01:16
1

Simply put, don't rely on catalina.base, that is your first problem :)

Or, more precisely, the java servlet api gives you access to resources inside your web application, so your app is truly portable (not only between servers, but also you can put it anywhere on the file system, zipped as a war or exploded)

Say you put your file at <webapp-root>/WEB-INF/somename.properties, then this is what you do in your servlet, listener, or other web-aware classes:

getServletContext().getResourceAsStream("/WEB-INF/somename.properties");

See similar question here.

Another alternative is to use regular java api to search for files in your classpath, e.g. this.getClass().getResource("/somename.properties"). In the case of a web application, this will find such a file located under /WEB-INF/class/ or any jar under /WEB-INF/lib/.

Finally, if you can't put the file inside your web application, you can put it anywhere on the hard drive and use some config param (e.g. a system property, or a context parameter in web.xml) to refer to it.

Community
  • 1
  • 1
Yoni
  • 9,671
  • 9
  • 49
  • 69
  • 1
    The thing is i cant place this file.Installer gonna place this property file for me.So there is no way to get that file in my build. I just want to read it from outside my build – vivekj011 May 24 '11 at 16:04
  • I just added that info while you were commenting. This is a typical use-case for a system parameter used with -D flag or something. – Yoni May 24 '11 at 16:09
1

First use the ServletContext.getServerInfo() to determine the container. Then based on the container, use container specific ways of getting the information. For e.g. if the method returns "tomcat*" then you can use catalina.base thing, if it returns glassfish, then use some glassfish specific ways, and so on.

Suraj Chandran
  • 23,444
  • 11
  • 58
  • 92
  • we can do this thing using ResourceBundle as well. But not sure how to use that.I've used ResourceBundle but its not able to read file outside my build – vivekj011 May 24 '11 at 16:07
  • 1
    That seems the best answer or else I misunderstood it. The way I understand it, this is just the standard wrapper approach over different platforms, just as jquery does for javascript over different browsers. –  Sep 11 '15 at 01:02
  • Can you tell me what the GlassFish specific way is? I cannot find it anywhere. – Sajib Acharya Apr 30 '16 at 20:41
  • 1
    don't think, this is right way of doing it; accepted answer makes sure that code is agnostic to app/web servers. – Venkatesh Laguduva Mar 21 '17 at 15:02