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

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.

Related

Access environment variable in .conf file for spring boot app

I have set environment variable by executing the command
export test=abcd
I can see test=abcd when I run printenvcommand
I have deployed a springboot.jar application and I am passing the JAVA_OPTS from the springboot.conf file.
JAVA_OPTS='-Dspring.profiles.active=aaa -Denv=$test'
I started the app by service springboot start . When I check the process, env variable doesn't have the value of $test environment variable.
/usr/bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -Dspring.profiles.active=aaa -Denv=.
How can I access the environment variable in the conf file? I read somewhere the environment variables will be stripped off when run as service. Basically I want to run as service springboot start which internally executes the below command
java -Dspring.profiles.active=aws -Denv=${whatever is set for env environment variable} -jar springboot.jar
I have tried the below configurations but nothing worked
JAVA_OPTS='-Dspring.profiles.active=aaa -Denv='$test
JAVA_OPTS='-Dspring.profiles.active=aaa -Denv='${test}
JAVA_OPTS='-Dspring.profiles.active=aaa -Denv=${test}'
JAVA_OPTS="-Dspring.profiles.active=aaa -Denv=$test"
Be careful about your quotes. Assuming that you use a "normal" shell, variables won't be substituted in single quotes.
java -Dspring.profiles.active=aws -Denv="$myvariable" -jar springboot.jar should lead to env being available in the JVM, no matter if you run it as a service or not.
If you can't get it to work, try to specify a hard coded value like this java -Dspring.profiles.active=aws -Denv=foo -jar springboot.jar. If env is now available in the JVM, your problem is with your shell or run mechanism. Verify that the user who runs the command (i.e. do you use sudo?) has the variable set.
I had the same problem where my .conf was referencing an environment variable which was in the .bashrc.
What I found out is:
The problem is service strips all environment variables but TERM, PATH and LANG which is a good thing. If you are executing the script directly nothing removes the environment variables so everything works.
https://unix.stackexchange.com/questions/44370/how-to-make-unix-service-see-environment-variables
One solution would be to install your app as a systemd service:
https://docs.spring.io/spring-boot/docs/1.3.x-SNAPSHOT/reference/html/deployment-install.html
Or another way is to use docker and you can specify extra configuration in the docker file, like loading a file which contains your environment variables.
As those solutions where not available in my case I ended up with having the value in the .conf file, like: -Denv=prod

In which file Tomcat Java Memory options are saved

I want to change memory configuration of Tomcat. I know it can be done at
Start > Apache Tomcat > Configure Tomcat > Java Tab] as can be seen below
and specifying options like
-Xms512m
-Xmx1024m
-XX:MaxPermSize=512m
-XX:MaxHeapFreeRatio=70
there.
However this program group is created if I install Tomcat from an executable. I have installed Tomcat by simply extracting the zip which does not create Program group. So now where can I specify this information
With regards to the question of where Tomcat's memory options are saved when using the service version, on my machine at least they can be found in the Windows Registry at:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\Tomcat-6\Parameters\Java
Initial memory and Maximum memory are recorded against the JvmMs and JvmMx values, while the options text is recorded against the Options value.
The Tomcat-6 portion of the address on mine is, I believe, based on the identifier I gave to the service (i.e. within the service manager Tomcat is named "Apache Tomcat 6.0 Tomcat-6"), and you may not need to go through Wow6432Node depending on whether you're using 32-bit or 64-bit Tomcat.
I'm assuming here that they haven't made any dramatic changes in where this information is stored in versions of Tomcat more recent than Tomcat 6.
Ohkay while digging inside Tomcat I found some information in one of its txt files (point 3.4) and online:
Apart from CATALINA_HOME (which is set to apache-tomcat-x.x.x directory, for e.g. C:\Program Files\Apache Software Foundation\apache-tomcat-7.0.41) and CATALINA_BASE (optional, defaults to CATALINA_HOME), all environment variables can
be specified in the setenv script. The script is placed either into
CATALINA_BASE/bin or into CATALINA_HOME/bin directory and is named
setenv.bat (on Windows) or setenv.sh (on *nix). The file has to be
readable.
By default the setenv script file is absent. If the script file is present
both in CATALINA_BASE and in CATALINA_HOME, the one in CATALINA_BASE is
preferred.
For example, to configure the JRE_HOME and CATALINA_PID variables you can
create the following script file:
On Windows, %CATALINA_BASE%\bin\setenv.bat:
set "JRE_HOME=%ProgramFiles%\Java\jre6"
exit /b 0
On *nix, $CATALINA_BASE/bin/setenv.sh:
JRE_HOME=/usr/java/latest
CATALINA_PID="$CATALINA_BASE/tomcat.pid"
To set Java options for memory allocation for web app, add something like following (as per memory requirements of your application) to the same file
set JAVA_OPTS="-Xms256m -Xmx512m"
The CATALINA_HOME and CATALINA_BASE variables cannot be configured in the
setenv script, because they are used to locate that file.
All the environment variables described here and the setenv script are
used only if you use the standard scripts to launch Tomcat. For example, if
you have installed Tomcat as a service on Windows, the service wrapper
launches Java directly and does not use the script files.

tomcat6 does not read environment variables

This is just an assumption, but I'm following the log of catalina.out and it looks like every time I would expect a value from an environment variable there is nothing. For example:
java.io.FileNotFoundException: /logs/adminLog.log (No such file or directory) where it should go to $CATALINA_BASE/logs/adminLog.log and $CATALINA_BASE=/var/lib/tomcat6
I've set the environment variables this webapp uses as system wide in the /etc/environment file. I've checked and after restarting they are still there. But tomcat insists of reading blanks.
Any ideas of why this is happening? Am I missing something?
You should put tomcat / webapp specific environment variables into setenv.sh in tomcat's bin directory. Create one if it does not exists.
Depends on how you start Tomcat up. Let us say you are starting as user 'test' (assuming unix machine.). Login as 'test' and check environment variables are there in your environment with the 'env' command.
If it is there then Tomcat when started from that shell, with tomcat/bin/startup.sh will be able to read them.
Now, Tomcat will only read variables it understands. If you are setting your own, then your application needs to read them.

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!

cross server environment variable

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

Categories

Resources