cross server environment variable - java

I would like to set to be able to set a string variable such as "DEVEL" or "PRODUCTION", in Glassfishv3 and Apache tomcat 6 servers, and want it to be accessible from java code so I can change behaviour of my app according to the variable. What is the easiest way of doing that?

I do not think there is a method of setting an environment variable that works for both of these servers. There are methods to set an environment variable for each of these servers though.
To set a system property that can be detected by your web application at run-time:
Tomcat : Set the value of the environment variable CATALINA_OPTS and start the server.
export CATALINA_OPTS=-DmyPropertyName=myPropertyValue
GlassFish 3 : There are a couple methods that you can use.
Direct use of a GlassFish system property. Start the server. Use the asadmin command 'create-system-properties' to define a System property. Restart the server.
asadmin create-system-property myPropertyName=myPropertyValue.
Direct use of a JVM Option: Start the server. Use the asadmin command 'create-jvm-option' to create a new JVM option that defines the System property that will be used when the server is started. Restart the server so that it uses the property.
asadmin create-jvm-options -DmyPropertyName=myPropertyValue
To change the value of a system property that can be detected by your web application at run-time:
Tomcat : Change the value of the CATALINA_OPTS environment variable and restart your server.
export CATALINA_OPTS=-DmyPropertyName=myNEWPropertyValue
GlassFish 3 : The method to change the property value depends on the method you used to set the property value.
Direct use of a GlassFish system property. Recreate the GlassFish system property with the 'create-system-properties' command and restart the server.
asadmin create-system-property myPropertyName=myNEWPropertyValue
Direct use of a JVM option: Delete the old jvm option and create a new one in its place. Restart the server.
asadmin delete-jvm-options -DmyPropertyName=myPropertyValue
asadmin create-jvm-options -DmyPropertyName=myNEWPropertyValue
See http://java.net/jira/browse/GLASSFISH-11253
To unset the value of a system property that can be detected by your web application at run-time:
Tomcat : Reset the value of the environment variable CATALINA_OPTS, without including the JVM Option definition. Restart the server.
export CATALINA_OPTS=
GlassFish 3 :
Using a GlassFish system property. Use the 'delete-system-properties' command and restart the server.
asadmin delete-system-property myPropertyName
Using a JVM Option to define the property. Use the delete-jvm-options command and restart the server.
asadmin delete-jvm-options -DmyPropertyName=myPropertyValue
To access a system property from inside your web application
Use System.getProperty(String) or [System.getProperty(String,String)][2]
After saying all this, I want to discourage you from using this info to pursue your stated development strategy.
There are other methods to differentiate a development and production environment that do not involve code changes.
[2]: http://download.oracle.com/javase/6/docs/api/java/lang/System.html#getProperty(java.lang.String, java.lang.String)

For tomcat you can use CATALINA_OPTS environment variable in order to set system properties:
CATALINA_OPTS (Optional) Java runtime options used when the "start",
or "run" command is executed.
So you can setup this in IDE or just in command line:
CATALINA_OPTS=-DdevelopmentMode=true
And then in your app:
System.getProperty("developmentMode")

Use an env-entry in the web.xml :
<env-entry>
<description>development or production</description>
<env-entry-name>devMode</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>PRODUCTION</env-entry-value>
</env-entry>
And in the Java code, you can do :
Context ctx = new InitialContext();
String devMode = (String) ctx.lookup("java:/comp/env/devMode");

It depends whether it should be constant or dynamic variable. Whether you want to change it during compilation time or in the runtime on the fly. With 1st approach you may do that in web.xml setting init parameter or env-entries or even use simple property file packed in the jar archive. With the 2nd approach you could use special kind of configuration table in your database which would be pooled by the application piropdically or maybe you could harness JMX management mechanism and modify configuration on the fly using jconsole

Related

Java Application WAR File Isn't Picking Up Environment Variables on AWS EC2 Using Apache Tomcat and System.getenv

I'm a bit confused on this one. It's working locally on Windows, but when I deploy to AWS EC2 with Apache Tomcat installed and Environment Variables configured it's not working. I'm getting the error;
java.sql.SQLException: The url cannot be null
This can only be coming from the bit of code that is trying to connect to the database, i.e. the Database Connection URL is NULL, which would mean that the .war file isn't picking up the Environment Variable correctly for some reason via the code;
System.getenv("myEnvVar_databaseConnectionURL");
What can I do to debug what is going on here? Seems like this should just be working, but isn't. My gut feel is telling me this is some weird Linux Environment Variable thing which is based on the user that is running, i.e. some kind of Global VS per-user Environment Variable thing. But that's just a guess that I need to dig into a little more. i.e. root Environment Variables VS {Tomcat User X TBC what this is} Environment Variables etc.
I can see the Environment Variables when SSH'ing in as 'root' and running;
printenv | myEnvVar_databaseConnectionURL
Yet when doing a basic command in the deployed code, the output is NULL;
System.out.println("URL: " + System.getenv("myEnvVar_databaseConnectionURL"));
This is when I run the command to print the Tomcat output from AWS EC2 as;
journalctl -u tomcat -f
Posting this question while I investigate further.
Environment variables are not shared across sessions, and they are not shared across user accounts in Linux. Just because you can see an environment variable when logged in as root doesn't mean the tomcat process, running as the tomcat user, can see the same environment variables. If you see an environment variable automatically there when you login, it is because one of the scripts your shell executes as part of your session creation is setting up those environment variables.
Since you didn't provide any details at all as to how you are setting the environment variable, I can't point out what you are doing wrong, or explain in any more detail why your current solution isn't working.
The best solution for setting environment variables for Tomcat is to add them to a $CATALINA_BASE/bin/setenv.sh script. Where the exact location of $CATALINA_BASE on your system is dependent on the flavor of Linux you are using (Ubuntu, RedHat, etc.).

