11

I need to set the codebase for the RMI application I'm working on at the moment and have done this successfully using first

try{
  ResourceBundle config = ResourceBundle.getBundle("myApp");
  String codeBaseUrl = config.getString("codeBaseUrl");
  System.setProperty("java.rmi.server.codebase", codeBaseUrl);
} catch (Exception e) {
  e.printStackTrace();
}

and later using

java -Djava.rmi.server.codebase=http://192.168.1.1/path/to/codebase ...

on the command line.

Both of these approaches allow for the codebase to be changed without the need to recompile, but the System.setProperty approach allows codebase to be bunlded into a properties file and the same launch command to be used.

Most of the tutorials/documentation I've read on this uses the -D approach leading me to believe this is accepted as best practice, but I've been unable to find anything that explains WHY I should use over the other.

Is -D considered best practice for setting system properties such as codebase, and what benefits does this give / what pitfalls does it avoid?

TaninDirect
  • 458
  • 1
  • 7
  • 15

4 Answers4

7

(Edited - I mis-read the question)

Comparing the two:

  • -D is configurable - it's specified at runtime
  • A resource bundle via System.setProperty() is still "runtime", but it's edited via a file which lives beyond the start-up command

Firstly, driving flexible behaviour by specifying settings at runtime is always preferable to hard-coding behaviour (unless the behaviour isn't actually flexible - ie don't use configuration unless there is value in doing so).

The main downside to using a file is that it may contain sensitive data, like passwords, that sysadmins don't want permanently lying around on disk. If the password is entered as part of the start-up command, it's ephemeral and much more secure (session command history not withstanding).

The upside to using a file is that you can establish the correct settings and they stay in the file. You can even manage the file via source control.


There's another even safer option, which is the have the start-up ask for passwords to be entered on the command line, which leaves no trace.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 2
    I missed some details in the question, I accounted for this by getting the property from a resource bundle. – TaninDirect Sep 27 '12 at 01:33
  • 1
    If the password is in the command-line arguments, you've got more to worry about than session history -- any other user on the machine can read the argument list of a running process. – Tim has moved to Codidact Feb 19 '13 at 01:31
4

I would use System.setProperty (at the very top of the application, because for some properties it may be too late otherwise), but take the information from a configuration file.

You almost do that already, but I would also allow for setting arbitrary properties, not just a few hard-coded keys.

I like to combine this with the configuration file that my app already uses, which also contains other (non-System.properties) settings. I distinguish between the two by prefixing the system properties with a -D (just like you would in the command line):

 # some configuration
 a.b.c = xxx

 # RMI settings
 -Djava.rmi.server.codebase = http://192.168.1.1/path/to/codebase

There would be a default location where to find this properties file, but that can be overridden via a command line switch (so that you can toggle between different configurations or have multiple installations of the code easily).

Having a file has the extra benefit that it can serve as documentation, too (as to what options are available, what their defaults are, and so on).

I really wish Java had a built-in facility to get system properties from a properties file, along with other JVM settings like memory and class path. Currently you have to do all that yourself, either in Java or in OS-specific shell wrappers.

Thilo
  • 257,207
  • 101
  • 511
  • 656
2

Unless there is a particular reason not to (e.g. avoiding exposing sensitive information, or preventing tinkering), I'd recommend using "-D" options rather than adding properties using System.setProperty.

  • It is simpler (less code)
  • It allows direct configuration in an application independent way
  • It avoids the problem of something reading the System properties during initialization before your application code has had a chance to set them.

My other recommendation would be NOT to use System properties a dumping ground for large numbers of application specific properties. If you have lots of application configuration properties use a separate Properties object (or something more complicated) and load it from a separate properties file (or something more complicated). Others may disagree with me on this, but I've found this to be a better approach.

(But obviously, if you are using a standard or 3rd party subsystem that looks in System properties, then that's what you need to do.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

Because by passing the argument in at runtime, you can easily have a single codebase for development and production (among other) environments without having to hardcode statements into your code. For example, in development you may want to connect to a server at 192.168.0.1 and in production you may want to go to 10.0.1.1. In order to achieve this result by hardcoding with System.setProperty you would need to have conditional statements and that can get messy.

You generally don't want to have to recompile your app for each environment, so it is often most convenient to pass the argument in at runtime or use some type of property file which can change per system.

jcern
  • 7,798
  • 4
  • 39
  • 47
  • You can use a properties file to store the properties and load them when you run your app. It will be *flexible*, too. Is another disadvantage besides the *hardcode* way? – Luiggi Mendoza Sep 27 '12 at 01:25
  • I am not sure I understand. A property file is flexible, just another method of maintaining flexibility - which was why I mentioned it. The general convention is not to hardcode a specific value into your code, but to allow it to be set at runtime. In most of the apps we develop, we use a mix of command line -D arguments and property files depending on the situation. – jcern Sep 27 '12 at 01:30
  • 2
    Instead of using `-D=` on runtime, you can use a property file to set the runtime properties, then load this file and use `System.setProperty(propertyName, propertyValue)` or similar. What would be the difference in this case? – Luiggi Mendoza Sep 27 '12 at 01:35
  • @LuiggiMendoza, this is exactly what I was doing. I've edited the question to reflect this. – TaninDirect Sep 27 '12 at 01:37
  • @TaninDirect is similar, but IMO you don't have to hardcode the property name in your app, it will be better that your resource bundle has the property/value data in the file, making your app even more flexible. – Luiggi Mendoza Sep 27 '12 at 01:39
  • Generally they offer the same performance, why you would use one or the other would depend mostly on the situation. Say you were developing a webapp and wanted to distribute it as compressed WAR. You can have properties that are unlikely to change in a properties file (like connection urls and such), but there maybe some that you wish to change outside of the WAR. For example, sometimes we have a production.mode property that we set with -D, or logging.level which can be helpful in diagnosing problems. – jcern Sep 27 '12 at 01:46
  • @jcem those could be in the properties file too. Your answer still don't convince me at all =\. Plus, it's easier to store properties name and values in a file and manage it through file version for development/production environment. Is there a really big difference between both? – Luiggi Mendoza Sep 27 '12 at 01:54
  • 1
    Again, this depends on your situation. For infrequently changed properties, a file is usually best. We have instances where we will want to take a machine down and bring it up with a temporary config change (like log level for diagnostics) and modifying a compressed WAR is more involved than changing a -D argument. You may have an environment with many machines and want to set a different param value on each. Both methods are useful, both have their place, and you can usually accomplish the same results with both. Like I said, we use both - and which is best is really dependent on your needs. – jcern Sep 27 '12 at 02:11