Hot questions for Using Azure in maven

Question:

I'm following this microsoft tutorial below and trying to deploy my azure function using the mvn azure-functions:deploy command. My function app name/artifactid is ci-cd-demo: https://azure.microsoft.com/en-us/resources/videos/azure-friday-java-in-azure-functions/

However, I receive an error:

[ERROR] Failed to execute goal com.microsoft.azure:azure-functions-maven-plugin:1.4.1:deploy (default-cli) on project ci-cd-demo: ci-cd-demod9632762a is not a valid storage account name. Storage account name mu
st be between 3 and 24 characters in length and use numbers and lower-case letters only.

I logged into the azure portal and created a Storage account. I also did this manually through the Azure CLI in command line. The storage account is "cicddemo777".

It looks as if when I run mvn azure-functions:deploy , the project cannot find the storage account , so it creates one and appends a bunch of numbers to the end of my function app name. I have the function app name , resource group, appservice plan and region variables in my pom.xml under the azure-functions-maven-plugin.

Is there a way to define the property variable for my azure storage account inside my project so I can successfully run the azure-functions:deploy command with this error?


Answer:

Update:

Thanks for ennth's sharing. This error comes from changing of functionAppName.

(Since FunctionAppName need unique in all of the world when deployed, it will generate a string of numbers by default.)

Original Answer:

mvn azure-functions:deploy is mainly used for the first time, because the files it produces are not specified. It will It generates random resources, which is by design.

Have a look of this:

https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven?pivots=java-build-tools-maven#deploy-the-function-to-azure

Use mvn azure-functions:deploy should not face problem. Have you set something in pom.xml? There must be no character like - in storage account name.

This is my pom.xml, and it is no problem:

http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0

<groupId>com.function</groupId>
<artifactId>ci-cd-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Azure Java Functions</name>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <azure.functions.maven.plugin.version>1.4.1</azure.functions.maven.plugin.version>
    <azure.functions.java.library.version>1.3.1</azure.functions.java.library.version>
    <functionAppName>ci-cd-demo-20200406102526581</functionAppName>
    <stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
</properties>

<repositories>
    <repository>
        <id>maven.snapshots</id>
        <name>Maven Central Snapshot Repository</name>
        <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

<pluginRepositories>
    <pluginRepository>
        <id>maven.snapshots</id>
        <name>Maven Central Snapshot Repository</name>
        <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </pluginRepository>
