Category Archives: PowerShell

Azure: Deploying WAR File to Tomcat

PROBLEM

Typically, when using ZipDeploy to push a WAR file (ex: my-app.war) to an Azure instance, we need to:-

  • Rename my-app.war to ROOT.war.
  • Place ROOT.war under webapps/.
  • Zip up webapps/.
  • Use ZipDeploy to push the zip file to an Azure instance.

This zip file will automatically be unzipped under site/wwwroot:-

D:\home\site\wwwroot
└── webapps
    └── ROOT.war

Tomcat detects ROOT.war and will try to unpack the WAR file under ROOT/:-

D:\home\site\wwwroot
└── webapps
    ├── ROOT
    │   ├── META-INF
    │   │   └── ...
    │   └── WEB-INF
    │       └── ...
    └── ROOT.war

The problem is sometimes Tomcat is unable to fully unpack ROOT.war because some files may be locked by some running processes. As a result, the web page fails to load and shows 404 error.

SOLUTION

A better and more stable solution is to use WarDeploy to push WAR file to an Azure instance because:-

  • It simplifies the deployment process because we don’t need to create a zip file with webapps/ containing a WAR file named ROOT.war.
  • Instead of relying on Tomcat to unpack the WAR file, WarDeploy will do the unpacking step elsewhere before copying to site/wwwroot/webapps/.

To use WarDeploy, you can use curl command or PowerShell script to do so.

Here’s an example of the PowerShell script:-

Param(
    [string]$filePath,
    [string]$apiUrl,
    [string]$username,
    [string]$password
)

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))

Invoke-RestMethod -Uri $apiUrl -Headers @{ Authorization = ("Basic {0}" -f $base64AuthInfo) } -Method POST -InFile $filePath -ContentType "multipart/form-data"

If the PowerShell script above is called deploy.ps1, to push my-app.war to my-app Azure instance:-

deploy.ps1 -filePath D:\my-app.war -apiUrl https://my-app.scm.azurewebsites.net/api/wardeploy -username [USER] -password [PASSWORD]

Depending on the size of the WAR file, you may get “The operation has timed out” error after 100 seconds:-

Invoke-RestMethod : The operation has timed out
At D:\agent\_work\2ea6e947a\my-app\deploy.ps1:18 char:1
+ Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization=("Basic {0}"  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

This will most likely to occur if the WAR file is too big (80MB+).

To fix this, increase the time out duration by adding -TimeoutSec option to Invoke-RestMethod statement:-

Invoke-RestMethod [OTHER_OPTIONS...] -TimeoutSec 300
Advertisements