Will a single webapp reload pick up a modified Tomcat setenv.sh?

Is it possible to modify Tomcat environment variables and have them picked up by a single reloaded webapp without restarting the whole server?
Let's say we have webapp A and B, and a setenv.sh:
#!/bin/bash
BASE_DIR=/var/srv
JAVA_HOME=/opt/java/jdk1.8.0_45
TOMCAT_DIR=/opt/apache-tomcat-8.0.18
TOMCAT_PORT=8080
SOME_PROPERTY=SOMETHING
If we change SOME_PROPERTY and reload only A, will it catch the new values, or do we need to restart Tomcat?
setenv.sh is not just a configuration file that is read. It is a script that is executed before the tomcat JVM is started, for setting the environment for the tomcat JVM process (a process for the underlying OS). Once that process is started, it is running in a context with this environment variables.
Java can access and mutate system properties (-D parameters to the JVM command line, not to be confused with env variables) through System.getProperty and System.setProperty but it won't be able, on its own, to parse and interpret the shell script(s) that were used to start the JVM process on the host OS.
My suggestion is to create a configuration file, pass the path to this configuration file in an env variable / system property, and reload this file on application startup.
In the documentation the setenv.sh script is listed as a run at startup script. So, you're going to need to restart Tomcat for changes to take hold.

Adding RAM to Tomcat

Which environment variable should I use to add more RAM to Tomcat?
JAVA_OPTS="-Xmx1024m -Xms256m"
or
CATALINA_OPTS="-Xmx1024m -Xms256m"?
Either will work. However, from skill-guru...
Note that CATALINA_OPTS is a better place than JAVA_OPTS. The former
is only used when actually starting the Tomcat instance. JAVA_OPTS is
also used to start JVMs that only interact with Tomcat (for example
the JVM instance that is used to send the shutdown-message to a
running Tomcat instance).
CATALINA_OPTS is used to control Tomcat environment options, whereas JAVA_OPTS controls the environment options at a higher level ie. for any Java library.
Windows: set CATALINA_OPTS=-Xms(min heap)m -Xmx(max heap)m
Linux: export CATALINA_OPTS=”-Xms(min heap)m -Xmx(max heap)m”
When you'll use CATALINA_OPTS then it's clear that this option is related to Tomcat server. Also when you'll use JAVA_OPTS then any other application could use this settings, and that isn't something that you probably intentionally want to achieve.
JAVA_OPTS. You are providing options to the java command, not the catalina one (which is a shell script).

Setting Environment Variable from Eclipse vs. System

I am using the Gurobi Optimizer, for which I need to set two environment variables: LD_LIBRARY_PATH and GRB_LICENSE_FILE.
If I set the variables using Eclipse (Run As --> Run Configuration --> Environment), everything works correctly. If I set the variables through the system (using export in Linux), I get the error
no GurobiJni46 in java.library.path
Any ideas why this happens and how to fix this?
In the end, I want to run a web application in Tomcat, which would require those variables set correctly.
In the case where you have set the environment variable using export are you then running your application from inside Eclipse or are you running your application from the command line?
The launcher for Eclipse usually explicitly sets the path using the command line switch -Djava.library.path which would overwrite what you have set in the environment.
If you set the LD_LIBRARY_PATH before running Tomcat it would work, provided that Tomcat doesn't override it in one of its start-up scripts!

How to pass a system property to a web application hosted in Tomcat 7 running as a Windows Service?

There are numerous places on the Internet, suggesting that it is easily achieved by any (or all) of the following methods:
through CATALINA_OPTS
through JAVA_OPTS
through TOMCAT_OPTS
by placing the set statements in the setenv.bat file inside the tomcat's bin folder
My problem, is that I have tried all of the above and my web application still does not see my system property!
Here is what I am doing:
Stop tomcat7 service
set CATALINA_OPTS=-Dabc.def=true in the system environment
set JAVA_OPTS=-Dabc.def=true in the system environment
set TOMCAT_OPTS=-Dabc.def=true in the system environment
put all of the above into c:\Program Files\Apache Software Foundation\Tomcat 7.0\bin\setenv.bat (seems totally redundant, but just in case)
Start tomcat7 service
Inspect the environment of the tomcat7 process using the Process Explorer tool - the environment is correct, I do see both CATALINA_OPTS and JAVA_OPTS and TOMCAT_OPTS equal to -Dabc.def=true
run my web app, which is a simple servlet dumping all the system properties to the response stream - abc.def is not amongst them
Please, put me out of my misery and tell me how to do it.
For the Tomcat service, startup settings are stored in the registry under Options key at:
HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat<X>\Parameters\Java
(substitute appropriate Tomcat version where needed).
Edit:
On 64-bit Windows, the registry key is:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\Tomcat<X>\Parameters\Java
even if Tomcat is running under a 64-bit JVM.
I know this post is almost 9 years old but thought someone might find this useful.
Although #prunge and #mark answers were very accurate and following their logic I was able to add system properties to my tomcat 7 instance running on Windows, there is an easier way.
In the installation directory of Tomcat there is an exe you can run called
%INSTALL_DIRECTORY%\bin\tomcat7w.exe
This opens up a Tomcat properties windows where you can control the service i.e. start and stop tomcat and there is a tab (Java) that allows you to set the Java properties as well
Scroll to the end of that panel under "Java Options" and add your system properties
-Dpropertyname=value
Then navigate back to the General tab and restart tomcat
I have tested this and my grails app now can see my properties. I use the following Groovy code to get the property out
System.properties.getProperty("propertyname")
Adding the system properties in the Windows registry showed up in this window as well so its one and the same thing, just this application seems to me to be slightly more convenient.
Hope this helps someone else

Categories

Resources