How to pass a system property using Wrapper.exe - java

How do I pass a property to a Java process, started as a Windows service using Wrapper.exe?
The target code calls:
System.getProperty("ADMIN_USERNAME");

http://wrapper.tanukisoftware.org/doc/english/prop-java-additional-n.html
You can set "additional parameters" that will go to the JVM (as opposed to your main class), and -DADMIN_USERNAME=gandalf should work there.
wrapper.java.additional.1=-Xrs
wrapper.java.additional.2=-Dprop=TRUE
wrapper.java.additional.3=-DADMIN_USERNAME=gandalf
Update: You must start with additional.1 and count up without gaps (This is a convention for shoe-horning lists into Java properties syntax).

You can set certain properties in the wrapper config file, see this link:
http://wrapper.tanukisoftware.org/doc/english/properties.html
I believe you can also configure the wrapper to startup java and pass additional properties using the java "-Dproperty=value" syntax

This is a shot in the dark, but have you considered using JMX to communicate with the service? Or is this overkill for what you need?
Yuval =8-)

#Thilo's answer is correct but I feel I must add that you have to take care for JAVA_OPTS environment variable. Many people/servers tend to use it (e.g: remote debugging) as whatever you put into JAVA_OPTS is passed as JVM arguments to any new JVM. If you have this environment variable set then any wrapper.java.additional.<n> will be ignored. I found that on the hard way :)

Related

How can I get command line arguments from java equinox bundle?

I've an equinox application and I want get some eventual command line parameters that the user can use. How can I get these parameters?
The list of possible arguments are listed in the EclipseLauncher class as constants. If you want, you can get the constants of the class with reflection. System property names are prefixed with "PROP_".
This might work for one version, but not for other. I would not recommend this.
You can get the system properties via System.getProperties() (I guess this was trivial).
If you want to now if the arguments have been passed in Oracle based JVM with the sun.java.command system property. This will not work with other JVM implementations.
Non of the options above are suggested to use in production :). I would be interested in the use-case you want to implement by getting these arguments programmatically.

How to read "OS variables" from Java (not System.properties)

I just read the excellent 12 Factor App document and it really registered with me. In Chapter 3 Config, the author stresses that:
The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.
I'm wondering what this implies for Java projects.
Typically, when it comes to my Java apps, I think of "env vars" as things that I can read from System.getProperty("blah"). Is this what the author is talking about? I don't think this is, because the author explicitly states "and unlike...or other config mechanisms such as Java System Properties...".
If not, what would be an example of an OS-agnostic "env var" that would satisfy this document's definition of "env var"? How would I read it from inside Java code?
Either way, some process has to first set each env var on the OS, so that the var is set & available by the time the app runs. What processes/methods could do this type of pre-run setup?
Use System.getenv() instead of System.getProperty(). System.getenv() returns value of specified environment variable defined in your OS.
Other, and probably preferable way is to pass selected OS environment variable to your JVM using -D command switch and then retrieve them using System.getProperty(). This way is more cross-platform: you may use the same java code even if specific platform does not support specific variable.
Updating the OS variables is absolutely other task. First, I do not think that you really want to do this. If you still want try to ask another question: probably other solution exists.
There is no cross platform API that does this in JDK and I do not know 3rd party library that dies this too. I personally planned to implement one but did not have time for this so far.
Windows stores variables in registry, so you can add variable to registry. But this does not affect current instance of shell, so your own java process will not see variables that it updated itself. You can however create process and run SET myvar=myvalue. If you want to write to registry you can use any of available libraries. Occasionally I implemented such library too. Its advantage is that it does not run any native code and is very compact. Take a look here.
On Unix you can run myvar=myvalue and if you want other processes to see this variable you have to run export myvar. But it still does not make this variable persisted. If you want this variable to survive OS restart you have to add it to one of the initial scripts (e.g. .bashrc). But this is completely depends on your system, configuration, permissions, shell etc.
Yes, the author is talking about environment variables. You can read environment variables from java code using the following snippet:
System.getenv(env);
See: http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getenv-java.lang.String-
If you want OS agnostic way, you can use JVM arguments and read using
System.getProperties();
For example, if you want a variable called var1 to be passed, use java -Dvar1=true -jar myJar.jar

How do I pass variables to JVM that are referenced in .property file?

I have following in my .properties file:
connection1.username=${cloud.db.username}
connection1.password=${cloud.db.password}
I'd like to pass these variables in Run/Debug Configuration
I thought all I need to do is to pass following parameters in JVM command line: -Dcloud.db.username=JOHN -Dcloud.db.password=SECRET.
But in the code call to Properties.getProperty() still returns ${cloud.db.username}.
I'm running it as junit under IntelliJ IDEA.
Passing properties into a jvm using -D puts them into the system properties (accessed via System.getProperties()).
Creating a java.util.Properties from a file in code gives you a completely separate set of properties.
Lots of applications allow you to specify properties via the command line -D option and in a file. To do this they have to implement some sort of fallback mechanism between the two and decide which gets preference.
Also, some applications allow you to define a property as referring to another, they generally do this either by extending or wrapping java.util.Properties.
You're expecting both of these things to work but neither are provided by Java out of the box.
If you want to implement these features, take a look at some open source projects that support them.
I don't fully understand why would you want to do something like that. Why do you need those values in the property file if you are not really using it?
If you want to pass those two parameters as custom command line parameters (-D) then can't you just do:
System.getProperty("cloud.db.username");
System.getProperty("cloud.db.password");
The value for connection1.username will alway be "${cloud.db.username}", java does not replace it with the value of another property or an environment variable.
If you want such a replacement, then you'll have to implement it (iterate through the entire value set of the properties object and replace all values, that match this pattern with the values of the referenced properties)
Trying accessing them via System.getProperty(...) instead

Is it correct for Java system properties to be used to set and get arbitrary program parameters?

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?

What's the best way to pass arguments to a tomcat instance?

What's the best way to pass arguments to a tomcat instance? Are command line arguments available to all applications within the container? Can I pass arguments to particular apps? Do I need to manage this through the built in app server?
EDIT:
To clarify, I'm looking to pass a parameter to specify the configs to use. Sometimes this might specify a set of configuration files which can differ per environment.
you can add -Dmy.config.var=configA and -Dmy.config.var=configB and to CATALINA_OPTS (each time the one you need) and read them from java via System.getProperty("my.config.var"). These are not environment variables.
I believe that the best way to configure it would be to use the server.xml and context.xml files. This is the place to add JNDI configuration. You can have a different context.xml file for every application. In your WAR file place this at META-INF directory and Tomcat will import it.
Everything can see the generic system environment through the standard Java Properties mechanism. Also, the environment variable CATALINA_OPTS can be used to pass arguments to the JVM.
Stuff that needs to go magically to a web application should be put in JNDI. This allows you to put and retreive objects in a "global hashtable" outside somewhere.
If all you need to do is have a configuration file name, then pass in a property (-Dfoo=bar).

Categories

Resources