I have deployed a Java Tomat application to Heroku platform. I needed a JDBC datasource. So I have added a "local" context.xml in the "META-INF" directory through maven war plugin.
Heroku provides a system environment variable JDBC_DATABASE_URL that should have served my purpose like below when added to context.xml :
<Resource name="jdbc/postgresqldb" auth="Container" type="javax.sql.DataSource"
url="${JDBC_DATABASE_URL}"
driverClassName="org.postgresql.Driver" initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5" validationQuery="select 1"
poolPreparedStatements="true"/>
However, I could not make it work and have to resort to the following:
<Resource name="jdbc/postgresqldb" auth="Container" type="javax.sql.DataSource"
username="tzse*********" password="bea7c190************************************************"
url="jdbc:postgresql://ec2-54-163-227-202.compute-1.amazonaws.com:5432/****************?sslmode=require"
driverClassName="org.postgresql.Driver" initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5" validationQuery="select 1"
poolPreparedStatements="true"/>
I basically copied and hard coded the environment variables here. This works fine, but is not portable and absolutely ugly!
Any hint where I am going wrong and what I could do to get it right ?
In Heroku console I can see:
2017-08-30T04:38:19.523960+00:00 app[web.1]: Aug 30, 2017 4:38:19 AM org.apache.naming.NamingContext lookup 2017-08-30T04:38:19.523961+00:00 app[web.1]: WARNING: Unexpected exception resolving reference 2017-08-30T04:38:19.523981+00:00 app[web.1]: java.sql.SQLException: Cannot create JDBC driver of class 'org.postgresql.Driver' for connect URL '${JDBC_DATABASE_URL}' 2017-08-30T04:38:19.523983+00:00 app[web.1]: at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:2160)
Does this mean that the reference to environment variables inside context.xml is not referencing the environment variables at all?
As far as I know, context.xml
does not support environment variables. As an alternative, I would recommend writing the context.xml
file on the fly when the app starts up. You would do this by creating a special start.sh
script you use to start your app, and putting the following code in it:
#!/usr/bin/env bash
cat << EOF > context.xml
<Resource name="jdbc/postgresqldb" auth="Container" type="javax.sql.DataSource"
url="${JDBC_DATABASE_URL}"
driverClassName="org.postgresql.Driver" initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5" validationQuery="select 1"
poolPreparedStatements="true"/>
EOF
java -jar yourapp.jar
Of course, you'll need to replace the java -jar yourapp.jar
command with the command you use to run your app (as seen in your Procfile
or heroku ps
). Then you're Procfile
should contain:
web: start.sh
Because this shell script will have access to the JDBC_DATABASE_URL
environment variable, the resulting context.xml
file will contain the full URL.
A bit late... but although context.xml might not support environment variables (such as $JDBC_DATABASE_URL
), it DOES support Java system properties. It's possible to pass an environment variable from Heroku as a system property to your app.
Using a Procfile (which is basically a Java-command-with-prefix) and the webapp-runner :
web: java -cp "target/dependency/*" $JAVA_OPTS -DDB_URL=$JDBC_DATABASE_URL webapp.runner.launch.Main --enable-naming --port $PORT target/*.war
Here, both $JAVA_OPTS
and $JDBC_DATABASE_URL
are environment variables, whereas -DDB_URL
will create a system property. In context.xml, use ${DB_URL}
:
<Resource name="jdbc/postgresqldb" url="${DB_URL}" .../>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.