Configure data sources for a Tomcat, or Java SE app in Azure App Service
This article shows how to configure data sources in a Java SE, Tomcat app in App Service.
Azure App Service runs Java web applications on a fully managed service in three variants:
- Java SE - Can run an app deployed as a JAR package that contains an embedded server (such as Spring Boot, Dropwizard, Quarkus, or one with an embedded Tomcat or Jetty server).
- Tomcat - The built-in Tomcat server can run an app deployed as a WAR package.
Note
For Spring applications, we recommend using Azure Spring Apps. However, you can still use Azure App Service as a destination.
Configure the data source
To connect to data sources in Spring Boot applications, we suggest creating connection strings and injecting them into your application.properties file.
In the "Configuration" section of the App Service page, set a name for the string, paste your JDBC connection string into the value field, and set the type to "Custom". You can optionally set this connection string as slot setting.
This connection string is accessible to our application as an environment variable named
CUSTOMCONNSTR_<your-string-name>
. For example,CUSTOMCONNSTR_exampledb
.In your application.properties file, reference this connection string with the environment variable name. For our example, we would use the following code:
app.datasource.url=${CUSTOMCONNSTR_exampledb}
For more information, see the Spring Boot documentation on data access and externalized configurations.
Tip
By default, the Linux Tomcat containers can automatically configure shared data sources for you in the Tomcat server. The only thing for you to do is add an app setting that contains a valid JDBC connection string to an Oracle, SQL Server, PostgreSQL, or MySQL database (including the connection credentials), and App Service automatically adds the cooresponding shared database to /usr/local/tomcat/conf/context.xml for you, using an appropriate driver available in the container.
These instructions apply to all database connections. You need to fill placeholders with your chosen database's driver class name and JAR file. Provided is a table with class names and driver downloads for common databases.
Database | Driver Class Name | JDBC Driver |
---|---|---|
PostgreSQL | org.postgresql.Driver |
Download |
MySQL | com.mysql.jdbc.Driver |
Download (Select "Platform Independent") |
SQL Server | com.microsoft.sqlserver.jdbc.SQLServerDriver |
Download |
To configure Tomcat to use Java Database Connectivity (JDBC) or the Java Persistence API (JPA), first customize the CATALINA_OPTS
environment variable that is read in by Tomcat at start-up. Set these values through an app setting in the App Service Maven plugin:
<appSettings>
<property>
<name>CATALINA_OPTS</name>
<value>"$CATALINA_OPTS -Ddbuser=${DBUSER} -Ddbpassword=${DBPASSWORD} -DconnURL=${CONNURL}"</value>
</property>
</appSettings>
Or set the environment variables in the Configuration > Application Settings page in the Azure portal.
Next, determine if the data source should be available to one application or to all applications running on the Tomcat servlet.
Application-level data sources
Create a context.xml file in the META-INF/ directory of your project. Create the META-INF/ directory if it doesn't exist.
In context.xml, add a
Context
element to link the data source to a JNDI address. Replace thedriverClassName
placeholder with your driver's class name from the table above.<Context> <Resource name="jdbc/dbconnection" type="javax.sql.DataSource" url="${connURL}" driverClassName="<insert your driver class name>" username="${dbuser}" password="${dbpassword}" /> </Context>
Update your application's web.xml to use the data source in your application.
<resource-env-ref> <resource-env-ref-name>jdbc/dbconnection</resource-env-ref-name> <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type> </resource-env-ref>
Shared server-level resources
You can't directly modify a Tomcat installation for server-wide configuration because the installation location is read-only. To make server-level configuration changes to your Windows Tomcat installation, the simplest way is to do the following on app start:
- Copy Tomcat to a local directory (
%LOCAL_EXPANDED%
) and use that asCATALINA_BASE
(see Tomcat documentation on this variable). - Add your shared data sources to
%LOCAL_EXPANDED%\tomcat\conf\server.xml
using XSL transform.
Add a startup file
Create a file named startup.cmd
%HOME%\site\wwwroot
directory. This file runs automatically before the Tomcat server starts. The file should have the following content:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File %HOME%\site\configure.ps1
Add the PowerShell configuration script
Next, add the configuration script called configure.ps1 to the %HOME%_\site directory with the following code:
# Locations of xml and xsl files
$target_xml="$Env:LOCAL_EXPANDED\tomcat\conf\server.xml"
$target_xsl="$Env:HOME\site\server.xsl"
# Define the transform function
# Useful if transforming multiple files
function TransformXML{
param ($xml, $xsl, $output)
if (-not $xml -or -not $xsl -or -not $output)
{
return 0
}
Try
{
$xslt_settings = New-Object System.Xml.Xsl.XsltSettings;
$XmlUrlResolver = New-Object System.Xml.XmlUrlResolver;
$xslt_settings.EnableScript = 1;
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load($xsl,$xslt_settings,$XmlUrlResolver);
$xslt.Transform($xml, $output);
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
echo 'Error'$ErrorMessage':'$FailedItem':' $_.Exception;
return 0
}
return 1
}
# Start here
# Check for marker file indicating that config has already been done
if(Test-Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker"){
return 0
}
# Delete previous Tomcat directory if it exists
# In case previous config isn't completed or a new config should be forcefully installed
if(Test-Path "$Env:LOCAL_EXPANDED\tomcat"){
Remove-Item "$Env:LOCAL_EXPANDED\tomcat" Recurse
}
md -Path "$Env:LOCAL_EXPANDED\tomcat"
# Copy Tomcat to local
# Using the environment variable $AZURE_TOMCAT90_HOME uses the 'default' version of Tomcat
New-Item "$Env:LOCAL_EXPANDED\tomcat" -ItemType Directory
Copy-Item -Path "$Env:AZURE_TOMCAT90_HOME\*" "$Env:LOCAL_EXPANDED\tomcat" -Recurse
# Perform the required customization of Tomcat
$success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml
# Mark that the operation was a success if successful
if($success){
New-Item -Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker" -ItemType File
}
This PowerShell completes the following steps:
- Check whether a custom Tomcat copy exists already. If it does, the startup script can end here.
- Copy Tomcat locally.
- Add shared data sources to the custom Tomcat's configuration using XSL transform.
- Indicate that configuration was successfully completed.
Add XSL transform file
A common use case for customizing the built-in Tomcat installation is to modify the server.xml
, context.xml
, or web.xml
Tomcat configuration files. App Service already modifies these files to provide platform features. To continue to use these features, it's important to preserve the content of these files when you make changes to them. To accomplish this, use an XSL transformation (XSLT).
Add an XSL transform file called configure.ps1 to the %HOME%_\site directory. You can use the following XSL transform code to add a new connector node to server.xml
. The identity transform at the beginning preserves the original contents of the configuration file.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Identity transform: this ensures that the original contents of the file are included in the new file -->
<!-- Ensure that your transform files include this block -->
<xsl:template match="@* | node()" name="Copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()" mode="insertConnector">
<xsl:call-template name="Copy" />
</xsl:template>
<xsl:template match="comment()[not(../Connector[@scheme = 'https']) and
contains(., '<Connector') and
(contains(., 'scheme="https"') or
contains(., "scheme='https'"))]">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
<xsl:template match="Service[not(Connector[@scheme = 'https'] or
comment()[contains(., '<Connector') and
(contains(., 'scheme="https"') or
contains(., "scheme='https'"))]
)]
">
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="insertConnector" />
</xsl:copy>
</xsl:template>
<!-- Add the new connector after the last existing Connnector if there's one -->
<xsl:template match="Connector[last()]" mode="insertConnector">
<xsl:call-template name="Copy" />
<xsl:call-template name="AddConnector" />
</xsl:template>
<!-- ... or before the first Engine if there's no existing Connector -->
<xsl:template match="Engine[1][not(preceding-sibling::Connector)]"
mode="insertConnector">
<xsl:call-template name="AddConnector" />
<xsl:call-template name="Copy" />
</xsl:template>
<xsl:template name="AddConnector">
<!-- Add new line -->
<xsl:text>
</xsl:text>
<!-- This is the new connector -->
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="${{user.home}}/.keystore" keystorePass="changeit"
clientAuth="false" sslProtocol="TLS" />
</xsl:template>
</xsl:stylesheet>
Set CATALINA_BASE
app setting
The platform also needs to know where your custom version of Tomcat is installed. You can set the installation's location in the CATALINA_BASE
app setting.
You can use the Azure CLI to change this setting:
az webapp config appsettings set -g $MyResourceGroup -n $MyUniqueApp --settings CATALINA_BASE="%LOCAL_EXPANDED%\tomcat"
Or, you can manually change the setting in the Azure portal:
- Go to Settings > Configuration > Application settings.
- Select New Application Setting.
- Use these values to create the setting:
- Name:
CATALINA_BASE
- Value:
"%LOCAL_EXPANDED%\tomcat"
- Name:
Finalize configuration
Finally, you place the driver JARs in the Tomcat classpath and restart your App Service. Ensure that the JDBC driver files are available to the Tomcat classloader by placing them in the /home/site/lib directory. In the bash, run az webapp deploy --type=lib
for each driver JAR:
az webapp deploy --resource-group <group-name> --name <app-name> --src-path <jar-name>.jar --type=lib --target-path <jar-name>.jar
Next steps
Visit the Azure for Java Developers center to find Azure quickstarts, tutorials, and Java reference documentation.