</pluginRepositories>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.23.4</version>
        </dependency>
        <dependency>
            <groupId>com.microsoft.azure.functions</groupId>
            <artifactId>azure-functions-java-library</artifactId>
            <version>${azure.functions.java.library.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.microsoft.azure.functions</groupId>
        <artifactId>azure-functions-java-library</artifactId>
    </dependency>

    <!-- Test -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-functions-maven-plugin</artifactId>
                <version>${azure.functions.maven.plugin.version}</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
        </plugins>
    </pluginManagement>

    <plugins>
        <plugin>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-functions-maven-plugin</artifactId>
            <configuration>
                <!-- function app name -->
                <appName>${functionAppName}</appName>
                <!-- function app resource group -->
                <resourceGroup>java-functions-group</resourceGroup>
                <!-- function app service plan name -->
                <appServicePlanName>java-functions-app-service-plan</appServicePlanName>
                <!-- function app region-->
                <!-- refers https://github.com/microsoft/azure-maven-plugins/tree/develop/azure-functions-maven-plugin#supported-regions for all valid values -->
                <region>westus</region>
                <!-- function pricingTier, default to be consumption if not specified -->
                <!-- refers https://github.com/microsoft/azure-maven-plugins/tree/develop/azure-functions-maven-plugin#supported-pricing-tiers for all valid values -->
                <!-- <pricingTier></pricingTier> -->
                <runtime>
                    <!-- runtime os, could be windows, linux or docker-->
                    <os>windows</os>
                    <!-- for docker function, please set the following parameters -->
                    <!-- <image>[hub-user/]repo-name[:tag]</image> -->
                    <!-- <serverId></serverId> -->
                    <!-- <registryUrl></registryUrl>  -->
                </runtime>
                <appSettings>
                    <property>
                        <name>FUNCTIONS_EXTENSION_VERSION</name>
                        <value>~3</value>
                    </property>
                </appSettings>
            </configuration>
            <executions>
                <execution>
                    <id>package-functions</id>
                    <goals>
                        <goal>package</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <overwrite>true</overwrite>
                        <outputDirectory>${stagingDirectory}</outputDirectory>
                        <resources>
                            <resource>
                                <directory>${project.basedir}</directory>
                                <includes>
                                    <include>host.json</include>
                                    <include>local.settings.json</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${stagingDirectory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                        <includeScope>runtime</includeScope>
                        <excludeArtifactIds>azure-functions-java-library</excludeArtifactIds>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!--Remove obj folder generated by .NET SDK in maven clean-->
        <plugin>
            <artifactId>maven-clean-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <filesets>
                    <fileset>
                        <directory>obj</directory>
                    </fileset>
                </filesets>
            </configuration>
        </plugin>
    </plugins>
</build>

In most cases, you should choose func azure functionapp publish <FunctionAppName> to deploy your function app. First, create a FunctionApp on Azure, and then deploy to this App. This is the doc:

https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#publish

Question:

My problem is that the packaged war file is not deployed from GitHub to Azure using Travis-CI correctly - the entire repository with the generated files are just copy-pasted. Here is what I do:

My approach:

I follow the Travis tutorial about Azure web app deployment and try to achieve the same in the minimal form. My goal is to assemble a war file and deploy it to Azure web app with Tomcat 8.0 container.

My project has the following .travis.yml configuration (I have omitted Java-8 definition, Sonar add-ons, and Coveralls after_success script for the sake of brevity):

script:
   - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar

deploy:
   provider: azure_web_apps
   skip_cleanup: true

I use AZURE_WA_USERNAME, AZURE_WA_PASSWORD and AZURE_WA_SITE environment variables.

I follow the standard Maven directory structure. The output directory is the standard /target. Thus, on the Travis is generated into:

/home/travis/build/MY_USERNAME/MY_WEBAPP/target/MY_WEBAPP.war

Where MY_USERNAME is the GitHub login name and MY_WEBAPP is the name of my application. The deployment looks fine at the first sight (I skipped similar lines):

Deploying application
[detached HEAD 9fd0ce7] Skip Cleanup Commit
54 files changed, 128 insertions(+)
create mode 100644 target/MY_WEBAPP-0.0.1-SNAPSHOT.war
create mode 100644 target/MY_WEBAPP-0.0.1-SNAPSHOT.war.original
create mode 100644 target/MY_WEBAPP-0.0.1-SNAPSHOT/WEB-INF/classes/... <- Skipped 3 lines
create mode 100644 target/MY_WEBAPP-0.0.1-SNAPSHOT/WEB-INF/lib/...     <- Skipped 20+ lines
... irrelevant ...                                                     <- Skipped 7 lines
Done. Your build exited with 0.

What is wrong and how it should be correct:

If I upload manually the war file via FTP(S) to the Azure directory /site/wwwroot/webapps, it's unpacked and deployed within a minute and works well.

Unlike the manual copy, Travis takes all the content and copy-paste it literally into the Azure webapp resulting in the mess like:

The war file hasn't been uploaded into the webapps folder. The newly created Azure webapp contains site/wwwroot/webapps/ROOT folder and is needed to upload the war file on the ROOT folder level. I have expected Travis would perform "smarter" behavior.

Question:

How to deploy to Azure from GitHub using Travis-CI correctly? I bet I miss something that isn't documented.


My workaround-attempts:

I have tried to fix the thing in several ways (none of them has worked). I consider all of them dirty:

  1. I tried to specify what to deploy in .travis.yml (no effect, everything is copied still):

    file_glob: true
    file: "/home/travis/build/MY_USERNAME/MY_WEBAPP/target/MY_WEBAPP*.war"
    
  2. An ugly bruteforce: Change the output directory from /target to /webapp resultin to override the destination folder in Azure upon deployment in the <build> section of 'pom.xml`:

    <directory>/webapps</directory>
    ...
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
            <warName>MY_WEBAPP</warName>
            <outputDirectory>/webapps</outputDirectory>
        </configuration>
    </plugin>
    
  3. Rename the output folder to webapps in .travis.yml:

    after_success:
     - bash mv /home/travis/build/MY_USERNAME/MY_WEBAPP/target/ /home/travis/build/MY_USERNAME/MY_WEBAPP/webapps/
    

    /bin/mv: /bin/mv: cannot execute binary file


Answer:

I have resolved the issue with uploading deployment scripts:

.deployment

[config]
command=deployment.cmd

deployment.cmd

@echo off
echo Azure: Deploying site

echo Azure: Removing the current war file
del %DEPLOYMENT_TARGET%\webapps\MY_WEBAPP.war /S /Q

echo Azure: Removing the current webapp folder
rmdir %DEPLOYMENT_TARGET%\webapps\MY_WEBAPP /S /Q

echo Azure: Copying war to the webapps folder
xcopy %DEPLOYMENT_TARGET%\..\repository\target\MY_WEBAPP.war %DEPLOYMENT_TARGET%\webapps /Y /s 

Question:

I got a missing artifact error when adding a dependency. The error I got is this:

Missing artifact com.azure:azure-security-keyvault-secrets:jar:4.1.0

This is my pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.companyname.encryptionkeyclient</groupId>
  <artifactId>encryptionkeyclient</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>encryptionkeyclient</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-security-keyvault-secrets</artifactId>
      <version>4.1.0</version>
    </dependency>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-identity</artifactId>
            <version>1.0.1</version>
    </dependency>
    <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-core</artifactId>
            <version>1.1.0</version>
        </dependency>
  </dependencies>
</project>

I suppose the reason is that the package is not available yet on maven, however, the package is available already https://mvnrepository.com/artifact/com.azure/azure-security-keyvault-secrets/4.1.0 .

So I don't know what I am missing here, can anyone help? Thanks.


Answer:

The mirror address you provided has "azure-security-keyvault-secrets" jar and in my project it download this jar successfully(with the same mirror address).

You can remove all of the packages under the "repository" folder and save the pom.xml, the project will download all of the packages again. The issue will go away.

Question:

I'm trying to deploy my java project on MS Azure. Locally it works fine, also I successfully deployed it on AWS and Heroku.

My steps:

1) Upload code to github repository

2) Create WebApp on Azure

3) Configure settings:

4) Go to deployment options & choose github

5) Select repository & press save

6) Wait for deployment

7) Open project url

But after all this steps I get "empty project pahe":

What am I doing wrong?


Answer:

It seems that the war file was deployed to an incorrect path, which be caused by your github repository structure. Please refer to my answer for a similar SO thread How to deploy java project on github to Azure, and check your github repository structure whether the war file is under the path <your-github-repository>/wwwroot/webapps, then try to deployment via Github again.

Any concern, please feel free to let me know.