Files
spring-cloud-function/spring-cloud-function-samples/function-azure-di-samples/README.md
Christian Tzolov 1d5dd42bcc Forward port #969
2022-12-15 12:04:51 +01:00

206 lines
6.0 KiB
Markdown

# Azure Functions with DI adapter
## Common instructions to integrate Azure Functions with Spring Framework
* Use the [Spring Initializer](https://start.spring.io/) to generate a pain, java Spring Boot project without additional dependencies. Set the boot version to `3.0.x`, the build to `Maven` and the packaging to `Jar`.
* Add the `spring-cloud-function-adapter-azure` POM dependency:
```xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
<version>4.0.0</version>
</dependency>
```
Having the adapter on the classpath activates the Azure Java Worker integration.
* Implement the [Azure Java Functions](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#java-function-basics) as `@FunctionName` annotated methods:
```java
import java.util.Optional;
import java.util.function.Function;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyAzureFunction {
@Autowired
private Function<String, String> uppercase;
@FunctionName("ditest")
public String execute(
@HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {
return this.uppercase.apply(request.getBody().get());
}
}
```
- The `@FunctionName` annotated methods represent the Azure Function implementations.
- The class must be marked with the Spring `@Component` annotation.
- You can use any Spring mechanism to auto-wire the Spring beans used for the function implementation.
* Add the `host.json` configuration under the `src/main/resources` folder:
```json
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
}
}
```
* When bootstrapped as Spring Boot project make sure to either disable the `spring-boot-maven-plugin` plugin or cover it into `thin-layout`:
```xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${spring-boot-thin-layout.version}</version>
</dependency>
</dependencies>
</plugin>
```
Since Azure Functions requires a specific, custom, Jar packaging we have to disable SpringBoot one.
* Add the `start-class` POM property to point to your main (e.g. SpringApplication) class.
```xml
<properties>
<java.version>17</java.version>
<start-class>YOUR MAIN CLASS</start-class>
...
</properties>
```
* Add the `azure-functions-maven-plugin` to your POM configuration. A sample configuration would look like this.
```xml
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-functions-maven-plugin</artifactId>
<version>1.22.0 or higher</version>
<configuration>
<appName>YOUR-AZURE-FUNCTION-APP-NAME</appName>
<resourceGroup>YOUR-AZURE-FUNCTION-RESOURCE-GROUP</resourceGroup>
<region>YOUR-AZURE-FUNCTION-APP-REGION</region>
<appServicePlanName>YOUR-AZURE-FUNCTION-APP-SERVICE-PLANE-NAME</appServicePlanName>
<pricingTier>YOUR-AZURE-FUNCTION-PRICING-TIER</pricingTier>
<hostJson>${project.basedir}/src/main/resources/host.json</hostJson>
<runtime>
<os>linux</os>
<javaVersion>11</javaVersion>
</runtime>
<funcPort>7072</funcPort>
<appSettings>
<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>
```
- Set the AZURE subscription configuration such as app name, resource group, region, service plan, pricing Tier
- Runtime configuration:
- [Java Versions](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#java-versions)
- Specify [Deployment OS](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-java?tabs=bash%2Cconsumption#specify-the-deployment-os)
* Build the project:
```
./mvnw clean package
```
## Running Locally
NOTE: To run locally on top of `Azure Functions`, and to deploy to your live Azure environment, you will need `Azure Functions Core Tools` installed along with the Azure CLI (see [here](https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-java?tabs=bash%2Cazure-cli%2Cbrowser#configure-your-local-environment)).
For some configuration you would need the [Azurite emulator](https://learn.microsoft.com/en-us/azure/storage/common/storage-use-emulator) as well.
Then build and run the sample:
```
./mvnw clean package
./mvnw azure-functions:run
```
## Running on Azure
Make sure you are logged in your Azure account.
```
az login
```
Build and deploy
```
./mvnw clean package
./mvnw azure-functions:deploy
```
## Debug locally
Run the function in debug mode.
```
./mvnw azure-functions:deploy -DenableDebug
```
Alternatively and the `JAVA_OPTS` value to your `local.settings.json` like this:
```json
{
"IsEncrypted": false,
"Values": {
...
"FUNCTIONS_WORKER_RUNTIME": "java",
"JAVA_OPTS": "-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005"
}
}
```
VS Code remote debug configuration:
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to Remote Program",
"request": "attach",
"hostName": "localhost",
"port": "5005"
},
}
```