Deploying Helidon applications to Azure App Service

Akihiro Nishikawa
Microsoft Azure
Published in
6 min readJun 8, 2020

[As of June 29, 2020]

Japanese edition is here.

Similar to the following article, I will describe how to deploy Helidon applications to Azure App Service.

Deploying Helidon Applications to Google App Engine

What is Helidon?

Helidon is an open-sourced web application development framework developed by Oracle. This is similar to Quarkus and Micronaut.

At the time of writing this article, the latest version is 1.4.4 and 2.0.0.

In this article, I use the quickstart application of Helidon 2.0.0 SE/MP for demonstration. For more details on the quickstart application of each edition, please check the following URLs.

We can use hello world app created via MicroProfile Starter, of course.

Deployment key points

Key points are listed below.

  • Adding dependencies and proper settings for Azure App Service
  • Using proper JDK suitable for Helidon version

Prerequisites

The following items are required to complete building and deploying applications.

  • JDK (JDK 8 or higher for Helidon 1.x, JDK 11 or higher for Helidon 2.x)
  • Maven
  • Azure CLI (needed to call Azure CLI from Maven Plugin for Azure App Service)

Generating resources

Use Maven to generate Quickstart application resources.

# Helidon SE
mvn archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-se \
-DarchetypeVersion=2.0.0 \
-DgroupId=io.helidon.examples \
-DartifactId=helidon-quickstart-se \
-Dpackage=io.helidon.examples.quickstart.se
# Helidon MP
mvn archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-mp \
-DarchetypeVersion=2.0.0 \
-DgroupId=io.helidon.examples \
-DartifactId=helidon-quickstart-mp \
-Dpackage=io.helidon.examples.quickstart.mp

Please confirm resource files are generated in either {current directory}/helidon-quickstart-se or {current directory}/helidon-quickstart-mp directory, depending upon calling command.

Adding dependencies

Add “Maven Plugin for Azure App Service” to pom.xml.

<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-webapp-maven-plugin</artifactId>
<version>1.9.1</version>
</plugin>

This operation is similar to that for Spring Boot application.

Configure Maven Plugin for Azure App Service

Configuration for Azure App Service

Invoke the following command to add configuration for Azure App Service.

mvn azure-webapp:config

Specify the operating system and the Java version as follows. If you want to change either the region to be deployed, resource group, name of App Service or Pricing Tier, you have to finish this command and modify settings in pom.xml directly.

[WARNING] The plugin may not work if you change the os of an existing webapp.
Define value for OS(Default: Linux):
1. linux [*]
2. windows
3. docker
Enter index to use: 1
Define value for javaVersion(Default: Java 8):
1. Java 11
2. Java 8 [*]
Enter index to use: 1
Please confirm webapp properties
AppName : helidon-quickstart-se-1591346807867
ResourceGroup : helidon-quickstart-se-1591346807867-rg
Region : westeurope
PricingTier : PremiumV2_P1v2
OS : Linux
RuntimeStack : JAVA 11-java11
Deploy to slot : false
Confirm (Y/N)? : Y
[INFO] Saving configuration to pom.
...

The following output is an excerpt from pom.xml modified in executing the command.

... 
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-webapp-maven-plugin</artifactId>
<version>1.9.1</version>
<configuration>
<schemaVersion>V2</schemaVersion>
<resourceGroup>helidon-quickstart-se-1591346807867-rg</resourceGroup>
<appName>helidon-quickstart-se-1591346807867</appName>
<pricingTier>P1v2</pricingTier>
<region>westeurope</region>
<runtime>
<os>linux</os>
<javaVersion>java11</javaVersion>
<webContainer>java11</webContainer>
</runtime>
<deployment>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
</deployment>
</configuration>
</plugin>
...

Specifying deployment targets

When building an application, the following artifacts are generated and stored in each directory.

  • JAR file without dependencies: ${project.basedir}/target
  • Dependency JAR files: ${project.basedir}/target/libs

If using default pom.xml to deploy to Azure App Service, only JAR file without dependencies is deployed. In this case, either helidon-quickstart-se.jar or helidon-quickstart-mp.jar is renamed to app.jar and app.jar only is deployed to Azure. So, this application does not work properly due to lack of dependencies.

