179

When passing a -D parameter in Java, what is the proper way of writing the command-line and then accessing it from code?

For example, I have tried writing something like this...

if (System.getProperty("test").equalsIgnoreCase("true"))
{
   //Do something
}

And then calling it like this...

java -jar myApplication.jar -Dtest="true"

But I receive a NullPointerException. What am I doing wrong?

Ryan Berger
  • 9,644
  • 6
  • 44
  • 56
  • consider using `compareToIgnoreCase` instead of `equalsIgnoreCase` for locale-agnostic identifiers; otherwise you may run into the Turkish four-Is problem, among others. – McDowell Feb 19 '11 at 10:10
  • 4
    May I suggest using Boolean.getBoolean instead of the long if-statement that you have? http://www.shankh.com/2009/07/07/some-fun-with-boolean-getboolean/ – mark Dec 28 '11 at 07:31
  • What does -D stands for ? – Anshul Jul 18 '19 at 09:03

3 Answers3

292

I suspect the problem is that you've put the "-D" after the -jar. Try this:

java -Dtest="true" -jar myApplication.jar

From the command line help:

java [-options] -jar jarfile [args...]

In other words, the way you've got it at the moment will treat -Dtest="true" as one of the arguments to pass to main instead of as a JVM argument.

(You should probably also drop the quotes, but it may well work anyway - it probably depends on your shell.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 17
    Works perfectly now. Also interesting to note is that in order to replicate this behavior within the Eclipse debugger these types of parameters must be placed in the VM Arguments section under Run Configurations. – Ryan Berger Feb 18 '11 at 19:52
  • 1
    At least from *bash* it works with the quotes there (and also allows spaces this way), I use this all the day for ant-calls. – Paŭlo Ebermann Feb 18 '11 at 22:03
  • 1
    Feel kinda stupid on how much time I spent on that one! Thanks for pointing that out. :) – toidiu Aug 13 '16 at 22:00
  • 8
    in case someone wondering, if you want to pass multiple properties just use -D multiple time after a 'space' java -D= -D= -D=... – Praveen Tiwari Oct 10 '18 at 02:34
58

That should be:

java -Dtest="true" -jar myApplication.jar

Then the following will return the value:

System.getProperty("test");

The value could be null, though, so guard against an exception using a Boolean:

boolean b = Boolean.parseBoolean( System.getProperty( "test" ) );

Note that the getBoolean method delegates the system property value, simplifying the code to:

if( Boolean.getBoolean( "test" ) ) {
   // ...
}
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Alain Pannetier
  • 9,315
  • 3
  • 41
  • 46
  • 2
    last bit is also true for: `Integer.getInteger("test"); Long.getLong("test")` assuming you have `-Dtest=123` – mtuulu Mar 19 '19 at 18:59
31

You're giving parameters to your program instead to Java. Use

java -Dtest="true" -jar myApplication.jar 

instead.

Consider using

"true".equalsIgnoreCase(System.getProperty("test"))

to avoid the NPE. But do not use "Yoda conditions" always without thinking, sometimes throwing the NPE is the right behavior and sometimes something like

System.getProperty("test") == null || System.getProperty("test").equalsIgnoreCase("true")

is right (providing default true). A shorter possibility is

!"false".equalsIgnoreCase(System.getProperty("test"))

but not using double negation doesn't make it less hard to misunderstand.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • 1
    Actually, `System.getProperty("test", "true").equalsIgnoreCase("true")` would be the better way to write the last condition. – Paŭlo Ebermann Feb 18 '11 at 22:05
  • 3
    `Boolean.getBoolean("test");` is another option. [See](http://download.oracle.com/javase/6/docs/api/java/lang/Boolean.html#getBoolean(java.lang.String)). – superfav Feb 18 '11 at 22:07
  • @Paulo Your solution works for properties only (I wanted to show a general one) but is nicer than mine. – maaartinus Feb 19 '11 at 01:29
  • 2
    Interesting: In this answer the JVM parameter comes *after* the -jar flag, while in the other answer it comes after the "java" but *before* the -jar flag. I take it then that they key is only that the JVM parameter comes before the JAR file itself, in this case "myApplication.jar"? – Colm Bhandal Jun 25 '17 at 09:55
  • @ColmBhandal Funny, nobody has noticed it for six years. What I concentrated on was that there are separate positions for parameters for the JVM and for parameters for the program. I'd suggest to use a more logical parameter order. I'll change my answer. – maaartinus Jun 25 '17 at 12:06
  • @maaartinus I don't think there's a need to change your answer if it works. In fact, I think it's better to have more of a variety of answers that work, so that the sentient aspects of the solution shine through. It seems like in this case, what really matters is that you don't put system parameters after your program name; other than that it doesn't matter where they come relative to the -jar flag. I am only guessing here as I didn't try the code, but that's the knowledge that these answers seem to provide, combined. – Colm Bhandal Jun 25 '17 at 12:11
  • @ColmBhandal It works (I've just tried it), but the order isn't logical and it also doesn't follow the description `java [-options] -jar jarfile [args...]`. So it may stop working one day and the tiny gain provided by my variant may get offset by the lost time of people failing using it. – maaartinus Jun 25 '17 at 12:19
  • Great. That really solidifes it for me. Thanks! – Colm Bhandal Jun 25 '17 at 12:20
  • 1
    Thumbs up for proving the point about double negation in such an obvious way. – Silwing Apr 11 '18 at 08:07