Java Config File not specific to directory - java

I am using a configuration (.ini) file with my java app. At the moment I am specifically calling the location of the dll like this.
Properties p = new Properties();
p.load(new FileInputStream("C:\\myconfigfile.ini");
I would like to have it so the user does not have to put it into a certain directory before the program operates.
Is there a way to implement this or is this just the best practice to go with.

Put it in the CLASSPATH and load resource as stream using the class loader. That'll always work, even for web apps in WAR files or JARs.

You should put your ini in a resources folder and load them as resources. Here's an excellent tutorial to get you started.

make an ini folder in your root directory, and put it in there. Then when you start your program, it's all relative to where you start from.
Properties p = new Properties();
p.load(new FileInputStream(".\\ini\\myconfigfile.ini");

Have a look at Apache Commons Configuration.
It is solving many issues around configuration files. It also supports having individual configs for each user what is imho very important for development in a team.

Related

FileInputStream in Spring MVC fails to find file

I am working on a SpringMVC project which runs a number of automated tests on a database. The access details for this database are located in a .properties file. This file is located within the project directory.
FileInputStream fis = new FileInputStream("batch-dm.properties");
propFile = new Properties();
propFile.load(fis);
As the file is stored in the project directory the FileInputStream should be able to access it no?
If I provide the absolute path e.g.
FileInputStream fis = new FileInputStream("C:/workspace/Project/batch-dm.properties");
It recognises the file and runs properly.
Do I need to sore this file in a different location because it is a Spring MVC project?
Thanks
Just to clear out your mind, try to see what is the value that outputs System.getProperty("user.dir") (let's call it A), this will print the complete absolute path from where your application was initialized, more specifically it will print the directory from where the JVM was started.
If you doesn't supply a parent path to the file that you are trying to open, the (A) path is taken by default and the file is looked inside that directory. So please, have in mind that.
Aditional information
If you absolutely need that file you should include it in your project so you can access it as a resource. Resource is a file that is included in your project and came bundled with the generated .jar or .war for re distribution.
My advice is to put the file in the package and use as a resource as it the safer way to work with external resources that should be shipped with your project.
Take a deeper look at this post for more about practical way of handling resources.
Please refer below link:
https://stackoverflow.com/a/2308388/1358551
You may have to use getResourceAsStream().

System.getProperty("catalina.base") There can be scenario where client may use any other server

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.
There are basically two ways.
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);
// ...
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.
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.
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.

Find conf file regardless how application started

I'm newbie to java.
I have some directory structure
product/
conf/
classes/com/../..
conf/ contains some configuration file, while under classes/ I have my application.
How can I ensure from inside java code that I'm able to find file in conf/ despite way I'm executing it (e.g. from eclipse, from different directories, from crontab etc.).
P.S.
Files in conf/ are not resources, since required to be edited by user.
Is there're way to know where my .class, so I canuse relative path form that directory to reach my directory (e.g. MY_CLASS_DIR/../../../../conf)
I would put the conf directory into the class path. That way you can always find them by:
YourClass.class.getClassLoader().getResource("conf/....");
You can use the absolute path, including the way to product.
Or you may use a configuration setting, by starting your program like
java -DXY_HOME=/some/path/product ...
From the javacode, you use it:
String xyHome = System.getProperty ("XY_HOME")
Or you use a kind of inifile in your home directory, where you specify where to look for the conf-directory.
Rereading your question multiple times, it is unclear to me what your goal is. To find the conf dir independently from where you are (eclipse, crontab, ...)? But the headline asks for the CWD, which is the opposite - the directory, depending on where you are.
Both is possible, but you have to decide what you want.
Its safe to use relative paths than absolute paths. Even if you JAR your classes tomorrow it will work as is,
Put you configuration files in classpath during deployment.(Please note that
project directory structure can be different from that of deployment directory structure)
product/
classes/com/../..
classes/conf/some_conf.properties
Then you can use Apache common configuration to get the URL of file
URL urlOfFile = org.apache.commons.configuration.
ConfigurationUtils.locate("conf/some_conf.properties");
The other alternative you can try is,
URL urlOfFile = <SomeClassFromClassesFolder>.class.
getClassLoader().getResource(resourceFile);
Once you get the URL of your configuration file getting stream out of it very simple,
InputStream stream = urlOfFile.openStream();
Good luck.
For you understanding you can refer the following as well,
http://bethecoder.com/applications/tutorials/showTutorials.action?tutorialId=Java_IO_CurrentWorkingDirectory
http://bethecoder.com/applications/tutorials/showTutorials.action?tutorialId=Java_Reflection_WheretheClassloadedfrom
Good luck.
you can find out what is the absolute path of the working dir by:
String str = new File("").getAbsolutePath()

Config files - where to put them in Java?

I have a java desktop app and the issue of config files is vexing me.
What I want is for my distributable application folder to look like this:
MyApp/Application.jar
MyApp/SpringConfig.xml
MyApp/OtherConfig.xml
MyApp/lib
But at the moment SpringConfig.xml is inside Application.jar and I can't even find OtherConfig.xml programmatically.
I don't care how I set up the various files in my compilation path, so long as they end up looking like the above.
So..
where do i put the files in my dev setup?
and how do i access them programmatically?
thanks
the spring config file is related to the code and wiring of your application, hence it'd better be inside the jar, and should be subject to change by the users
(new File(".")).getAbsolutePath(); returns the absolute path of your jar - then you can load the OtherConfig.xml by a simple FileInputStream
if the SpringConfig.xml contains configuration data like database credentials, put them in an external application.properties and use a custom PropertyPlaceholderConfigurer to load the external file.
Answering the question "where do I put the files in my dev setup" is not possible because we don't know your environment.
Actually, if you want to be able to edit the config yourself (and not necessarily end-users), you can open the jar with any zip software (WinRAR for instance) and edit the config file from within the jar.
Update: as it seems you can't make the config files to be places out of the jar. Well, for a start, you can do it manually - whenever the .jar is complete, just remove the config file from inside and place it outside.
I typically create a structure where I have a src/ directory and then other directories exist at the same level. Some of those directories include:
lib/ - External Libraries
config/ - Configuration Files
resources/ - Various resources I use (images, etc)
At that same level, I then create an Ant script to perform my build so that the appropriate config files, resources, lib, etc are copied into my JAR file upon build. It has worked great for me up to this point and is a fairly easy to understand organizational structure.
Update: Accessing my config files is done, typically, by knowing their location and opening them up and reading them in the code. Because I use Ant to build, I make sure that my config files are in a location that I expect. So, for example, in a recent application I created, when I compile, my JAR file is in the top level directory (relative to the application release structure). Then, there is a "main" config file at that same level. And there is a "theme" config file that is in a themes folder.
To read the various files, I just open them up as I would any other file and read them in and go from there. It's nothing particularly fancy but it works well and it makes it easy to manually change configurations if I need to do so.
In dev mode, put them in source dir and they will be copied to your classes folder, you can then access them using classloader.
Example:
URL url = ClassLoader.getSystemResource("test.properties");
Properties p = new Properties();
p.load(new FileInputStream(new File(url.getFile())));
In Prod mode, you can make them part of your jar.

Simulate app.config for Java?

I know that you can use java.util.Properties to read Java properties files.
See: Java equivalent to app.config?
Is there a standard place to put this file? In .NET we put application.exe.config in the same directory as application.exe. The application looks for it here by default.
Java can be made to look for a properties file in the class path but I am struggling to understand the filename/path structure to use and how to use either a standard .properties format or XML format file.
Assuming I have an API packaged in org_example_api.jar (the root package is org.example.api). I don't want to put the properties file inside the jar as it should be editable by the user. I want the user to be able to put the required configuration properties in either a .properties or .xml file somewhere relative to the classpath so I can find it without needing to know anything about the ir file system structure.
Will this work on all systems:
/classpath/org_example_api.jar
/classpath/org/example/api/config.properties OR
/classpath/org/example/api/config.xml
Code:
java.util.Properties = ? //NEED SOME HELP HERE
This purely depends on the type of application you are developing.
1) If it is a web application the best place is inside the WEB-INF/classes/ folder.
2) If you are developing a standalone application there are many approaches. From your example I think the following structure will work.
/<dist>/org_example_api.jar
/<dist>/config.xml
/<dist>/run.sh
In the run.sh you can start the java application providing the current directory also in the classpath. Something like this.
java -cp .:org_example_api.jar ClassToExecute
3) If it is an API distribution it is up to the end user. You can tell the user that they can provide the config.xml in the classpath which should follow some predefined structure. You can look at Log4J as an example in this case.
The world is wide open to you here. The only best practice is what works best for you:
Whatever program the user is running can require the path to the properties file as an argument
Your application can be configured to look in the current directory for config.properties.
If the file can't be found, you could maybe fall back to the user.home directory, or fall back to wherever your application is installed.
Personally I usually have my applications attempt to read properties files from the classpath - but I'm not in a world where I have end-users update/change the file.
Whatever option you choose, just make sure you clearly document it for your users so they know which file to edit and where it needs to be!
You can put the properties file in a directory or JAR in your CLASSPATH, and then use
InputStream is = getClass().getResourceAsStream("/path/goes/here");
Properties props = new Properties();
props.load(is);
(I noticed you mentioned this in your OP, but others may find the code useful.)

Categories