To avoid this, we have two options listed below.

  1. Specify any Jar files in not only ${project.basedir}/target but also any subdirectories of ${project.basedir}/target as the deployment target.
<deployment>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>
</deployment>

2. Explicitly add /libs/*.jar as the additional deployment target.

<deployment>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<includes>
<include>*.jar</include>
<include>/libs/*.jar</include>
</includes>
</resource>
</resources>
</deployment>

Indeed we can use “maven assembly plugin” to generate an executable jar file that contains all dependencies. However, Helidon MP application does not always have a main method in the application, so it is sometimes hard to generate an executable jar with the plugin. Therefore, I recommend you copy all dependencies to Azure App Service.

Technically, the main class is not needed unless you want to control the startup sequence. You can set the mainClass to io.helidon.microprofile.Main and it will find the application annotated with ApplicationScoped. Though it is likely that almost any "real" application would want its own main class.

Start implementing the MicroProfile application - Helidon MP Tutorial
https://helidon.io/docs/v2/#/mp/guides/10_mp-tutorial

Server listening port

The following passage in the document says App service waits for incoming requests to 80/tcp.

App Service Linux routes incoming requests to port 80, so your application should listen on port 80 as well. You can do this in your application’s configuration (such as Spring’s application.properties file), or in your Startup Command (for example, java -jar spring-app.jar --server.port=80). Please see the following documentation for common Java frameworks:

Server Port
https://docs.microsoft.com/azure/app-service/containers/configure-language-java#server-port

As default listening port of both SE and MP is not 80/tcp but 8080/tcp, we have two options listed below (If deploying Helidon based applications as Docker containers, we can use port binding to meet this requirement).

  1. Bind ports in order to use default port of Helidon quickstart application.
  2. Modify the listening port in order to meet Azure App Service requirements.

Port binding

Add property in appSettings section (in pom.xml) to specify bound ports as follows.

<configuration>
...
<appSettings>
<property>
<name>PORT</name>
<value>8080</value>
</property>
<property>
<name>WEBSITES_PORT</name>
<value>8080</value>
</property>
</appSettings>
...
</configuration>

Modifying port (Helidon SE)

Modify the value of server.port in resources/application.yaml. (Default value is 8080).

app:
greeting: "Hello"
server:
port: 80
host: 0.0.0.0

Modifying port (Helidon MP)

Modify the value of server.port in META-INF/microprofile-config.properties. (Default value is 8080).

# Application properties. This is the default greeting
app.greeting=Hello
# Microprofile server properties
server.port=80
server.host=0.0.0.0

Build and deploy

We have to recognize privilege port related error might happen when the listening port is set to not 8080/tcp but 80/tcp. If needed, skip the test phase.

mvn package

When deploying the application to Azure App Service, use the following command (mvn azure-webapp:deploy).

mvn azure-webapp:deploy

As this deployment operation requires authentication against Azure, we have to complete authentication and authorization against Azure via Azure CLI in advance.

# Authentication and authorization with Azure CLI
az login
# In case of multiple subscriptions, you should specify subscription ID.
az account set -s "subscription ID or subscription name"
# Deploy!
mvn azure-webapp:deploy

Disabling FTP

Unless permitting deploying artifacts via FTP or FTPS, you should disable FTP/FTPS for security reasons.

Azure Portal : Settings > Configuration > General settings

Please make sure you save modified configuration.

(Optional) Confirming deployments via SSH

*** This operation is only for checking deployments purpose. ***

We can access inside of App Service container via SSH to check Jar files deployed to Azure. Open Azure Portal and select SSH in Development Tools.

Change the current directory to /home/site/wwwroot (deployment target directory), and we can see the following points.

  • app.jar, which is renamed from either helidon-quickstart-se.jar or helidon-quickstart-mp.jar, exists in /home/site/wwwroot.
  • Dependency Jar files exist in /home/site/www/root/libs.

Test

When calling GET /greet/{name} (http://<Azure App Service URL>/greet/Taro1), the following response comes back.

Conclusion

In this article, I described how to deploy Helidon applications to Azure App Service. I hope this article helps.

--

--

Akihiro Nishikawa
Microsoft Azure

Cloud Solution Architect @ Microsoft, and JJUG (Japan Java Users Group) board member. ♥Java (JVM/GraalVM) and open-source technologies. All views are my own.