Overwrite the properties file if command line value is present

13,405

Solution 1

Create a loop, instead.

List<String> paramNames = new ArrayList<String>{"NUMBER_OF_THREADS", "NUMBER_OF_TASKS", 
            "ID_START_RANGE", "TABLES"}; // Try to reuse the names from the property file
Map<String, String> paramMap = new HashMap<String, String>();
...
// Validate the length of args here
...
// As you table names can be passed separately. You need to handle that somehow. 
// This implementation would work when number of args will be equal to number of param names
for(int i = 0; i< args.length; i++) {
   paramMap.put(paramNames[i], args[i]); 
}

props.putAll(paramMap);
... // Here props should have it's values overridden with the ones provided

Solution 2

When defining command line input as follows

java -jar Test.jar "C:\\test\\config.properties" 10 100

It means one must always provide noOfThreads to override noOfTasks.

To solve this you could specify these as system properties on command line along with file location which other wise has a default location too. For example: -

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

Then.

  1. Read file properties into Properties.
  2. Iterate over keys in the properties and find corresponding System.getProperty().
  3. If value is found override corresponding entry in the properties.

This way no matter how many new properties you introduce your code will always remain same.

You can go step further and encapsulate all of this in a PropertyUtil that also provide utility methods like getIntProperty(), getStringProperty() etc.

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertyUtil {

  private static final String DEFAULT_CONFIG_FILE_LOCATION = "config.properties";

  private String configFileLocation;

  private Properties properties;

  public PropertyUtil() throws IOException {

    this(DEFAULT_CONFIG_FILE_LOCATION);
  }

  public PropertyUtil(String configFileLocation) throws IOException {

    this.configFileLocation = configFileLocation;
    this.properties = new Properties();
    init();
  }

  private void init() throws IOException {

    properties.load(new FileInputStream(this.configFileLocation));

    for (Object key : this.properties.keySet()) {

      String override = System.getProperty((String) key);

      if (override != null) {

        properties.put(key, override);
      }
    }
  }

  public int getIntProperty(String key) {

    return this.properties.contains(key) ? Integer.parseInt(properties.get(key)) : null;
  }

  public String getStringProperty(String key) {

    return (String) this.properties.get(key);
  }
}

Examples.

config.properties

NUMBER_OF_THREADS=100
NUMBER_OF_TASKS=10000
ID_START_RANGE=1
TABLES=TABLE1,TABLE2

To override NUMBER_OF_THREADS.

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

Short hand example to read 'NUMBER_OF_THREADS' as int.

new PropertyUtil(System.getProperty("config.file.location")).getIntProperty("NUMBER_OF_THREADS");
Share:
13,405
arsenal
Author by

arsenal

profile for ferhan on Stack Exchange, a network of free, community-driven Q&amp;A sites http://stackexchange.com/users/flair/335839.png

Updated on June 04, 2022

Comments

  • arsenal
    arsenal about 2 years

    I have a program which will read everything from config.properties file if command line does not contain any arguments apart from config.properties file location. Below is my config.properties file-

    NUMBER_OF_THREADS: 100
    NUMBER_OF_TASKS: 10000
    ID_START_RANGE: 1
    TABLES: TABLE1,TABLE2
    

    If I am running my program from the command prompt like this-

    java -jar Test.jar "C:\\test\\config.properties"

    It should read all the four properties from the config.properties file. But suppose if I am running my program like this-

    java -jar Test.jar "C:\\test\\config.properties" 10 100 2 TABLE1 TABLE2 TABLE3

    then it should read all the properties from the arguments and overwrite the properties in config.properties file.

    Below is my code which is working fine in this scenario-

    public static void main(String[] args) {
    
            try {
    
                readPropertyFiles(args);
    
            } catch (Exception e) {
                LOG.error("Threw a Exception in" + CNAME + e);
            }
        }
    
        private static void readPropertyFiles(String[] args) throws FileNotFoundException, IOException {
    
            location = args[0];
    
            prop.load(new FileInputStream(location));
    
            if(args.length >= 1) {
                noOfThreads = Integer.parseInt(args[1]);
                noOfTasks = Integer.parseInt(args[2]);
                startRange = Integer.parseInt(args[3]);
    
                tableName = new String[args.length - 4];
                for (int i = 0; i < tableName.length; i++) {
                    tableName[i] = args[i + 4];
                    tableNames.add(tableName[i]);
                }
            } else {
                noOfThreads = Integer.parseInt(prop.getProperty("NUMBER_OF_THREADS").trim());
                noOfTasks = Integer.parseInt(prop.getProperty("NUMBER_OF_TASKS").trim());
                startRange = Integer.parseInt(prop.getProperty("ID_START_RANGE").trim());
                tableNames = Arrays.asList(prop.getProperty("TABLES").trim().split(","));
            }
    
            for (String arg : tableNames) {
    
                //Some Other Code
    
            }
        }   
    

    Problem Statement:-

    Now what I am trying to do is- Suppose if any person is running program like this

    java -jar Test.jar "C:\\test\\config.properties" 10

    then in my program, it should overwrite noOfThreads only-

    noOfThreads should be 10 instead of 100
    

    And suppose if that person is running program like this-

    java -jar Test.jar "C:\\test\\config.properties" 10 100

    then in my program, it should overwrite noOfThreads and noOfTasks only-

    noOfThreads should be 10 instead of 100
    noOfTasks should be 100 instead of 10000
    

    And possible other use cases as well.

    Can anyone suggest me how to achieve this scenario? Thanks for the help

  • arsenal
    arsenal over 11 years
    ASK Adeel. Thanks Adeel for the help. I am not using JDK1.7 so cannot use those braces. :( And also can you provide me the full flow where I am supposed to put this to make this thing work. Thanks for the help.
  • arsenal
    arsenal over 11 years
    Thanks sgp15 for the suggestion. If you can provide me an example basis on my scenario then I would be able to understand much better. Thanks for the help.
  • Adeel Ansari
    Adeel Ansari over 11 years
    +1 for -D option alone. Btw, your getIntProperty() seems broken. So, I fixed it. You are welcome to revert it, if you think it was actually correct.
  • Adeel Ansari
    Adeel Ansari over 11 years
    TechGeeky: I have replaced the diamond operators, so you can use it with Java 6.