11

Our code uses a lot of system properties eg, 'java.io.tmpdir', 'user.home', 'user.name' etc. We do not have any constants defined for these anywhere (and neither does java I think) or any other clever thing for dealing with them so they are in plain text littered throughout the code.

String tempFolderPath = System.getProperty("java.io.tmpdir");

How is everyone using system properties?

willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111

7 Answers7

9

I would treat this just as any other String constant you have scattered throughout your code and define a constant variable for it. Granted, in this case "java.io.tmpdir" is unlikely to change, but you never know. (I don't mean that Sun might change the meaning of "java.io.tmpdir", or what system property it points to, but that you might change your mind about what system property you need to read.)

If you're only using a particular property within one class, then I'd define the constants right in that class.

private final String TEMPDIR = "java.io.tmpdir";

If you're using the same properties in different classes, you may want to define an static class of your own to hold the constants you use most often.

public final Class Prop {
    public static final String TEMPDIR = "java.io.tmpdir";
    ...
}

Then, everywhere you need to use that constant just call it using

System.getProperty(Prop.TEMPDIR);
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • But where would you do that? Make some sort of constants only interface somewhere for just system properties? Never been a big fan of them really. Any suggestions? – willcodejavaforfood Jan 28 '09 at 13:28
  • I added a couple of different suggestions, but I think for constant strings you in a lot of different classes, the interface you describe is the best way. – Bill the Lizard Jan 28 '09 at 13:37
5

SystemUtils provided by Apache Commons Lang package, solves this problem.

SystemUtils has defined constant for most of the system properties, which can be obtained by a lookup, for example:

import org.apache.commons.lang3.SystemUtils;

class Something
{
    public static void main(String[] args){     
        System.out.println(SystemUtils.JAVA_IO_TMPDIR);
    }
}

Probably, that is a cleaner way to do it.

a3.14_Infinity
  • 5,653
  • 7
  • 42
  • 66
4

I think that in an object oriented software, you have probably an object (or a method) that have a dependency on a directory where a job has to be done. So, you can put in evidence this dependency on the constructor or the method. After that, if you need a default for that directory and the default come from a system property, you can simply create a factory method or a constructor/method with less parameters passing to the other costrunctor/method a:

new File(System.getProperty("java.io.tmpdir");

You don't need to create a "dependency magnet" only to contain a configuration parameter.

Sixro
  • 402
  • 4
  • 16
4

if you are using it in multiple places it might be a good idea to write a class to encapsulate reading the property and maybe other properties.

so maybe something like: Configuration.getTemporaryDirectory()

4

Since the question title is extremely broad, I'll throw in another good practice you should consider when using system properties. Access to system properties can by denied by the SecurityManager, so you may need to access them through a PrivilegedAction, like this:

String tmpdir = AccessController.doPrivileged(new PrivilegedAction<String>() {
  public String run() {
    return System.getProperty("java.io.tmpdir");
  }
});

Use a privileged action when your code constrains a sensitive action so that it will be safe even if malicious code invokes it.

For example, it would be unsafe to use a privileged action in a method like OutputStream open(File file). Untrusted code could invoke it, and use your code's privileges to write anything, anywhere.

However, if you had a method that saved user preferences for your application to a file you choose, that would probably be safe. A malicious caller can't choose the file location or its contents; those are specified by your code. So, your method can use a privileged action to allow it to be invoked by unprivileged code.

erickson
  • 265,237
  • 58
  • 395
  • 493
1

I'd treat these as any other constant, probably with a P_ or PROP_ prefix, and put them in an appropriate constants class.

If you use lots of them, I'd even consider splitting them out to a PropertyNames constants class:

public final class PropertyNames
{
  private PropertyNames()
  {
     // no instantiation
  }

  public static final String P_VAR_DIRECTORY = "org.acme.app.varDir";

  public static final String P_TMP_DIRECTORY = "java.io.tmpDir";
}

Finally, I would seriously considering namespacing the property names themselves, with the standard reverse domain name used for packages. This is just to avoid clashing with third-party properties consumers.

jamesh
  • 19,863
  • 14
  • 56
  • 96
0

In Java, Strings are immutable, which means the same object in memory space is not overwritten; a new String is created every time. The currently highest voted suggestion is to use a constant:

System.getProperty(Prop.TEMPDIR);

Unfortunately, the constant being used is for the actual property key. That means that every time you make this call, you're going to create a new String object to hold the value. In my opinion, you should make the constant the result of the call itself:

public static final String SYS_PROP_TEMP_DIR = System.getProperty("java.io.tmpdir");
Cody Burleson
  • 244
  • 2
  • 6
  • 1
    That's incorrect: you're not creating a String, rather the JRE is returning a reference to a String and it will quite likely give you the same one on subsequent calls, rather than creating it afresh. However it's still worth doing as you suggest because the `System.getProperty()` call is apparently quite slow: http://stackoverflow.com/a/18045622/587365 – Andrew Spencer Jun 11 '15 at 13:52
  • 1
    also it doesn't hurt to encapsulate the fact that you are obtaining this information from a system property. – Andrew Spencer Jun 11 '15 at 13:54