The Azure Code Samples are currently available in English

Scaling Stateful Java Apps on Azure

This guide walks you through the process of scaling stateful Java apps on Azure, aka:

  • Migrate or deploy stateful Java apps to App Service Linux
  • Externalize HTTP sessions to Azure Redis Cache

Table of Contents

What you will migrate to cloud

You will migrate stateful Java apps to Azure, scale it across geographies and demo failover across data centers. These apps use:

  • Java Servlet (JSR 369)
  • Java EE 7

Upon migration, you will power the apps using App Service Linux and Azure Redis Cache.

Migrated Java apps can be hosted anywhere – virtual machines, containers - AKS or managed Tomcat in App Service Linux. We chose the managed option. The underlying technique for migration is the SAME regardless of a choice of where migrated apps are hosted.

What you will need

In order to deploy a Java Web app to cloud, you need an Azure subscription. If you do not already have an Azure subscription, you can activate your MSDN subscriber benefits or sign up for a free Azure account).

In addition, you will need the following:

| Azure CLI | Java 8 | Maven 3 | Git

Getting Started

You can start from scratch and complete each step, or you can bypass basic setup steps that you are already familiar with. Either way, you will end up with working code.

Step ONE - Clone and Prep

git clone --recurse-submodules https://github.com/Azure-Samples/scaling-stateful-java-web-app-on-azure
cd scaling-stateful-java-web-app-on-azure
yes | cp -rf .prep/* .

Build Scalable Layout for Stateful Java Apps on Azure

Build the Stateful Java Web App:


# change to initial directory
cd initial/stateful-java-web-app

# build WAR package
mvn package

[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------------------------------------------------[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ Stateful-Tracker [INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/selvasingh/scaling-stateful-java-web-app-on-azure/initial/stateful-java-web-app/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ Stateful-Tracker [INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ Stateful-Tracker [INFO] Packaging webapp
[INFO] Assembling webapp [Stateful-Tracker] in [/Users/selvasingh/scaling-stateful-java-web-app-on-azure/initial/stateful-java-web-app/target/Stateful-Tracker-1.0.0-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/selvasingh/scaling-stateful-java-web-app-on-azure/initial/stateful-java-web-app/src/main/webapp]
[INFO] Webapp assembled in [67 msecs]
[INFO] Building war: /Users/selvasingh/scaling-stateful-java-web-app-on-azure/initial/stateful-java-web-app/target/Stateful-Tracker-1.0.0-SNAPSHOT.war
[INFO] ---------------------------------------------------------------------[INFO] Total time: 2.963 s
[INFO] Finished at: 2019-02-18T21:44:22-08:00
[INFO] Final Memory: 20M/308M
[INFO] ---------------------------------------------------------------------[INFO] Building Stateful-Tracker 1.0.0-SNAPSHOT
[INFO] ---------------------------------------------------------------------[INFO] Authenticate with Azure CLI 2.0
[INFO] Target Web App doesn't exist. Creating a new one...
[INFO] Creating App Service Plan 'stateful-java-web-app-appservice-plan-westus'...
[INFO] Successfully created App Service Plan.
[INFO] Successfully created Web App.
[INFO] Trying to deploy artifact to stateful-java-web-app-westus...
[INFO] Deploying the war file...
[INFO] Successfully deployed the artifact to https://stateful-java-web-app-westus.azurewebsites.net
[INFO] ---------------------------------------------------------------------[INFO] Total time: 01:09 min
[INFO] Finished at: 2019-02-18T22:03:14-08:00
[INFO] Final Memory: 54M/546M
[INFO] ---------------------------------------------------------------------[INFO] Building Stateful-Tracker 1.0.0-SNAPSHOT
[INFO] ---------------------------------------------------------------------[INFO] Authenticate with Azure CLI 2.0
[INFO] Target Web App doesn't exist. Creating a new one...
[INFO] Creating App Service Plan 'stateful-java-web-app-appservice-plan-eastus'...
[INFO] Successfully created App Service Plan.
[INFO] Successfully created Web App.
[INFO] Trying to deploy artifact to stateful-java-web-app-eastus...
[INFO] Deploying the war file...
[INFO] Successfully deployed the artifact to https://stateful-java-web-app-eastus.azurewebsites.net
[INFO] ---------------------------------------------------------------------[INFO] Total time: 03:51 min
[INFO] Finished at: 2019-02-18T22:09:11-08:00
[INFO] Final Memory: 55M/648M
[INFO] ---------------------------------------------------------------------[INFO] Building Stateful-Tracker 1.0.0-SNAPSHOT
[INFO] ---------------------------------------------------------------------[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ Stateful-Tracker [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/selvasingh/scaling-stateful-java-web-app-on-azure/initial/stateful-java-web-app/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ Stateful-Tracker [INFO] No tests to run.
[INFO] 
[INFO] --- maven-war-plugin:3.2.2:war (default-war) @ Stateful-Tracker [INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------------```

Update the `pom.xml` to upload app settings, particularly secrets
to connect with Azure Redis Cache:

```xml
<plugin>
    <groupId>com.microsoft.azure</groupId>
             <artifactId>azure-webapp-maven-plugin</artifactId>
             <version>1.5.3</version>
             <configuration>

                 <!-- Web App information -->
                 <resourceGroup>${RESOURCEGROUP_NAME}</resourceGroup>
                 <appServicePlanName>${WEBAPP_PLAN_NAME}-${REGION}</appServicePlanName>
                 <appName>${WEBAPP_NAME}-${REGION}</appName>
                 <region>${REGION}</region>
                 <linuxRuntime>tomcat 9.0-jre8</linuxRuntime>

                 <appSettings>
                     <property>
                         <name>REDIS_CACHE_NAME</name>
                         <value>${REDIS_CACHE_NAME}</value>
                     </property>
                     <property>
                         <name>REDIS_PORT</name>
                         <value>${REDIS_PORT}</value>
                     </property>
                     <property>
                         <name>REDIS_PASSWORD</name>
                         <value>${REDIS_PASSWORD}</value>
                     </property>
                     <property>
                         <name>REDIS_SESSION_KEY_PREFIX</name>
                         <value>${REDIS_SESSION_KEY_PREFIX}</value>
                     </property>
                     <property>
                         <name>JAVA_OPTS</name>
                         <value>-Xms2048m -Xmx2048m -DREDIS_CACHE_NAME=${REDIS_CACHE_NAME} -DREDIS_PORT=${REDIS_PORT} -DREDIS_PASSWORD=${REDIS_PASSWORD} -DREDIS_SESSION_KEY_PREFIX=${REDIS_SESSION_KEY_PREFIX}</value>
                     </property>

                 </appSettings>

             </configuration>
         </plugin>

Re-deploy the stateful Java Web app to the first data center:

mvn azure-webapp:deploy -DREGION=${REGION_1}

[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------------------------------------------------[INFO] 
[INFO] --- azure-webapp-maven-plugin:1.5.3:deploy (default-cli) @ Stateful-Tracker [INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------------# stop and start the first app
az webapp stop -g ${RESOURCEGROUP_NAME} -n ${WEBAPP_NAME}-${REGION_1}
az webapp start -g ${RESOURCEGROUP_NAME} -n ${WEBAPP_NAME}-${REGION_1}

Re-deploy the Stateful Java Web App to Second Data Center

Similarly, redeploy the stateful Java Web app to second data center:

mvn azure-webapp:deploy -DREGION=${REGION_2}

[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------------------------------------------------------[INFO] 
[INFO] --- azure-webapp-maven-plugin:1.5.3:deploy (default-cli) @ Stateful-Tracker [INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------------# stop and start the first app
az webapp stop -g ${RESOURCEGROUP_NAME} -n ${WEBAPP_NAME}-${REGION_2}
az webapp start -g ${RESOURCEGROUP_NAME} -n ${WEBAPP_NAME}-${REGION_2}

Open Scaled Stateful Java Web Apps on Azure

Open the Traffic Manager profile endpoint:

open http://stateful-java-web-app.trafficmanager.net

Let us stop one of the stateful Java Web app and check how failover happens:

az webapp stop -g ${RESOURCEGROUP_NAME} -n ${WEBAPP_NAME}-${REGION_1}

Traffic Manager Profile should look like this:

Refresh the browser:

Failover SUCCEEDED because the session tracking begins, particularly, once the connection breaks, the client is round robined to another server in East US data center, then the correlation is continued, tracks to Number of Visits = 2, using externalized sessions.

When you are finished, you can check your results against YOUR code in scaling-stateful-java-web-app-on-azure/complete.

Congratulations!

Congratulations!! You migrated existing Java enterprise workloads to Azure, aka stateful Java app to App Service Linux and app's externalized session store to Azure Redis Cache.

Resources

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.