Spring Cloud Function in Azure
This article outlines the deployment of Spring Cloud Function as a Java Function to Azure Functions, from validation and setup to testing and deployment.
Join the DZone community and get the full member experience.
Join For FreeThis article covers the usage of Spring Cloud Function as a Java Function and deployment to Azure Functions.
Prerequisites
- JDK, version 8+.
- Apache Maven, version 3 or higher.
- Azure Account (free trial would suffice as well).
- Azure CLI.
- Azure Functions Core Tools.
Validating the Local Environment Setup
Verify Apache Maven version:
mvn -V
Verify Azure CLI:
xxxxxxxxxx
az --version
Verify Azure Function Core tools:
xxxxxxxxxx
func -v
Code Setup
Create an empty maven project. Use the below pom.xml and build the project.
x
<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.demo</groupId>
<artifactId>demo-springcloud-function</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Helloworld Spring Function on Azure</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<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.java.library.version>1.4.0</azure.functions.java.library.version>
<azure.functions.maven.plugin.version>1.3.1</azure.functions.maven.plugin.version>
<functionResourceGroup>sample-resource-group</functionResourceGroup>
<functionAppName>helloworld-spring-function</functionAppName>
<functionAppRegion>westeurope</functionAppRegion>
<stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
<start-class>com.demo.HelloworldApplication</start-class>
<spring.boot.wrapper.version>1.0.26.RELEASE</spring.boot.wrapper.version>
</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>
<!-- Test -->
<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>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-dependencies</artifactId>
<version>3.1.0</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>
<plugins>
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<configuration>
<appName>${functionAppName}</appName>
<resourceGroup>${functionResourceGroup}</resourceGroup>
<appServicePlanName>azure-functions-app-service-plan</appServicePlanName>
<region>${functionAppRegion}</region>
<runtime>
<os>windows</os>
</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>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<filesets>
<fileset>
<directory>obj</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</project>
Customize below properties in the pom.xml file as per your application.
<functionAppName>
— name of your Azure Function
<functionAppRegion>
— name of the Azure region where your Function will be deployed
<functionResourceGroup>
— name of the Azure resource group which will be used
In the Project base directory create the following configuration files required by the Azure Functions.
host.json
xxxxxxxxxx
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
local.settings.json
xxxxxxxxxx
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "java"
},
"Host": {
"LocalHttpPort": 8091,
"CORS": "*",
"CORSCredentials": false
}
}
Create below Model Classes.
Employee.java
xxxxxxxxxx
package com.demo.model;
import jdk.nashorn.internal.objects.annotations.Getter;
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
EmployeeGreeting.java
x
package com.demo.model;
public class EmployeeGreeting {
private String message;
public EmployeeGreeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Create the Springboot Application
The welcomeEmployee()
function returns a java.util.function.Function
and is a Spring bean. It is important that the Azure Functions that we create next will have the same name.
welcomeEmployee
xxxxxxxxxx
package com.demo;
import com.demo.model.Employee;
import com.demo.model.EmployeeGreeting;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.util.function.Function;
public class HelloworldApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(HelloworldApplication.class, args);
}
public Function<Employee, EmployeeGreeting> welcomeEmployee() {
return employee -> new EmployeeGreeting("Hello, We welcome you , " + employee.getName());
}
}
Create the Azure Function
- The Java class which is an Azure Function extends the
AzureSpringBootRequestHandler
, does the link between Azure Functions and Spring Cloud Function. This is what provides thehandleRequest()
method that is used in itsexecute()
method. - The name of the function, defined with
@FunctionName("welcomeEmployee")
annotation, is the same as the Spring bean we have configured in the previous step,welcomeEmployee
xxxxxxxxxx
package com.demo;
import com.demo.model.Employee;
import com.demo.model.EmployeeGreeting;
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.AzureSpringBootRequestHandler;
import java.util.Optional;
public class HelloWorldHandler extends AzureSpringBootRequestHandler<Employee, EmployeeGreeting> {
"welcomeEmployee") (
public HttpResponseMessage execute(
name = "request", methods = {HttpMethod.GET, HttpMethod.POST},authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<Employee>> request,ExecutionContext context) { (
return request
.createResponseBuilder(HttpStatus.OK)
.body(handleRequest(request.getBody().get(), context))
.header("Content-Type", "application/json")
.build();
}
}
Local Testing
Package the application:
xxxxxxxxxx
mvn clean package
Run the project locally:
xxxxxxxxxx
mvn azure-functions:run
Below will be the output in the console on successful startup:
Test the setup using Postman:
Deployment to Azure Function
In the command line, run the below command and login to the Azure account.
xxxxxxxxxx
az login
Deploy to Azure function using below command:
xxxxxxxxxx
mvn azure-functions:deploy
Verify the deployment by logging into the Azure Portal:
Test the Azure function by using Postman:
Opinions expressed by DZone contributors are their own.
Comments