I am creating a Azure function with Spring Cloud with below configuration. It's working fine when run locally but when I deploy this in Azure (Deploying using IntelliJ IDE) deployment is success but when accessing the function in Azure portal its throwing error its not able to locate the Main classs.
When I extract the jar created in local can see MANIFEST.MF file with entry as Main-Class: com.azlearning.functionapp.AzEmailSenderFunctionApplication.
But Azure runtime is expecting main class to be defined with MAIN_CLASS. When using spring provided plugin its alway creates Main-Class entry.
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.azlearning</groupId>
<artifactId>az-email-sender-function</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>az-email-sender-function</name>
<description>Azure Email Sender function</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-boot-thin-layout.version>1.0.31.RELEASE</spring-boot-thin-layout.version>
<!-- Spring Boot start class! WARING: correct class must be set! -->
<start-class>com.azlearning.functionapp.AzEmailSenderFunctionApplication</start-class>
<!-- AZURE FUNCTION CONFIG -->
<azure.functions.maven.plugin.version>1.36.0</azure.functions.maven.plugin.version>
<functionAppName>email-sender-funapp</functionAppName>
<functionAppRegion>Region</functionAppRegion>
<functionResourceGroup>az-cert-resource-group</functionResourceGroup>
<functionAppServicePlanName>PlanName</functionAppServicePlanName>
<functionPricingTier>PriceTier</functionPricingTier>
<spring-cloud.version>2024.0.0</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<version>${azure.functions.maven.plugin.version}</version>
<configuration>
<appName>${functionAppName}</appName>
<resourceGroup>${functionResourceGroup}</resourceGroup>
<region>${functionAppRegion}</region>
<appServicePlanName>${functionAppServicePlanName}</appServicePlanName>
<pricingTier>${functionPricingTier}</pricingTier>
<hostJson>${project.basedir}/src/main/resources/host.json</hostJson>
<!-- <localSettingsJson>${project.basedir}/src/main/resources/local.settings.json</localSettingsJson> -->
<runtime>
<os>linux</os>
<javaVersion>17</javaVersion>
</runtime>
<funcPort>7072</funcPort>
<appSettings>
<property>
<name>FUNCTIONS_EXTENSION_VERSION</name>
<value>~4</value>
</property>
<!-- <property>
<name>MAIN_CLASS</name>
<value>com.azlearning.functionapp.AzEmailSenderFunctionApplication</value>
</property> -->
</appSettings>
</configuration>
<executions>
<execution>
<id>package-functions</id>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.azlearning.functionapp.AzEmailSenderFunctionApplication</mainClass>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.31.RELEASE</version>
</dependency>
</dependencies>
</plugin> -->
</plugins>
</build>
</project>
Start-Class
in pom.xml
to the main class of your spring boot application.<start-class>com.example.DemoApplication</start-class>
Main_Class = com.example.DemoApplication
in the FunctionApp=>Settings=>Environment Variables=>App Settings
.I have created a simple Spring Boot Azure function, refer GitHub repository for the sample project.
Run the project locally before deploying to Azure and check if you are able to sync the function trigger.
Update pom.xml
as below:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>hello</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Hello Spring Function on Azure</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<azure.functions.maven.plugin.version>1.22.0</azure.functions.maven.plugin.version>
<azure.functions.java.library.version>3.0.0</azure.functions.java.library.version>
<spring.cloud.function.dependencies>4.0.0</spring.cloud.function.dependencies>
<functionResourceGroup>resource_group_name</functionResourceGroup>
<functionAppServicePlanName>AppService_Plan</functionAppServicePlanName>
<functionAppName>Function_App_Name</functionAppName>
<functionAppRegion>Region</functionAppRegion>
<functionPricingTier>Pricing Tier</functionPricingTier>
<start-class>com.example.DemoApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-function-webflux</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-dependencies</artifactId>
<version>${spring.cloud.function.dependencies}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.microsoft.azure.functions</groupId>
<artifactId>azure-functions-java-library</artifactId>
<version>${azure.functions.java.library.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<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.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>4.1.5</version>
<configuration>
<includes>
<include>com.example.loadtest.*</include>
</includes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<configuration>
<resourceGroup>${functionResourceGroup}</resourceGroup>
<appName>${functionAppName}</appName>
<region>${functionAppRegion}</region>
<appServicePlanName>${functionAppServicePlanName}</appServicePlanName>
<pricingTier>${functionPricingTier}</pricingTier>
<hostJson>${project.basedir}/src/main/azure/host.json</hostJson>
<localSettingsJson>${project.basedir}/src/main/azure/local.settings.json</localSettingsJson>
<runtime>
<os>linux</os>
<javaVersion>17</javaVersion>
</runtime>
<appSettings>
<!-- Run Azure Function from package file by default -->
<property>
<name>FUNCTIONS_EXTENSION_VERSION</name>
<value>~4</value>
</property>
</appSettings>
</configuration>
<executions>
<execution>
<id>package-functions</id>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
<!--Remove obj folder generated by .NET SDK in maven clean-->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filesets>
<fileset>
<directory>obj</directory>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
DemoApplication.java:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(DemoApplication.class, args);
}
}
HelloHandler.java:
package com.example;
import com.example.model.Greeting;
import com.example.model.User;
import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
import java.util.Optional;
public class HelloHandler extends FunctionInvoker<User, Greeting> {
@FunctionName("hello")
public HttpResponseMessage execute(
@HttpTrigger(name = "request", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request,
ExecutionContext context) {
User user = request.getBody()
.filter((u -> u.getName() != null))
.orElseGet(() -> new User(
request.getQueryParameters()
.getOrDefault("name", "world")));
context.getLogger().info("Greeting user name: " + user.getName());
return request
.createResponseBuilder(HttpStatus.OK)
.body(handleRequest(user, context))
.header("Content-Type", "application/json")
.build();
}
}
Deployed the spring boot function to Azure using the command mvn azure-functions:deploy
:
C:\Users\uname\hello-spring-function-azure>mvn azure-functions:deploy
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< com.example:hello >--------------------------
[INFO] Building Hello Spring Function on Azure 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- azure-functions:1.22.0:deploy (default-cli) @ hello ---
[INFO] Auth type: AZURE_CLI
Default subscription: Subscription(158b8345XXd98-95c5-f21815dd048f)
Username: userid
//Removed few logs
[INFO] Function App(rkfn) is successfully created
[INFO] Starting deployment...
[INFO] Trying to deploy artifact to rkfn...
[INFO] Successfully deployed the artifact to https://functionname.azurewebsites.net
[INFO] Deployment done, you may access your resource through rkfn.azurewebsites.net
[INFO] Syncing triggers and fetching function information
[INFO] Querying triggers...
[INFO] HTTP Trigger Urls:
[INFO] hello : https://functionname.azurewebsites.net/api/hello
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:22 min
[INFO] Finished at: 2024-12-19T16:40:02+05:30
[INFO] ------------------------------------------------------------------------
Portal:
Response:
Route to https://functionname.azurewebsites.net/api/hello
: