Deploying a Maven Project to an Azure Web App

My goal in this post is to build, test, and deploy a Java project using Maven into an Azure Web App running Tomcat 8 and Java 8, execute jUnit tests, and publish code coverage results.  I will be using Azure Resource Manager templates to provision the Web App during my release pipeline and JaCoCo to calculate code coverage during my build. While I was building this demo I ran into a problem. Although a WAR file is just a zip file, using it as the value for the Web Deploy Package field of the out of the box Deploy Web App Deployment task failed.

2016-03-01T00:50:29.0940661Z ##[error]Package file 'C:\a1\_w\8f0ccb3f6\JavaWeb App ARM\drop\target\PeopleTracker.JavaService.war' does not have a .zip file name extension.

Desired folder structure

That error seemed easy enough to fix. I will just change the extension to .zip and everything should be fine. Unfortunately, the structure of the WAR file did not match the directory structure expected by the Azure Web App.  With a Web App, the zip file uploaded is expanded starting from the site\wwwroot folder.

The problem with that is we are missing two folders webapps and ROOT which start the folder structure of a Azure Web App configured with Tomcat 8 and Java 8. Therefore, we have to restructure the WAR file to start at webapps\ROOT and be a .zip file instead of .war file.  That way when it expands we will end up with the desired folder structure.

I have been doing a lot of work with writing custom Node.js tasks for Visual Studio Team Services (VSTS) and thought this was a great opportunity to use that knowledge.  I will write future posts on how I created the task. For now you can simply install the tasks from the Visual Studio Team Service Marketplace as the Trackyon Advantage extension.


The current version of the task simply extracts the contents of the WAR file and re-zips it in the desired folder structure with a .zip extension. Future plans are to support Tokenization of files before it is re-zipped.

Now we can configure your build. You can use any Maven project that produces a WAR file.  You will need to add an Azure Resource Manager (ARM) template to your source repository.  You can my 201-web-app-java-tomcat ARM template from GitHub.  Simply add the azuredeploy.json file to your repository. You can add it anywhere you like. I created an ARM folder and placed it there.

With all your code in source control, we can now create our build definition.

  1. Log in to VSTS
  2. Click the Build hubimage
  3. Click the green plus 
  4. Select the Empty template
  5. Click Next
  6. Select your repository
  7. Check the box for Continuous integration
  8. Click Create

With the build created, we need to add the required tasks.


  1. Click Add build step…
  2. Select the Build category
  3. Click Add next to the Maven task
  4. Select the Utility category
  5. Click Add next to the Copy and Publish Build Artifacts task
  6. Click Close

With the tasks added, we can now configure each task.

  1. Select the Maven task
  2. Browse to the desired pom.xml file
  3. Select JaCoCo for Code Coverage Tool
  4. Select the Copy and Publish Build Artifacts task
    Field Value
    Contents **/*.war
    Artifact Name drop
    Artifact Type Server
  5. Click Save
  6. Give your build a name
  7. Click OK
  8. Click Queue build…
  9. Click OK

Verify that the build completes successfully.  Now we can create our release.

  1. Open build summaryimage
  2. Click Create release from the Deployments section
  3. Click Yes
  4. Select the Azure Website Deployment template
  5. Click OK
  6. Click Add tasks
  7. Select the Utility category
  8. Click Add next to the War Converter task
  9. Select the Deploy category
  10. Click Add next to the Azure Resource Group Deployment task
  11. Drag and drop the War Converter task to the top
  12. Drag and drop the Azure Resource Group Deployment task above the Azure Web App Deployment task
  13. Delete the Visual Studio Test task

With the tasks added, we can now configure each task. 

  1. Select the Azure Resource Group Deployment task
    Field Value
    Azure Connection Type Azure Resource Manager
    Azure RM Subscription Select your Azure RM Subscription
    If you do not have a Azure RM Subscription, you can click Manage to add one.  For step-by-step instructions on adding an Azure RM Subscription, follow this blog post: Creating an Azure Resource Manager Service Endpoint.
    Resource Group Select an existing Resource Group or type in a name of one you would like created
    Location Select location to create your Resource Group
    Template Click the browse button for the Template and select the json file added from GitHub
    Override Template Parameters -webSiteName {DesiredWebSiteName} -hostingPlanName {DesiredHostingPlanName}
  2. Select the Azure Web App Deployment task
    Field Value
    Azure Subscription Select your Azure Subscription
    If you do not have a Azure RM Subscription you can click Manage to add one.  For step-by-step instructions on adding an Azure Subscription, follow one of the following posts: Creating an Azure Service Endpoint with a certificate or Creating an Azure Service Endpoint with credentials.
    Web App Name {DesiredWebSiteName}
    Web App Location Select same value as used for Resource Group location
    Additional Arguments <blank>

Now we are going to configure our environment to deploy as soon as a release is created.

  1. Click the ellipse of the Default Environment 
  2. Select Deployment Conditions…
  3. Select the After release creation radio button
  4. Click OK
  5. Click the Triggers tab
  6. Select the Continuous Deployment radio button
  7. Select the build definition we created earlier
  8. Enter an name for your release Definition
  9. Click Save

Now we can test everything by starting a new release.

  1. Click Release
  2. Select Create Release
  3. Select the build we ran to test our build definition
  4. Click Create
  5. Click the release link
  6. Click the Logs tab

Verify that the release completes successfully.  This pipeline demonstrates how to use Infrastructure as Code to provision a Tomcat 8 Azure Web App and deploy a Java application built with Maven using VSTS.  It also shows the integration of build and release and support for Java, jUnit, JaCoCo and Tomcat. 


Comments (4) -

  • Mariusz

    12/20/2017 3:13:26 PM | Reply

    Hi Don !

    Is there a smilar converter task for the *.jar files ? Or can the Trackyon be used as well for the *.war files and *.jar ?


    • Donovan

      2/2/2018 6:24:17 PM | Reply

      It should just work. I have not tested it. If not let me know.

  • Olov

    4/3/2018 4:01:31 PM | Reply

    Installed the extension but got some errors:

    2018-04-03T15:59:07.8170466Z ##[section]Starting: WAR Converter **/*.war
    2018-04-03T15:59:07.8173343Z ==============================================================================
    2018-04-03T15:59:07.8174054Z Task         : Trackyon WAR Converter
    2018-04-03T15:59:07.8174307Z Description  : Converts a WAR file so it can be uploaded to an Azure Web App.
    2018-04-03T15:59:07.8174529Z Version      : 1.0.987
    2018-04-03T15:59:07.8174700Z Author       : Trackyon
    2018-04-03T15:59:07.8174909Z Help         : Replace with markdown to show in help
    2018-04-03T15:59:07.8175456Z ==============================================================================
    2018-04-03T15:59:08.9175067Z (node:3728) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version.
    2018-04-03T15:59:08.9847571Z ##[error]Unhandled: invalid signature: 0x622f2123
    2018-04-03T15:59:09.0813334Z ##[section]Finishing: WAR Converter **/*.war

    • Donovan

      4/10/2018 3:13:07 PM | Reply

      I would uninstall and re-install the extension. It does not appear to have installed cleanly.

Add comment