I have several systems that all need to load the same properties to the JVM. I can use the -D flag to load one property at a time, but i am looking for something that will load all the properties in an entire file at one time. For instance:
I could just add --options-file=blah.properties to all jvms on my network, once, and from then on only change the properties file, which could be a single central file over a network share.
Thank you,
EDIT: Any arguments or commands must also work in a windows environment. Therefore any bash or scripting hacks specific to unix will not work.
That's roughly how we do it:
java $(tr '\n' ' ' < options_file) other args...
Here options_file contains ready -Dsomething or -Xsomething values, one per line. The tr command just replaces every newline with a space.
I don't think you can do that via the command line (without some bash hacks, perhaps), but you definitely can do that programatically:
Simply set one property -DmyPropertiesFile=/your/properties/file.properties and then read that with one of the Properties.load() overloads. After that, System.setProperties(yourProps) should do what you expect.
Of course, this requires that you can hook this code early enough so that your properties will be available when needed (For instance, if the main() method is yours, this is perfect).
Some options:
Wrap your properties in your .jar file and then get your processes to read that properties file from getClass().getResourceAsStream()
Write a batch file to execute your Java processes, and either explicitly list the -D options, or create the command line dynamically.
I solve this problem normally by using Spring (used for other reasons too) and a PropertyPlaceholderConfigurer. That allows me to specify one or more locations for property files and modifies the Spring configuration in-place.
If you use Ant to lanuch the Java process, 9000's answer (plus his windows comment) will work, and you can have the launcher deal with the OS difference.
There is a StackOverflow thread here which describes how to determine the OS from ant
Related
Short version
How do I configure the icedtea-plugin package for ubuntu precise in such a way that it executes all applets with a specific memory limit by default? Preferrably using command line tools and no graphical user interface.
Long version
I'm building a kiosk setup using java applets, and would like to increase the default memory limit for all these applets. The kiosk is based on ubuntu linux, using the icedtea-plugin package as a browser plugin. As building the kiosk is automated and headless, I'd rather configure it from the command line if possible.
Here is what I've found out so far:
I'll probably have to specify a -Xmx… command line argument which will be used when starting the java virtual machine for the plugin.
It is possible to pass such arguments using a parameter in the HTML code, i.e.
<param name="java_arguments" value="-Xmx…">.
But that would mean modifying all my HTML files, which I'd rather avoid. And there is a good chance that I'd have to sign my code to make this work, which adds quite a lot of problems in other places of my project.
On my desktop system, using the Oracle VM, there is an application ControlPanel which I can use to set these command line switches. It seems that the configuration gets written to a file ~/.java/deployment/deployment.properties, where it is associated with the key deployment.javaws.jre.0.args.
That key name is not described in the specs for that file. The number 0 seems to refer to one specific JVM, as represented in one row of the table in the control panel. For each JVM, there are several values besides this args value, all sharing a common index number.
According to this wiki section, IcedTea supports a similar file, located at ~/.icedtea/. Not sure whether that means ~/.icedtea/deployment.properties or rather ~/.icedtea/deployment/deployment.properties. IcedTea does not seem to come with a ControlPanel.
As you can see, there are many hints as to how this might work, but so far I haven't seen any definite answer as to what will work. There are still many open questions:
Do I have to create this icedtea deployment file?
Do I have to include a directory named deployment in the path?
Which is the minimal set of keys that I need to specify to make this file work as intended?
Is the args value even supported by OpenJDK, even if it is not described in the corresponding specification?
I guess I could try out all possible combinations to see whether one of them works, but doing so will take considerable time. So I'm asking here, to see if someone has experience in this, and can provide a quiecker answer. If not, I guess I'll answer my own question eventually, once I've tried things the hard way.
as oracle says: http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/plugin.html.
following environment variable should be set to add additional arguments to applets:
_JPI_VM_OPTIONS=-Xmx…
Moreover as the reffered site says:
Please note that you need to restart your browser after you set the environment variable. If you are setting this environment variable in the command shell, then you must use the same command shell to launch the browser so that the browser inherits the value of environment variable.
However if you doubt how to set environment variable in ubuntu, following post might be helpful: Make $JAVA_HOME easily changable in Ubuntu
I just had a look at the source code of the icedtea-web plugin. The part of the code which builds the command line seems to have no provision at all for including custom arguments, no matter their origin. So it does not matter which config files, HTML files or environment variables I edit, the code there will build the same command line to call java, disregarding all my whishes.
So if all configuration fails, what remains is hackery. One approach would be to patch the source code of the plugin, and make it include additional words into its command line. For a static addition, i.e. a single size change, this would be fairly easy. A more general fix would include the content of some environment variable, the way Peter's answer suggests. That would mean word-splitting the environment variable in question, and allocating the space for the array of words dynamically. Quite a bit of work at the C level.
As an alternative, one could tackle this at the level of the executed binary. The plugin apparently has the path of the executable hard-coded into it. In my case, this path is /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java. One can rename that binary to java.orig, and put a shell script in its place, with the following content:
#!/bin/bash
for i in "$#"; do
if [[ "${i}" == sun.applet.PluginMain ]]; then
exec "$0.orig" -Xmx512m "$#"
fi
done
exec "$0.orig" "$#"
One consequence of this approach is the fact that ps will no longer print these applets as java but instead as java.orig. Should not be a problem in most cases.
Right now my team deals with about 4-5 different servers and about 2-3 different DB servers and we're using environmental variables to decide which server we're on and what server configuration to use.
Is there a better way to do this as my team continues to expand? I've considered compiler flags / args, but it doesn't seem as robust.
From my perspective, in java, you have basically 3 ways to crack this cookie:
Environment variables
-D JVM parameters (which are System Properties)
properties files
You've already discovered Environment Variables and that is pretty much "the unix way" to get the effect you are after; different configuration to common binary that customizes the running application for the environment it is executing on.
System Properties are really the Java "moral equivalent" of Environment Variables. They come in via -D parameters on your application's command line like...
java -Dlogback.configurationFile=/opt/dm/logback.xml -cp app.jar org.rekdev.App
Explicit Properties file processing http://docs.oracle.com/javase/tutorial/essential/environment/properties.html in Java is a third variant which you often see coupled with -D to get something like default behavior which can be overridden at runtime from the command line. That is what is basically going on with the logback.xml configuration above, the JAR file has a logback.xml inside it that will be used unless a System Property called "logback.configurationFile" exists, at which point the App will load it instead.
As you try to figure out how to keep this all in sync and working correctly in a multi-server environment, consider the use of chef http://wiki.opscode.com/display/chef/Home to do the deployments and put each specific environment's customizations under chefs control. Put the chef "recipes" in version control and, voila, full on configuration management.
SHIP IT!
I can see two scenarios
You embed all the different properties within your package (can be a war, ear, jar, or on the file system /yourapp/etc/)
You embed only one property file and this one is created during build (with ant or maven)
Say your app is named foo
Solution 1
It has the advantage that your app can be put as-is on any of the supported servers (all that have a property file in your app package).
Your properties will be named foo.dev.properties, foo.test.properties, foo.prod.properties, foo.damien.properties, foo.bob.properties.
One other advantage is that every developer working has its own dev file that he can safely push on svn/git/whatever and be sure that other developer won't destroy his config.
At runtime the application can check the -D parameter or even retrieve the hostname dinamycally, in order to load the correct property file.
Solution 2
It has the advantage that your package is not polluted by unnecessary properties files.
You must configure a lot of ant tasks/maven target in order to build for specific environment. You will have in your source directory the properties files for the environments also, but only one will be shipped with your app. This one foo.properties will only have placeholders for values, and values will be inferred within it using foo.ENV.properties with the right ant task/maven target.
At my actual job and the previous one also, we did use the solution 1, I think it brings flexibility.
Some parameter (like database user/password) were fetched directly from environment variables on the Unix servers though (so that only the server admins knew the credentials).
You can safely mix the solutions, in order to get where you feel there is the more flexibility for you and your team.
It is possible using -Dproperty=value arguments to set arbitrary system properties (not some fixed set of system properties actually used by the JVM) and a program can get these properties later using System.getProperty("property"). Is it correct to do this?
I haven't found an authoritative answer on this, so that's why I'm asking here. It seems to me that program parameters should be set through command line arguments to the program, not to the JVM. However, perhaps this is an accepted practice that just isn't documented anywhere I've looked so far. I'd like to be sure. Thanks.
I think Java system properties are used to pass values from command line to libraries or plugins inside the execution. It is, that insider component has no direct way to receive the parameter from the main program that's executing it. So it reads it from a "context" that Java system properties are.
If we look at it as layers, command line arguments would be parameters for the inmediate lower layer, and system java properties are context for all the lower layers.
command line: arguments + properties
main program: uses arguments
some library/plugin: uses properties from context
If it's not this way the main program should have to carry all the parameters that user could set to the lower layers and it can be very cumbersome.
I don't like to depend on contextual properties so if I design a program I'd try to pass over all the properties in some non-global way. But it can be very handy some times (and using namespacing it's not probable they collide).
In my opinion this is not "incorrect" and there are programs and libraries that do use their own system properties for configuration.
However, it is probably more practical to put configuration parameters for your software in a configuration file (in whatever format you think is suitable - a .properties file, an XML file, or something else). It is cumbersome, especially if you have many configuration parameters, to have to put all those parameters on the command line with -Dname=value options.
You can use this method to set some of your application settings. I think of settings as a contrast to program arguments. For example. Let's think abount some file converter. It converts file A to B. So files A and B should be command line params. If you converter needs some temporary folder you can make id settable by -Dmy.package.tempfolder=\my\tmp\folder. But there should be a default setting for that and the program should work without this setting.
Think about it as an alternative to .properties file. .properties file will be more convinient of course.
You just have to know what you're doing. If your application is a standalone application, system properties provide an easy to use way to pass named arguments, in any order, to the program, and I don't see anything intrinsically bad in using them.
If your app is a webapp that must be deployed in a app server shared by multiple webapps, then it might not be a good idea, especially if you aren't allowed to change how the server is started, or if you have to deploy multiple versions of the same application.
From http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html:
For example, the following invocation of getProperty looks up the
System property called subliminal.message. This is not a valid system
property, so instead of returning null, this method returns the
default value provided as a second argument: "Buy StayPuft
Marshmallows!"
System.getProperty("subliminal.message",
"Buy StayPuft Marshmallows!");
This implies that properties other than those used by the JVM are "invalid". However, later in the same document, it gives the example of loading a properties file containing the same property setting.
subliminal.message=Buy StayPuft Marshmallows!
It only advises "In general, be careful not to overwrite system properties."
So it seems that this is a supported use of System Properties. It looks like a case of misleading naming. When I hear "System Properties" I think "properties of the JVM" where the JVM is the system. While the properties are used for this, they can also be used for application settings. I think I'll make a mental note to think of this as "System and Application Properties".
Does anyone disagree with this?
I have a JAR-packaged standalone application that, when executed, unpacks itself into a temporal directory and spawns a child process within that directory. The reason being some third-party code and configuration assumes data files are found relative to current working directory, and java has no chdir() method, so the only way is to switch the working dir for a child process.
All works fine, except for the system properties. An operator may decide to specify some system properties in the command line, both standard ones and ones related to the third-party configuration:
java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)
The system properties available to the parent java process are not by default propagated to child. I should do it myself. And here I get into a roadblock: I have no way to tell which properties are set by operator and which are initialized by default by JVM.
Take that java.io.tmpdir one. If operator has provided it, he has a good reason to do so (perhaps the default location is "disk full"). I have to set it to child process, or it will fail. But how do I know if it came from operator? It may be just the default value.
I may try and set all available system properties to the child process. It takes a long list though and, worse, fails in some environments where the command line length is limited.
The only workaround I've found so far (quite a wicked one) is to spawn another child process first, with no arguments at all, and let it pipe back to the parent all the system properties it has. The values that match those that parent has are defaults. The rest should be passed down to the worker child process.
Does anyone have a better alternative?
Where I work, we had a slowly growing list of system properties that users could apply, and while we did not have the child process to worry about, we did have a different issue: there were simply too many.
Rather than making the user supply system properties via the command line (or, in our case, making the line in the script that launches the application yet another property longer), we added support for loading a .properties file by default.
If you can convince users to put permanent properties there, then start the process of launching the child process, and then loading from the file, you could avoid the headache altogether.
Still, you would likely be presented with debug scenarios where temporary, or one-time properties are desired without modifying the file (not that it's really a big deal). You have a few choices here:
Continue to use the approach you are currently.
Get the user to pass the system properties as command line arguments that you then load into system properties for both the parent and child process.
Say tough, use the file. (Not a terrible thing, but I would be annoyed with that solution as a user)
I don't think there is a good answer to this. But fortunately, most of the standard system properties either can't be overridden, or nobody in their right mind would override.
So the following approaches are probably your best bets:
pass on the subset of the standard properties that you think that it makes sense to pass on,
provide a way to specify the JVM options (including -D options) to be used for child JVMs, or
a combination of the above approaches.
Chosen solution:
I still had to go with a child process that does nothing but passes the parent all the system properties it gets to compare. The only minor issue I stumbled upon was line.separator property which caused my line reading code stumble on extra empty line. That was easy to fix.
Why I accepted none of answers:
Approaches suggested in the answers below are reasonable, but none of them is completely satisfying.
I do not have much power over the users to tell them that Java system properties should be passed via a property file or a special command-line argument. This is awkward and goes against operational practices (special cases are always bad).
I cannot also select a subset of system properties to pass to the child process. System class documentation doesn't tell which ones are OK to overwrite (and common sense replaces no documentation). There is also a facility for end-user to define their own properties, and those I cannot predict neither by name no number.
How do I set the maximal jvm-memory without adding an extra batch-script to my Programm.
Answer is provided below.
It's a good question, but your implmenetation assumes a lot. I presume you have to document the name of your jar for your users to invoke "java -jar xyz.jar" on so can you also include in the documentation that "-Xmx256M" is required?
You may have more luck using a java launcher, such as this one for Windows, where you put the launcher config (path, max memory etc.) in a separate file. For cross platform, there's LaunchAnywhere, and others, which function similarly. See How can I convert my Java program to an .exe file?
To improve upon your existing scheme:
use the java.home system property to resolve the location of the JDK/JRE
use the java.class.path to set up the class path, and similarly for java.library.path if your application requires native code.
pass command arguments passed to your main method to the spanwed process
But still, this seems to be a lot of effort that at best represents a leaky abstraction, when instead simple and clear documentation would suffice.