Using Program Parameters in Java Part-2
Alternatives to the command line
Giving parameters on the command line is not always the best way to enter properties for your program. A typical situation where something else is needed is when your Java program isn’t invoked through a main method. An good example is when you have coded a servlet for a web server. In this situation you may use the web.xml
file to specify the parameters you need.
Another servlet example could be when you’re using Struts. In this case you don’t code the servlet, so it might be more logical to place the parameter on the Struts action. You may then use the parameter
attribute on the action
element in the struts-config file for entering parameters.
If you have access to the command line where the VM is initiated you may use the -D
option to pass parameters to your own code. For example:
1 2 | java - Dmykey=myvalue dk.hansen.playground.SomeMainClass |
mykey
and myvalue
are available through the Java system properties interface, which provides a nice segue to the next topic: the Properties
class.
The Java Properties class
The Properties
class is an interface to the file system–or rather a Java InputStream
. To read parameters from a file you first enter your information in the file as key-value pairs:
1 | mykey=myvalue |
Here’s the code needed to read the value for the mykey
parameter from a file called my.properties
(for the Java program to find the properties file it should be placed in the classpath).
1 2 3 4 5 6 7 8 9 10 11 | Properties props = new Properties(); try { props.load(new FileInputStream("my.properties")); } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(-1); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } System.out.println(props.getProperty("mykey")); |
This is a nice way to specify parameters to your program. You may create several property files if this is more convenient for your application, and why not combine this solution with CLI and specify the name of the property file as a command line option:
1 | java dk.hansen.playground.SomeMainClass -file my.properties |
A complete main program that combines CLI with a property file looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | package dk.hansen.playground; import java.io.*; import java.util.Properties; import org.apache.commons.cli.*; public class ReadPropertyFile { public static void main(String[] args) { Option option1 = new Option("file", "name of property file to read"); option1.setArgs(1); option1.setArgName("filename"); Options options = new Options(); options.addOption(option1); CommandLineParser parser = new BasicParser(); CommandLine cmd = null; try { cmd = parser.parse( options, args); } catch (ParseException e) { System.out.println("***ERROR: " + e.getClass() + " " + e.getMessage()); HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "parameters:", options ); return; } // Get the name of the properties file // - if specified String fileName = ""; if (cmd.hasOption("file")) fileName = cmd.getOptionValue("file"); else fileName = "my.properties"; // Read the property file Properties props = new Properties(); try { props.load(new FileInputStream(fileName)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println(props.getProperty("mykey")); } } |
System properties
I briefly mentioned that you could enter key/value pairs to the Java VM like this:
1 | java -Dmykey=myvalue dk.hansen.playground.SomeMainClass |
Such values may be retrieved from the System
Properties
instance like this:
1 2 | String value = System.getProperty("mykey")); . . . |
More key-value pairs are entered by repetition:
1 | java -Dmykey=myvalue -Dmykey2=myvalue2 dk.hansen.SomeMainClass |
This solution could be used when your code is used by a main program that can’t be modified.
In the CLI section I mentioned that CLI also allows you to specify key-value pairs. This is useful if you for some reason don’t know the parameter names in advance. Here’s a handy way of specifying a key-value option called “X”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | . . . Option property = OptionBuilder.withArgName("property=value") .hasArgs() .withValueSeparator() .withDescription( "use value for given property" ) .create( "X" ); Options options = new Options(); options.addOption( property ); CommandLineParser parser = new BasicParser(); String[] args2 = {"-X", "a=1", "b=2"}; try { CommandLine line = parser.parse(options, args2); System.out.println(Arrays.asList(line.getOptionValues("X"))); } catch( ParseException exp ) { System.out.println( "Parsing failed. Reason: " + exp.getMessage() ); } . . . |
Note that you must separate the -X parameter from its values by at least one blank space. Here’s the output from this code:
1 | [a, 1, b, 2] |
You get 4 values back in a String array.