Configure a Java app for Azure App Service
Note
For Spring applications, we recommend using Azure Spring Apps. However, you can still use Azure App Service as a destination. See Java Workload Destination Guidance for advice.
Azure App Service lets Java developers to quickly build, deploy, and scale their Java SE, Tomcat, and JBoss EAP web applications on a fully managed service. Deploy applications with Maven plugins, from the command line, or in editors like IntelliJ, Eclipse, or Visual Studio Code.
This guide provides key concepts and instructions for Java developers using App Service. If you've never used Azure App Service, you should read through the Java quickstart first. General questions about using App Service that aren't specific to Java development are answered in the App Service FAQ.
Show Java version
To show the current Java version, run the following command in the Cloud Shell:
az webapp config show --name <app-name> --resource-group <resource-group-name> --query "[javaVersion, javaContainer, javaContainerVersion]"
To show all supported Java versions, run the following command in the Cloud Shell:
az webapp list-runtimes --os windows | grep java
To show the current Java version, run the following command in the Cloud Shell:
az webapp config show --resource-group <resource-group-name> --name <app-name> --query linuxFxVersion
To show all supported Java versions, run the following command in the Cloud Shell:
az webapp list-runtimes --os linux | grep "JAVA\|TOMCAT\|JBOSSEAP"
For more information on version support, see App Service language runtime support policy.
Deploying your app
Build Tools
Maven
With the Maven Plugin for Azure Web Apps, you can prepare your Maven Java project for Azure Web App easily with one command in your project root:
mvn com.microsoft.azure:azure-webapp-maven-plugin:2.11.0:config
This command adds an azure-webapp-maven-plugin
plugin and related configuration by prompting you to select an existing Azure Web App or create a new one. Then you can deploy your Java app to Azure using the following command:
mvn package azure-webapp:deploy
Here's a sample configuration in pom.xml
:
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-webapp-maven-plugin</artifactId>
<version>2.11.0</version>
<configuration>
<subscriptionId>111111-11111-11111-1111111</subscriptionId>
<resourceGroup>spring-boot-xxxxxxxxxx-rg</resourceGroup>
<appName>spring-boot-xxxxxxxxxx</appName>
<pricingTier>B2</pricingTier>
<region>westus</region>
<runtime>
<os>Linux</os>
<webContainer>Java SE</webContainer>
<javaVersion>Java 11</javaVersion>
</runtime>
<deployment>
<resources>
<resource>
<type>jar</type>
<directory>${project.basedir}/target</directory>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
</deployment>
</configuration>
</plugin>
Gradle
Set up the Gradle Plugin for Azure Web Apps by adding the plugin to your
build.gradle
:plugins { id "com.microsoft.azure.azurewebapp" version "1.7.1" }
Configure your web app details. The corresponding Azure resources are created if they don't exist. Here's a sample configuration, for details, refer to this document.
azurewebapp { subscription = '<your subscription id>' resourceGroup = '<your resource group>' appName = '<your app name>' pricingTier = '<price tier like 'P1v2'>' region = '<region like 'westus'>' runtime { os = 'Linux' webContainer = 'Tomcat 9.0' // or 'Java SE' if you want to run an executable jar javaVersion = 'Java 8' } appSettings { <key> = <value> } auth { type = 'azure_cli' // support azure_cli, oauth2, device_code and service_principal } }
Deploy with one command.
gradle azureWebAppDeploy
IDEs
Azure provides seamless Java App Service development experience in popular Java IDEs, including:
- VS Code: Java Web Apps with Visual Studio Code
- IntelliJ IDEA:Create a Hello World web app for Azure App Service using IntelliJ
- Eclipse:Create a Hello World web app for Azure App Service using Eclipse
Kudu API
Java SE
To deploy .jar files to Java SE, use the /api/publish/
endpoint of the Kudu site. For more information on this API, see this documentation.
Note
Your .jar application must be named app.jar
for App Service to identify and run your application. The Maven plugin does this for you automatically during deployment. If you don't wish to rename your JAR to app.jar, you can upload a shell script with the command to run your .jar app. Paste the absolute path to this script in the Startup File textbox in the Configuration section of the portal. The startup script doesn't run from the directory into which it's placed. Therefore, always use absolute paths to reference files in your startup script (for example: java -jar /home/myapp/myapp.jar
).
Tomcat
To deploy .war files to Tomcat, use the /api/wardeploy/
endpoint to POST your archive file. For more information on this API, see this documentation.
JBoss EAP
To deploy .war files to JBoss, use the /api/wardeploy/
endpoint to POST your archive file. For more information on this API, see this documentation.
To deploy .ear files, use FTP. Your .ear application is deployed to the context root defined in your application's configuration. For example, if the context root of your app is <context-root>myapp</context-root>
, then you can browse the site at the /myapp
path: http://my-app-name.azurewebsites.net/myapp
. If you want your web app to be served in the root path, ensure that your app sets the context root to the root path: <context-root>/</context-root>
. For more information, see Setting the context root of a web application.
Don't deploy your .war or .jar using FTP. The FTP tool is designed to upload startup scripts, dependencies, or other runtime files. It's not the optimal choice for deploying web apps.
Logging and debugging apps
Performance reports, traffic visualizations, and health checkups are available for each app through the Azure portal. For more information, see Azure App Service diagnostics overview.
Stream diagnostic logs
To access the console logs generated from inside your application code in App Service, turn on diagnostics logging by running the following command in the Cloud Shell:
az webapp log config --resource-group <resource-group-name> --name <app-name> --docker-container-logging filesystem --level Verbose
Possible values for --level
are: Error
, Warning
, Info
, and Verbose
. Each subsequent level includes the previous level. For example: Error
includes only error messages, and Verbose
includes all messages.
Once diagnostic logging is turned on, run the following command to see the log stream:
az webapp log tail --resource-group <resource-group-name> --name <app-name>
If you don't see console logs immediately, check again in 30 seconds.
Note
You can also inspect the log files from the browser at https://<app-name>.scm.azurewebsites.net/api/logs/docker
.
To stop log streaming at any time, type Ctrl
+C
.
You can access the console logs generated from inside the container.
First, turn on container logging by running the following command:
az webapp log config --name <app-name> --resource-group <resource-group-name> --docker-container-logging filesystem
Replace <app-name>
and <resource-group-name>
with the names appropriate for your web app.
Once container logging is turned on, run the following command to see the log stream:
az webapp log tail --name <app-name> --resource-group <resource-group-name>
If you don't see console logs immediately, check again in 30 seconds.
To stop log streaming at any time, type Ctrl+C.
You can also inspect the log files in a browser at https://<app-name>.scm.azurewebsites.net/api/logs/docker
.
For more information, see Stream logs in Cloud Shell.
SSH console access
To make open a direct SSH session with your container, your app should be running.
Paste the following URL into your browser and replace <app-name>
with your app name:
https://<app-name>.scm.azurewebsites.net/webssh/host
If you're not yet authenticated, you're required to authenticate with your Azure subscription to connect. Once authenticated, you see an in-browser shell, where you can run commands inside your container.
Note
Any changes you make outside the /home directory are stored in the container itself and don't persist beyond an app restart.
To open a remote SSH session from your local machine, see Open SSH session from remote shell.
Troubleshooting tools
The built-in Java images are based on the Alpine Linux operating system. Use the apk
package manager to install any troubleshooting tools or commands.
Java Profiler
All Java runtimes on Azure App Service come with the JDK Flight Recorder for profiling Java workloads. You can use it to record JVM, system, and application events and troubleshoot problems in your applications.
To learn more about the Java Profiler, visit the Azure Application Insights documentation.
Flight Recorder
All Java runtimes on App Service come with the Java Flight Recorder. You can use it to record JVM, system, and application events and troubleshoot problems in your Java applications.
Timed Recording
To take a timed recording, you need the PID (Process ID) of the Java application. To find the PID, open a browser to your web app's SCM site at https://<your-site-name>.scm.azurewebsites.net/ProcessExplorer/
. This page shows the running processes in your web app. Find the process named "java" in the table and copy the corresponding PID (Process ID).
Next, open the Debug Console in the top toolbar of the SCM site and run the following command. Replace <pid>
with the process ID you copied earlier. This command starts a 30-second profiler recording of your Java application and generate a file named timed_recording_example.jfr
in the C:\home
directory.
jcmd <pid> JFR.start name=TimedRecording settings=profile duration=30s filename="C:\home\timed_recording_example.JFR"
SSH into your App Service and run the jcmd
command to see a list of all the Java processes running. In addition to jcmd itself, you should see your Java application running with a process ID number (pid).
078990bbcd11:/home# jcmd
Picked up JAVA_TOOL_OPTIONS: -Djava.net.preferIPv4Stack=true
147 sun.tools.jcmd.JCmd
116 /home/site/wwwroot/app.jar
Execute the following command to start a 30-second recording of the JVM. It profiles the JVM and creates a JFR file named jfr_example.jfr in the home directory. (Replace 116 with the pid of your Java app.)
jcmd 116 JFR.start name=MyRecording settings=profile duration=30s filename="/home/jfr_example.jfr"
During the 30-second interval, you can validate the recording is taking place by running jcmd 116 JFR.check
. The command shows all recordings for the given Java process.
Continuous Recording
You can use Java Flight Recorder to continuously profile your Java application with minimal impact on runtime performance. To do so, run the following Azure CLI command to create an App Setting named JAVA_OPTS with the necessary configuration. The contents of the JAVA_OPTS App Setting are passed to the java
command when your app is started.
az webapp config appsettings set -g <your_resource_group> -n <your_app_name> --settings JAVA_OPTS=-XX:StartFlightRecording=disk=true,name=continuous_recording,dumponexit=true,maxsize=1024m,maxage=1d
Once the recording starts, you can dump the current recording data at any time using the JFR.dump
command.
jcmd <pid> JFR.dump name=continuous_recording filename="/home/recording1.jfr"
Analyze .jfr
files
Use FTPS to download your JFR file to your local machine. To analyze the JFR file, download and install Java Mission Control. For instructions on Java Mission Control, see the JMC documentation and the installation instructions.
App logging
Enable application logging through the Azure portal or Azure CLI to configure App Service to write your application's standard console output and standard console error streams to the local filesystem or Azure Blob Storage. Logging to the local App Service filesystem instance is disabled 12 hours after it's configured. If you need longer retention, configure the application to write output to a Blob storage container. Your Java and Tomcat app logs can be found in the /home/LogFiles/Application/ directory.
Enable application logging through the Azure portal or Azure CLI to configure App Service to write your application's standard console output and standard console error streams to the local filesystem or Azure Blob Storage. If you need longer retention, configure the application to write output to a Blob storage container. Your Java and Tomcat app logs can be found in the /home/LogFiles/Application/ directory.
Azure Blob Storage logging for Linux based apps can only be configured using Azure Monitor.
If your application uses Logback or Log4j for tracing, you can forward these traces for review into Azure Application Insights using the logging framework configuration instructions in Explore Java trace logs in Application Insights.
Note
Due to known vulnerability CVE-2021-44228, be sure to use Log4j version 2.16 or later.
Customization and tuning
Azure App Service supports out of the box tuning and customization through the Azure portal and CLI. Review the following articles for non-Java-specific web app configuration:
- Configure app settings
- Set up a custom domain
- Configure TLS/SSL bindings
- Add a CDN
- Configure the Kudu site
Copy App Content Locally
Set the app setting JAVA_COPY_ALL
to true
to copy your app contents to the local worker from the shared file system. This setting helps address file-locking issues.
Set Java runtime options
To set allocated memory or other JVM runtime options, create an app setting named JAVA_OPTS
with the options. App Service passes this setting as an environment variable to the Java runtime when it starts.
In the Azure portal, under Application Settings for the web app, create a new app setting named JAVA_OPTS
for Java SE or CATALINA_OPTS
for Tomcat that includes other settings, such as -Xms512m -Xmx1204m
.
To configure the app setting from the Maven plugin, add setting/value tags in the Azure plugin section. The following example sets a specific minimum and maximum Java heap size:
<appSettings>
<property>
<name>JAVA_OPTS</name>
<value>-Xms1024m -Xmx1024m</value>
</property>
</appSettings>
Note
You don't need to create a web.config file when using Tomcat on Windows App Service.
Developers running a single application with one deployment slot in their App Service plan can use the following options:
- B1 and S1 instances:
-Xms1024m -Xmx1024m
- B2 and S2 instances:
-Xms3072m -Xmx3072m
- B3 and S3 instances:
-Xms6144m -Xmx6144m
- P1v2 instances:
-Xms3072m -Xmx3072m
- P2v2 instances:
-Xms6144m -Xmx6144m
- P3v2 instances:
-Xms12800m -Xmx12800m
- P1v3 instances:
-Xms6656m -Xmx6656m
- P2v3 instances:
-Xms14848m -Xmx14848m
- P3v3 instances:
-Xms30720m -Xmx30720m
- I1 instances:
-Xms3072m -Xmx3072m
- I2 instances:
-Xms6144m -Xmx6144m
- I3 instances:
-Xms12800m -Xmx12800m
- I1v2 instances:
-Xms6656m -Xmx6656m
- I2v2 instances:
-Xms14848m -Xmx14848m
- I3v2 instances:
-Xms30720m -Xmx30720m
When tuning application heap settings, review your App Service plan details and take into account multiple applications and deployment slot needs to find the optimal allocation of memory.
Turn on web sockets
Turn on support for web sockets in the Azure portal in the Application settings for the application. You need to restart the application for the setting to take effect.
Turn on web socket support using the Azure CLI with the following command:
az webapp config set --name <app-name> --resource-group <resource-group-name> --web-sockets-enabled true
Then restart your application:
az webapp stop --name <app-name> --resource-group <resource-group-name>
az webapp start --name <app-name> --resource-group <resource-group-name>
Set default character encoding
In the Azure portal, under Application Settings for the web app, create a new app setting named JAVA_OPTS
with value -Dfile.encoding=UTF-8
.
Alternatively, you can configure the app setting using the App Service Maven plugin. Add the setting name and value tags in the plugin configuration:
<appSettings>
<property>
<name>JAVA_OPTS</name>
<value>-Dfile.encoding=UTF-8</value>
</property>
</appSettings>
Pre-Compile JSP files
To improve performance of Tomcat applications, you can compile your JSP files before deploying to App Service. You can use the Maven plugin provided by Apache Sling, or using this Ant build file.
Secure applications
Java applications running in App Service have the same set of security best practices as other applications.
Authenticate users (Easy Auth)
Set up app authentication in the Azure portal with the Authentication and Authorization option. From there, you can enable authentication using Microsoft Entra ID or social sign-ins like Facebook, Google, or GitHub. Azure portal configuration only works when configuring a single authentication provider. For more information, see Configure your App Service app to use Microsoft Entra sign-in and the related articles for other identity providers. If you need to enable multiple sign-in providers, follow the instructions in Customize sign-ins and sign-outs.
Java SE
Spring Boot developers can use the Microsoft Entra Spring Boot starter to secure applications using familiar Spring Security annotations and APIs. Be sure to increase the maximum header size in your application.properties file. We suggest a value of 16384
.
Tomcat
Your Tomcat application can access the user's claims directly from the servlet by casting the Principal object to a Map object. The Map
object maps each claim type to a collection of the claims for that type. In the following code example, request
is an instance of HttpServletRequest
.
Map<String, Collection<String>> map = (Map<String, Collection<String>>) request.getUserPrincipal();
Now you can inspect the Map
object for any specific claim. For example, the following code snippet iterates through all the claim types and prints the contents of each collection.
for (Object key : map.keySet()) {
Object value = map.get(key);
if (value != null && value instanceof Collection {
Collection claims = (Collection) value;
for (Object claim : claims) {
System.out.println(claims);
}
}
}
To sign out users, use the /.auth/ext/logout
path. To perform other actions, see the documentation on Customize sign-ins and sign-outs. There's also official documentation on the Tomcat HttpServletRequest interface and its methods. The following servlet methods are also hydrated based on your App Service configuration:
public boolean isSecure()
public String getRemoteAddr()
public String getRemoteHost()
public String getScheme()
public int getServerPort()
To disable this feature, create an Application Setting named WEBSITE_AUTH_SKIP_PRINCIPAL
with a value of 1
. To disable all servlet filters added by App Service, create a setting named WEBSITE_SKIP_FILTERS
with a value of 1
.
Configure TLS/SSL
To upload an existing TLS/SSL certificate and bind it to your application's domain name, follow the instructions in Secure a custom DNS name with an TLS/SSL binding in Azure App Service. You can also configure the app to enforce TLS/SSL.
Use KeyVault References
Azure KeyVault provides centralized secret management with access policies and audit history. You can store secrets (such as passwords or connection strings) in KeyVault and access these secrets in your application through environment variables.
First, follow the instructions for granting your app access to a key vault and making a KeyVault reference to your secret in an Application Setting. You can validate that the reference resolves to the secret by printing the environment variable while remotely accessing the App Service terminal.
To inject these secrets in your Spring or Tomcat configuration file, use environment variable injection syntax (${MY_ENV_VAR}
). For Spring configuration files, see this documentation on externalized configurations.
Use the Java Key Store
By default, any public or private certificates uploaded to App Service Linux are loaded into the respective Java Key Stores as the container starts. After uploading your certificate, you'll need to restart your App Service for it to be loaded into the Java Key Store. Public certificates are loaded into the Key Store at $JRE_HOME/lib/security/cacerts
, and private certificates are stored in $JRE_HOME/lib/security/client.jks
.
More configuration might be necessary for encrypting your JDBC connection with certificates in the Java Key Store. Refer to the documentation for your chosen JDBC driver.
Initialize the Java Key Store
To initialize the import java.security.KeyStore
object, load the keystore file with the password. The default password for both key stores is changeit
.
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(
new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/cacerts"),
"changeit".toCharArray());
KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(
new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/client.jks"),
"changeit".toCharArray());
Manually load the key store
You can load certificates manually to the key store. Create an app setting, SKIP_JAVA_KEYSTORE_LOAD
, with a value of 1
to disable App Service from loading the certificates into the key store automatically. All public certificates uploaded to App Service via the Azure portal are stored under /var/ssl/certs/
. Private certificates are stored under /var/ssl/private/
.
You can interact or debug the Java Key Tool by opening an SSH connection to your App Service and running the command keytool
. See the Key Tool documentation for a list of commands. For more information on the KeyStore API, see the official documentation.
Configure APM platforms
This section shows how to connect Java applications deployed on Azure App Service with Azure Monitor Application Insights, NewRelic, and AppDynamics application performance monitoring (APM) platforms.
Configure Application Insights
Azure Monitor Application Insights is a cloud native application monitoring service that enables customers to observe failures, bottlenecks, and usage patterns to improve application performance and reduce mean time to resolution (MTTR). With a few clicks or CLI commands, you can enable monitoring for your Node.js or Java apps, autocollecting logs, metrics, and distributed traces, eliminating the need for including an SDK in your app. For more information about the available app settings for configuring the agent, see the Application Insights documentation.
Azure portal
To enable Application Insights from the Azure portal, go to Application Insights on the left-side menu and select Turn on Application Insights. By default, a new application insights resource of the same name as your web app is used. You can choose to use an existing application insights resource, or change the name. Select Apply at the bottom.
Azure CLI
To enable via the Azure CLI, you need to create an Application Insights resource and set a couple app settings on the Azure portal to connect Application Insights to your web app.
Enable the Applications Insights extension
az extension add -n application-insights
Create an Application Insights resource using the following CLI command. Replace the placeholders with your desired resource name and group.
az monitor app-insights component create --app <resource-name> -g <resource-group> --location westus2 --kind web --application-type web
Note the values for
connectionString
andinstrumentationKey
, you'll need these values in the next step.To retrieve a list of other locations, run
az account list-locations
.
Set the instrumentation key, connection string, and monitoring agent version as app settings on the web app. Replace
<instrumentationKey>
and<connectionString>
with the values from the previous step.az webapp config appsettings set -n <webapp-name> -g <resource-group> --settings "APPINSIGHTS_INSTRUMENTATIONKEY=<instrumentationKey>" "APPLICATIONINSIGHTS_CONNECTION_STRING=<connectionString>" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default" "XDT_MicrosoftApplicationInsights_Java=1"
Set the instrumentation key, connection string, and monitoring agent version as app settings on the web app. Replace
<instrumentationKey>
and<connectionString>
with the values from the previous step.az webapp config appsettings set -n <webapp-name> -g <resource-group> --settings "APPINSIGHTS_INSTRUMENTATIONKEY=<instrumentationKey>" "APPLICATIONINSIGHTS_CONNECTION_STRING=<connectionString>" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default"
Configure New Relic
Create a NewRelic account at NewRelic.com
Download the Java agent from NewRelic. It has a file name similar to newrelic-java-x.x.x.zip.
Copy your license key, you need it to configure the agent later.
SSH into your App Service instance and create a new directory /home/site/wwwroot/apm.
Upload the unpacked NewRelic Java agent files into a directory under /home/site/wwwroot/apm. The files for your agent should be in /home/site/wwwroot/apm/newrelic.
Modify the YAML file at /home/site/wwwroot/apm/newrelic/newrelic.yml and replace the placeholder license value with your own license key.
In the Azure portal, browse to your application in App Service and create a new Application Setting.
- For Java SE apps, create an environment variable named
JAVA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar
. - For Tomcat, create an environment variable named
CATALINA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar
.
- For Java SE apps, create an environment variable named
Create a NewRelic account at NewRelic.com
Download the Java agent from NewRelic. It has a file name similar to newrelic-java-x.x.x.zip.
Copy your license key, you'll need it to configure the agent later.
SSH into your App Service instance and create a new directory /home/site/wwwroot/apm.
Upload the unpacked NewRelic Java agent files into a directory under /home/site/wwwroot/apm. The files for your agent should be in /home/site/wwwroot/apm/newrelic.
Modify the YAML file at /home/site/wwwroot/apm/newrelic/newrelic.yml and replace the placeholder license value with your own license key.
In the Azure portal, browse to your application in App Service and create a new Application Setting.
- For Java SE apps, create an environment variable named
JAVA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar
. - For Tomcat, create an environment variable named
CATALINA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jar
.
- For Java SE apps, create an environment variable named
If you already have an environment variable for
JAVA_OPTS
orCATALINA_OPTS
, append the-javaagent:/...
option to the end of the current value.
Configure AppDynamics
Create an AppDynamics account at AppDynamics.com
Download the Java agent from the AppDynamics website. The file name is similar to AppServerAgent-x.x.x.xxxxx.zip
Use the Kudu console to create a new directory /home/site/wwwroot/apm.
Upload the Java agent files into a directory under /home/site/wwwroot/apm. The files for your agent should be in /home/site/wwwroot/apm/appdynamics.
In the Azure portal, browse to your application in App Service and create a new Application Setting.
- For Java SE apps, create an environment variable named
JAVA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>
where<app-name>
is your App Service name. - For Tomcat apps, create an environment variable named
CATALINA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>
where<app-name>
is your App Service name.
- For Java SE apps, create an environment variable named
Create an AppDynamics account at AppDynamics.com
Download the Java agent from the AppDynamics website. The file name is similar to AppServerAgent-x.x.x.xxxxx.zip
SSH into your App Service instance and create a new directory /home/site/wwwroot/apm.
Upload the Java agent files into a directory under /home/site/wwwroot/apm. The files for your agent should be in /home/site/wwwroot/apm/appdynamics.
In the Azure portal, browse to your application in App Service and create a new Application Setting.
- For Java SE apps, create an environment variable named
JAVA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>
where<app-name>
is your App Service name. - For Tomcat apps, create an environment variable named
CATALINA_OPTS
with the value-javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>
where<app-name>
is your App Service name.
- For Java SE apps, create an environment variable named
Note
If you already have an environment variable for JAVA_OPTS
or CATALINA_OPTS
, append the -javaagent:/...
option to the end of the current value.
Configure data sources
Java SE
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.
app.datasource.url=${CUSTOMCONNSTR_exampledb}
For more information, see the Spring Boot documentation on data access and externalized configurations.
Tomcat
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
Tomcat installations on App Service on Windows exist in shared space on the App Service Plan. You can't directly modify a Tomcat installation for server-wide configuration. To make server-level configuration changes to your Tomcat installation, you must copy Tomcat to a local folder, in which you can modify Tomcat's configuration.
Automate creating custom Tomcat on app start
You can use a startup script to perform actions before a web app starts. The startup script for customizing Tomcat needs to complete the following steps:
- Check whether Tomcat was already copied and configured locally. If it was, the startup script can end here.
- Copy Tomcat locally.
- Make the required configuration changes.
- Indicate that configuration was successfully completed.
For Windows apps, create a file named startup.cmd
or startup.ps1
in the wwwroot
directory. This file runs automatically before the Tomcat server starts.
Here's a PowerShell script that completes these steps:
# 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
}
# 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\*" -Destination "$Env:LOCAL_EXPANDED\tomcat" -Recurse
# Perform the required customization of Tomcat
{... customization ...}
# Mark that the operation was a success
New-Item -Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker" -ItemType File
Transforms
A common use case for customizing a Tomcat version 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, we recommend that you use an XSL transformation (XSLT). Use an XSL transform to make changes to the XML files while preserving the original contents of the file.
Example XSLT file
This example transform adds a new connector node to server.xml
. Note the Identity Transform, which preserves the original contents of the 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>
Function for XSL transform
PowerShell has built-in tools for transforming XML files by using XSL transforms. The following script is an example function that you can use in startup.ps1
to perform the transform:
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
Write-Host 'Error'$ErrorMessage':'$FailedItem':' $_.Exception;
return 0
}
return 1
}
App settings
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:
Example startup.ps1
The following example script copies a custom Tomcat to a local folder, performs an XSL transform, and indicates that the transform was successful:
# 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
}
$success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml
# 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
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
}
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 Cloud Shell, 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
Tomcat
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
Adding a shared, server-level data source requires you to edit Tomcat's server.xml. First, upload a startup script and set the path to the script in Configuration > Startup Command. You can upload the startup script using FTP.
Your startup script will make an xsl transform to the server.xml file and output the resulting xml file to /usr/local/tomcat/conf/server.xml
. The startup script should install libxslt via apk. Your xsl file and startup script can be uploaded via FTP. Below is an example startup script.
# Install libxslt. Also copy the transform file to /home/tomcat/conf/
apk add --update libxslt
# Usage: xsltproc --output output.xml style.xsl input.xml
xsltproc --output /home/tomcat/conf/server.xml /home/tomcat/conf/transform.xsl /usr/local/tomcat/conf/server.xml
The following example XSL file adds a new connector node to the Tomcat server.xml.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<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>
Finalize configuration
Finally, 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 Cloud Shell, 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 --path <jar-name>.jar
If you created a server-level data source, restart the App Service Linux application. Tomcat will reset CATALINA_BASE
to /home/tomcat
and use the updated configuration.
JBoss EAP Data Sources
There are three core steps when registering a data source with JBoss EAP: uploading the JDBC driver, adding the JDBC driver as a module, and registering the module. App Service is a stateless hosting service, so the configuration commands for adding and registering the data source module must be scripted and applied as the container starts.
Obtain your database's JDBC driver.
Create an XML module definition file for the JDBC driver. The following example shows a module definition for PostgreSQL.
<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.1" name="org.postgres"> <resources> <!-- ***** IMPORTANT : REPLACE THIS PLACEHOLDER *******--> <resource-root path="/home/site/deployments/tools/postgresql-42.2.12.jar" /> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>
Put your JBoss CLI commands into a file named
jboss-cli-commands.cli
. The JBoss commands must add the module and register it as a data source. The following example shows the JBoss CLI commands for PostgreSQL.#!/usr/bin/env bash module add --name=org.postgres --resources=/home/site/deployments/tools/postgresql-42.2.12.jar --module-xml=/home/site/deployments/tools/postgres-module.xml /subsystem=datasources/jdbc-driver=postgres:add(driver-name="postgres",driver-module-name="org.postgres",driver-class-name=org.postgresql.Driver,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource) data-source add --name=postgresDS --driver-name=postgres --jndi-name=java:jboss/datasources/postgresDS --connection-url=${POSTGRES_CONNECTION_URL,env.POSTGRES_CONNECTION_URL:jdbc:postgresql://db:5432/postgres} --user-name=${POSTGRES_SERVER_ADMIN_FULL_NAME,env.POSTGRES_SERVER_ADMIN_FULL_NAME:postgres} --password=${POSTGRES_SERVER_ADMIN_PASSWORD,env.POSTGRES_SERVER_ADMIN_PASSWORD:example} --use-ccm=true --max-pool-size=5 --blocking-timeout-wait-millis=5000 --enabled=true --driver-class=org.postgresql.Driver --exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter --jta=true --use-java-context=true --valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker
Create a startup script,
startup_script.sh
that calls the JBoss CLI commands. The following example shows how to call yourjboss-cli-commands.cli
. Later, you'll configure App Service to run this script when the container starts.$JBOSS_HOME/bin/jboss-cli.sh --connect --file=/home/site/deployments/tools/jboss-cli-commands.cli
Using an FTP client of your choice, upload your JDBC driver,
jboss-cli-commands.cli
,startup_script.sh
, and the module definition to/site/deployments/tools/
.Configure your site to run
startup_script.sh
when the container starts. In the Azure portal, navigate to Configuration > General Settings > Startup Command. Set the startup command field to/home/site/deployments/tools/startup_script.sh
. Save your changes.
To confirm that the datasource was added to the JBoss server, SSH into your webapp and run $JBOSS_HOME/bin/jboss-cli.sh --connect
. Once you're connected to JBoss, run the /subsystem=datasources:read-resource
to print a list of the data sources.
robots933456 in logs
You may see the following message in the container logs:
2019-04-08T14:07:56.641002476Z "-" - - [08/Apr/2019:14:07:56 +0000] "GET /robots933456.txt HTTP/1.1" 404 415 "-" "-"
You can safely ignore this message. /robots933456.txt
is a dummy URL path that App Service uses to check if the container is capable of serving requests. A 404 response simply indicates that the path doesn't exist, but it lets App Service know that the container is healthy and ready to respond to requests.
Choosing a Java runtime version
App Service allows users to choose the major version of the JVM, such as Java 8 or Java 11, and the patch version, such as 1.8.0_232 or 11.0.5. You can also choose to have the patch version automatically updated as new minor versions become available. In most cases, production apps should use pinned patch JVM versions. This prevents unanticipated outages during a patch version autoupdate. All Java web apps use 64-bit JVMs, and it's not configurable.
If you're using Tomcat, you can choose to pin the patch version of Tomcat. On Windows, you can pin the patch versions of the JVM and Tomcat independently. On Linux, you can pin the patch version of Tomcat; the patch version of the JVM is also pinned but isn't separately configurable.
If you choose to pin the minor version, you need to periodically update the JVM minor version on the app. To ensure that your application runs on the newer minor version, create a staging slot and increment the minor version on the staging slot. Once you confirm the application runs correctly on the new minor version, you can swap the staging and production slots.
JBoss EAP
Clustering in JBoss EAP
App Service supports clustering for JBoss EAP versions 7.4.1 and greater. To enable clustering, your web app must be integrated with a virtual network. When the web app is integrated with a virtual network, it restarts, and the JBoss EAP installation automatically starts up with a clustered configuration. The JBoss EAP instances communicate over the subnet specified in the virtual network integration, using the ports shown in the WEBSITES_PRIVATE_PORTS
environment variable at runtime. You can disable clustering by creating an app setting named WEBSITE_DISABLE_CLUSTERING
with any value.
Note
If you're enabling your virtual network integration with an ARM template, you need to manually set the property vnetPrivatePorts
to a value of 2
. If you enable virtual network integration from the CLI or Portal, this property is set for you automatically.
When clustering is enabled, the JBoss EAP instances use the FILE_PING JGroups discovery protocol to discover new instances and persist the cluster information like the cluster members, their identifiers, and their IP addresses. On App Service, these files are under /home/clusterinfo/
. The first EAP instance to start obtains read/write permissions on the cluster membership file. Other instances read the file, find the primary node, and coordinate with that node to be included in the cluster and added to the file.
Note
You can avoid JBOSS clustering timeouts by cleaning up obsolete discovery files during your app startup
The Premium V3 and Isolated V2 App Service Plan types can optionally be distributed across Availability Zones to improve resiliency and reliability for your business-critical workloads. This architecture is also known as zone redundancy. The JBoss EAP clustering feature is compatible with the zone redundancy feature.
Autoscale Rules
When configuring autoscale rules for horizontal scaling, it's important to remove instances incrementally (one at a time) to ensure each removed instance can transfer its activity (such as handling a database transaction) to another member of the cluster. When configuring your autoscale rules in the Portal to scale down, use the following options:
- Operation: "Decrease count by"
- Cool down: "5 minutes" or greater
- Instance count: 1
You don't need to incrementally add instances (scaling out), you can add multiple instances to the cluster at a time.
JBoss EAP App Service Plans
JBoss EAP is only available on the Premium v3 and Isolated v2 App Service Plan types. Customers that created a JBoss EAP site on a different tier during the public preview should scale up to Premium or Isolated hardware tier to avoid unexpected behavior.
Tomcat Baseline Configuration On App Services
Java developers can customize the server settings, troubleshoot issues, and deploy applications to Tomcat with confidence if they know about the server.xml file and configuration details of Tomcat. Possible customizations include:
- Customizing Tomcat configuration: By understanding the server.xml file and Tomcat's configuration details, you can fine-tune the server settings to match the needs of their applications.
- Debugging: When an application is deployed on a Tomcat server, developers need to know the server configuration to debug any issues that might arise. This includes checking the server logs, examining the configuration files, and identifying any errors that might be occurring.
- Troubleshooting Tomcat issues: Inevitably, Java developers encounter issues with their Tomcat server, such as performance problems or configuration errors. By understanding the server.xml file and Tomcat's configuration details, developers can quickly diagnose and troubleshoot these issues, which can save time and effort.
- Deploying applications to Tomcat: To deploy a Java web application to Tomcat, developers need to know how to configure the server.xml file and other Tomcat settings. Understanding these details is essential for deploying applications successfully and ensuring that they run smoothly on the server.
When you create an app with built-in Tomcat to host your Java workload (a WAR file or a JAR file), there are certain settings that you get out of the box for Tomcat configuration. You can refer to the Official Apache Tomcat Documentation for detailed information, including the default configuration for Tomcat Web Server.
Additionally, there are certain transformations that are further applied on top of the server.xml for Tomcat distribution upon start. These are transformations to the Connector, Host, and Valve settings.
Note that the latest versions of Tomcat have server.xml (8.5.58 and 9.0.38 onward). Older versions of Tomcat don't use transforms and might have different behavior as a result.
Connector
<Connector port="${port.http}" address="127.0.0.1" maxHttpHeaderSize="16384" compression="on" URIEncoding="UTF-8" connectionTimeout="${site.connectionTimeout}" maxThreads="${catalina.maxThreads}" maxConnections="${catalina.maxConnections}" protocol="HTTP/1.1" redirectPort="8443"/>
maxHttpHeaderSize
is set to16384
URIEncoding
is set toUTF-8
conectionTimeout
is set toWEBSITE_TOMCAT_CONNECTION_TIMEOUT
, which defaults to240000
maxThreads
is set toWEBSITE_CATALINA_MAXTHREADS
, which defaults to200
maxConnections
is set toWEBSITE_CATALINA_MAXCONNECTIONS
, which defaults to10000
Note
The connectionTimeout, maxThreads and maxConnections settings can be tuned with app settings
Following are example CLI commands that you might use to alter the values of conectionTimeout, maxThreads, or maxConnections:
az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_TOMCAT_CONNECTION_TIMEOUT=120000
az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_CATALINA_MAXTHREADS=100
az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_CATALINA_MAXCONNECTIONS=5000
- Connector uses the address of the container instead of 127.0.0.1
Host
<Host appBase="${site.appbase}" xmlBase="${site.xmlbase}" unpackWARs="${site.unpackwars}" workDir="${site.tempdir}" errorReportValveClass="com.microsoft.azure.appservice.AppServiceErrorReportValve" name="localhost" autoDeploy="true">
appBase
is set toAZURE_SITE_APP_BASE
, which defaults to localWebappsLocalPath
xmlBase
is set toAZURE_SITE_HOME
, which defaults to/site/wwwroot
unpackWARs
is set toAZURE_UNPACK_WARS
, which defaults totrue
workDir
is set toJAVA_TMP_DIR
, which defaultsTMP
errorReportValveClass
uses our custom error report valve
Valve
<Valve prefix="site_access_log.${catalina.instance.name}" pattern="%h %l %u %t "%r" %s %b %D %{x-arr-log-id}i" directory="${site.logdir}/http/RawLogs" maxDays="${site.logRetentionDays}" className="org.apache.catalina.valves.AccessLogValve" suffix=".txt"/>
directory
is set toAZURE_LOGGING_DIR
, which defaults tohome\logFiles
maxDays
is toWEBSITE_HTTPLOGGING_RETENTION_DAYS
, which defaults to0
[forever]
On Linux, it has all of the same customization, plus:
- Adds some error and reporting pages to the valve:
<xsl:attribute name="appServiceErrorPage">
<xsl:value-of select="'${appService.valves.appServiceErrorPage}'"/>
</xsl:attribute>
<xsl:attribute name="showReport">
<xsl:value-of select="'${catalina.valves.showReport}'"/>
</xsl:attribute>
<xsl:attribute name="showServerInfo">
<xsl:value-of select="'${catalina.valves.showServerInfo}'"/>
</xsl:attribute>
Next steps
Visit the Azure for Java Developers center to find Azure quickstarts, tutorials, and Java reference documentation.
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for