21

I have a Tomcat 8 project that uses a datasource (see below)

<Resource auth="Container" 
          name="jdbc/JtmDS"  
          driverClassName="org.apache.derby.jdbc.EmbeddedDriver" 
          type="javax.sql.DataSource" 
          username="xfer"
          password="xfer10" 
          url="jdbc:derby:/home/PUID/tm/control/JtmDB"                    
          initialSize="25"
          maxTotal="100" 
          maxIdle="30" 
          maxWaitMillis="10000"                                      
          removeAbandonedOnBorrow="true"
          removeAbandonedTimeout="20" />

This works perfectly well.

However the url is a hard-coded path /home/PUID/tm/control/JtmDB

When this gets into production the PUID part of the path will differ across numerous systems. I have an environment variable set export PUID=abcd The rest of the application is able to use things like System.getenv( ) or ${env:PUID} as and where appropriate.

These all work fine.

My question is very simply: How can I make the PUID value in my context.xml a variable that can be read from an environment variable?

thonnor
  • 1,206
  • 2
  • 14
  • 28

2 Answers2

25

I finally discovered what I actually needed to do here.... Quite simple in the end.

I passed in a java parameter to Tomcat at runtime as shown below.

I added the following bits to setenv.sh

export PUID=abcd

JAVA_OPTS=-Dpuid=${PUID} 

Then edited my context.xml as shown here

<Resource auth="Container" 
          name="jdbc/JtmDS"  
          driverClassName="org.apache.derby.jdbc.EmbeddedDriver" 
          type="javax.sql.DataSource" 
          username="xfer"
          password="xfer10" 
          url="jdbc:derby:/home/${puid}/tm/control/JtmDB"                    
          initialSize="25"
          maxTotal="100" 
          maxIdle="30" 
          maxWaitMillis="10000"                                      
          removeAbandonedOnBorrow="true"
          removeAbandonedTimeout="20" />

So now my Tomcat installation will read this and be able to use a different path for each different PUID.


Background: This works because Tomcat will automatically perform variable substition in its configuration files:

Tomcat configuration files are formatted as schemaless XML; elements and attributes are case-sensitive.

Apache Ant-style variable substitution is supported; a system property with the name propname may be used in a configuration file using the syntax ${propname}. All system properties are available including those set using the -D syntax, those automatically made available by the JVM and those configured in the $CATALINA_BASE/conf/catalina.properties file.

Apache Tomcat 9 Configuration Reference - Overview

The part:

JAVA_OPTS=-Dpuid=${PUID}

describe above is necessary because Tomcat will only read Java system properties (which are provided by the JVM), but not environment variables (which are provided by the OS/runtime libraries that the JVM is running on). The parameter -D sets a Java system property from the environment variable of the same name.

sleske
  • 81,358
  • 34
  • 189
  • 227
thonnor
  • 1,206
  • 2
  • 14
  • 28
  • 1
    Thanks for that answer. It works for other values as well. – O. Schnieders Nov 28 '19 at 09:47
  • Absolutely. You can put anything you want in there. – thonnor Nov 28 '19 at 14:06
  • 1
    Keep in mind that this exposes the env var values in the command line if you query something like `ps -eo args`. This can potentially be grabbed by instrumentation agents and send to lots of places, which may leak passwords and other secrets. – Bruno Medeiros Jan 29 '21 at 09:01
  • My I ask in which context you're running the setenv.sh? Facing the same problem locally, but I am not able to the Java Opts through with this... – Remo Mar 24 '21 at 09:11
  • Its been a while since I looked at this. This was run via a Command Line so the setenv.sh was automatically read by Tomcat. We just needed to make sure the correct variable were in there. If you can't change setenv.sh then I'm not sure how you will be able to do this. – thonnor Mar 26 '21 at 10:44
2

Either you set the JVM env. variables as mentioned by sleske above.

If you like to use the system env. variables you have to set the JAVA_OPTS: -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource
For more information have a look at this entry: inject environment variables in tomcat catalina.properties [Kubernetes]

Hope this helps at least one person! (:

kaerbr
  • 21
  • 2