Best way to read properties file in java? - java

I am aware of two ways to read a .properties file:
1- System.getProperties.load(Inputstream for .properties file);
2- Creating a new Properties object and then calling load(Inputstream for .properties file);
In first approach, are we going to store values of .properties file in the System object. Is it utilizing more resources?
Would like to know which is the best way to do it or apart from above two ways, if there is any other best way, please let me know.
Thanks.

Depends on what the properties file represents. If it represents system properties which needs to override/supply some default system properties, then go for the first approach. But if it represents application-specific properties (which is more often the usual case), then go for the second approach.

IMO, it is a BAD idea to load application properties into the System properties object. If someone puts bogus property values into the file you are loading, this could cause all sorts of obscure failures. For example, setting "java.home" to a bogus value will cause JavaMail to fail, and setting one of the "*.separator" properties could cause all sorts of things to behave strangely.
If your application really needs to "overlay" the system properties, then it would be better to do this:
Properties props = new Properties(System.getProperties());
props.load(someInputStream);
If it doesn't, then just load the Properties as follows:
Properties props = new Properties();
props.load(someInputStream);
If for some reason you need to override values in the System Properties object itself, then you should do it much more carefully / selectively.

we will read properties files using the URl...
Properties props = new Properties();
try
{
java.net.URL url = Thread.currentThread().getContextClassLoader().getResource(fileName);
java.net.URL url2 = ClassLoader.getSystemResource(fileName);
props.load(url.openStream());
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return props;

Related

How do I add properties to a properties file using Java?

I have a real quick question. I have a Java program in which I use a properties file. The file is used for keeping track of the program's users. My problem is I cannot figure out how to ADD to the file. I know how to set existing properties to a value, but I don't know how to add more properties without over writing the other ones.
I would like the program to 'register' users, so to speak. Whenever a new users 'signs up', I want the program to add a new property containing the new user's information. I run into this problem though:
Example:
File: numOfUsers=0
One user registers. The username is 'c00lGuy'. The program registers this in the file:
File: numOfUsers=1 user1-username=c00lGuy
Another user registers. She decides to call her username 'theGr8Girl'. The program registers this:
File: numOfUsers=2 user2-username=theGr8Girl
The file after the two users registered:
File: numOfUsers=2 user2-username=theGr8Girl
How do I prevent my program from overwriting existing lines in the file? It seems to erase the file's contents, and then add what I tell it to. I don't want it to erase the file's contents.
The code I am using to register the properties:
Properties prop = new Properties();
OutputStream output = null;
int userCount = getUserCount();
userCount++;
try {
output = new FileOutputStream(fileName);
// set the properties value
prop.setProperty("numOfUsers", String.valueOf(userCount));
prop.setProperty("user" + userCount + "-username", username);
// save properties to project root folder
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null)
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Try something like this:
FileOutputStream out = new FileOutputStream(fileName);
props.setProperty("numOfUsers", 2);
...
props.store(out, null);
out.close();
Properties files aren't really intended for this sort of usage, but if you have a small enough data set it'll work.
The step you are missing is that you need to read the properties from disk, make the changes, then save them back to disk.
Properties props = new Properties();
try{
props.load(inputStream);
} finally {
inputStream.close();
}
props.setProperty(....);
try{
props.store(outputStream);
} finally {
outputStream.close();
}
Just bear in mind that this is not at all suitable for any sort of volume processing. Also, there is a race condition if you have two threads trying to make changes to the properties file at the same time.
If you are looking for a lightweight persistent store, I highly recommend mapdb.
You code is creating a new Properties object each time. Make sure to reuse the old instance when adding a user.
The typical format for a line in this file would be
user=hashedPassword
so use the username as the key and the password as a value. The number of users does not need to be stored, it is just the size of the properties map.

Multiple projects retrieving credentials from a local file

I have several different projects and all of them currently hardcode server names, DB user and passwords.
I have found all of the places that need to be changed in order to point to a new server, but there are at least 50 instances where the same change is required, which looks like terrible design.
I would like to change this so that this information is centralized so no one else would have to go hunting for this again. I have read about setting environment variables, but preferably I would like to include the information with the projects themselves such as reading from some sort of configuration file.
How should I approach this?
How about properties file? You can use it like this as suggested here :
public class App {
public static void main( String[] args )
{
Properties prop = new Properties();
try {
//load a properties file
prop.load(new FileInputStream("config.properties"));
//get the property value and print it out
System.out.println(prop.getProperty("database"));
System.out.println(prop.getProperty("dbuser"));
System.out.println(prop.getProperty("dbpassword"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Java - Properties failing to load, but storing properly

I need a configuration file (Properties) for this project I'm working on.
The issue is that the Properties instance fails to load from the file (no exceptions, no visible problems) although it can store properly.
Because I have a defaults HashMap, any property that doesn't exist has it's default value placed in the Properties instance, which then stores everything, so that new properties are seamlessly added when the production server is updated.
I've been tracking this bug for hours, and I can't fix it. I've read dozens of questions here on StackOverflow as well as code examples on other sites. Nothing helped.
The one reason I haven't dropped it already and used the DB instead is that the JDBC driver URL, user and password are stored in that file as well. Notice that the file is being read and written to the hard drive.
Since the defaults system puts stuff in place, even if the file doesn't exist when I try to read, after it's saved it appears, but the next run still won't read anything. I noticed the bug after I changed a setting, and checked the file after a few runs, and to my shock, all values were default.
What's currently happening is the following:
1) No matter if the file is there or not, Properties will not load anything.
2) Since there's nothing in the Properties instance, it is filled with defaults.
3) The instance will now save, overwriting the file with the default values.
Here's all the relevant code:
private static Properties getConfig(){
Properties properties = new Properties();
File cfgFile = new File("data/titallus.properties");
try{
if(cfgFile.createNewFile()){
System.out.println("Config file not found. A default config file will be created automatically.");
}
FileReader reader = new FileReader(cfgFile);
FileWriter writer = new FileWriter(cfgFile);
properties.load(reader);
reader.close();
System.out.println(properties); // Debug, always prints '{}'
for(String k : defaults.keySet()){
if(!properties.containsKey(k)){
properties.setProperty(k, defaults.get(k));
}
}
properties.store(writer, "Titallus Configuration File");
writer.close();
}catch(Exception e){
e.printStackTrace();
System.exit(-1);
}
return properties;
}
I have tried everything I could think of, to no avail.
I also have a Properties subclass for multi-language support, which works just fine.
Does anyone have any idea how to fix this, or at least, another approach to this?
FileWriter writer = new FileWriter(cfgFile);
will be erasing your file before you read from it.
You create a FileWriter for the file before you load the file, which clears the existing data.

override log4j configuration programmatically: file location for FileAppender

is it possible to override the "File" property of an appender that has been configured in the log4j.properties without creating a new appender?
And if so - how?
This is the situation: I have two apenders, A1 is a ConsoleAppender and A2 is a FileAppender. A2's "File" points a generic error.log:
log4j.appender.A2.File=error.csv
This appender only logs error-level events or worse through
log4j.appender.A2.Threshold=error.
Now I want those errors to be written in different files depending on which class caused the error, as there are several classes that instances are being created of.
Being able to see which class created the error(s) fast would be of great help, as it is a lot more helpful then skimming through the error.log looking for the class-tags.
So my idea was to override the "File" property e.g. in the constructors of these newly created classes, so they log errors in different files.
Thanks a lot in advance!
For changing log4j properties on runtime visit this link
http://alperkaratepe.wordpress.com/2010/01/16/how-to-change-log4j-properties-at-runtime/
private void updateLog4jConfiguration(String logFile) {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream( "/log4j.properties");
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("Error: Cannot laod configuration file ");
}
props.setProperty("log4j.appender.FILE.file", logFile);
PropertyConfigurator.configure(props);
}
Old question (well indexed in google). In addition to OP's requirement, adding additional methods iv'e read about to manipulate log4j.properties
Modify loaded log4j.properties in runtime
private void updateLog4jConfiguration(String logFile) {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream( "/log4j.properties");
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("Errornot laod configuration file ");
}
props.setProperty("log4j.appender.FILE.file", logFile);
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
}
full example is in this article
Setting log4j.properties in runtime
Can be done manually
Properties properties = new Properties();
properties.setProperty("log4j.logger.org.hibernate", "ERROR");
// ...
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
Or by loading a different properties file
Properties properties = new Properties();
properties.load(new FileInputStream("/etc/myapp/properties/custom-log4j.properties"));
LogManager.resetConfiguration();
PropertyConfigurator.configure(properties);
VM Option
You can tell log4j to load a different file using log4j.configuration VM option
java -Dlog4j.configuration=file:///etc/myapp/properties/custom-log4j.properties
if you choose this option, it must be provided in the execution line

java update properties file run time

i am writing standalone java app for production monitoring. once it starts running the api is configured for default values which is set in .properties file. in running state the api's configuration can be changed and the .properties file should be updated accordingly. is there a way to achieve this ? or are there any other approaches to implement this ?
Thanks in advance
The Java Properties class (api here) specifies "load" and "store" methods which should do exactly that. Use FileInputStream and FileOutputStream to specify the file to save it into.
You could use a very simple approach based on the java.util.Properties class which has indeed a load and store methods that you can use in conjunction with a FileInputStream and FileOutputStream:
But actually, I'd recommend to use an existing configuration library like Commons Configuration (amongst others). Check the Properties Howto to see how to load, save and automatically reload a properties file using its API.
I completely agree that Apache Commons Configuration API is really good choice.
This example update properties at runtime
File propertiesFile = new File(getClass().getClassLoader().getResource(fileName).getFile());
PropertiesConfiguration config = new PropertiesConfiguration(propertiesFile);
config.setProperty("hibernate.show_sql", "true");
config.save();
From the post how to update properties file in Java
Hope this help!
java.util.Properties doesn't provide runtime reloading out-of-the-box as far as I know.
Commons Configuration provides support for reloading configuration at runtime. The reload strategy can be configured by setting a ReloadingStrategy on the PropertiesConfiguration object. It also offers various other useful utilities for making your application configurable.
In addition to the load and store method of the Properties class, you can also use the Apache Commons Configuration library, which provides functions to easily manipulate configuration files (and not only .properties files).
Apache common configuration API provided different strategies to reload property files at run time. FileChangedReloadingStrategy is one of them. Refer this link to see an example for property file reloading at run time using FileChangedReloadingStrategy.
Try this:
// Write in property file at runtime
public void setValue(String key, String value) {
Properties props = new Properties();
String path = directoryPath+ "/src/test/resources/runTime.properties";
File f = new File(path);
try {
final FileInputStream configStream = new FileInputStream(f);
props.load(configStream);
configStream.close();
props.setProperty(key, value);
final FileOutputStream output = new FileOutputStream(f);
props.store(output, "");
output.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// Read same file
public String getValue(String key) {
String value = null;
try {
Properties prop = new Properties();
File f = new File(directoryPath+"/src/test/resources/runTime.properties");
if (f.exists()) {
prop.load(new FileInputStream(f));
value = prop.getProperty(key);
}
} catch (Exception e) {
System.out.println("Failed to read from runTime.properties");
}
return value;
}

Categories