Spring Cloud Function en Azure
Este artículo le guía por el uso de Spring Cloud Functions para desarrollar una función de Java y publicarla en Azure Functions. Cuando haya terminado, el código de la función se ejecuta en el Plan de consumo en Azure y puede activarse mediante una solicitud HTTP.
Prerrequisitos
- Una suscripción de Azure. Si no tiene una suscripción de Azure , cree una cuenta gratuita de antes de empezar.
Para desarrollar funciones mediante Java, debe tener instalado lo siguiente:
- Kit para desarrolladores de Java, versión 11
- Apache Maven, versión 3.0 o posterior
- CLI de Azure
- Azure Functions Core Tools versión 4
Importante
- Debe establecer la variable de entorno
JAVA_HOME
en la ubicación de instalación del JDK para completar este inicio rápido. - Asegúrese de que la versión de las herramientas principales sea al menos 4.0.5455.
Lo que vamos a crear
Vamos a crear una función clásica "Hello, World" que se ejecuta en Azure Functions y se configura con Spring Cloud Function.
La función recibe un objeto JSON de User
, que contiene un nombre de usuario, y devuelve un objeto Greeting
, que contiene el mensaje de bienvenida a ese usuario.
El proyecto está disponible en el ejemplo de Spring Cloud Function en Azure del repositorio azure-function-java-worker en GitHub. Puede usar ese ejemplo directamente si desea ver el trabajo final descrito en este inicio rápido.
Creación de un nuevo proyecto de Maven
Vamos a crear un proyecto de Maven vacío y configurarlo con Spring Cloud Function y Azure Functions.
En una carpeta vacía, cree un nuevo archivo pom.xml y copie o pegue el contenido del archivo pom.xml del proyecto de ejemplo.
Nota
Este archivo usa las dependencias de Maven tanto de Spring Boot como de spring Cloud Functions, y configura los complementos de Spring Boot y Maven de Azure Functions.
Debe personalizar algunas propiedades para la aplicación:
<functionAppName>
es el nombre de la función de Azure<functionAppRegion>
es el nombre de la región de Azure donde se implementa la función.<functionResourceGroup>
es el nombre del grupo de recursos de Azure que usa.
Cambie esas propiedades directamente cerca de la parte superior del archivo pom.xml, como se muestra en el ejemplo siguiente:
<properties>
<java.version>11</java.version>
<!-- Spring Boot start class. WARNING: correct class must be set -->
<start-class>com.example.DemoApplication</start-class>
<!-- customize those properties. WARNING: the functionAppName should be unique across Azure -->
<azure.functions.maven.plugin.version>1.36.0</azure.functions.maven.plugin.version>
<functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
<functionAppServicePlanName>my-spring-function-service-plan</functionAppServicePlanName>
<functionAppName>my-spring-function</functionAppName>
<functionPricingTier>Y1</functionPricingTier>
<functionAppRegion>eastus</functionAppRegion>
</properties>
Creación de archivos de configuración de Azure
Cree una carpeta src/main/resources y agregue los siguientes archivos de configuración de Azure Functions.
host.json:
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.2.0)"
},
"functionTimeout": "00:10:00"
}
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "java",
"FUNCTIONS_EXTENSION_VERSION": "~4",
"AzureWebJobsDashboard": ""
}
}
Creación de objetos de dominio
Azure Functions puede recibir y enviar objetos en formato JSON.
Ahora vamos a crear nuestros objetos User
y Greeting
, que representan nuestro modelo de dominio.
Puede crear objetos más complejos, con más propiedades, si desea personalizar este inicio rápido y hacer que sea más interesante para usted.
Cree una carpeta src/main/java/com/example/model y agregue los dos archivos siguientes:
User.java:
package com.example.model;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Greeting.java:
package com.example.model;
public class Greeting {
private String message;
public Greeting() {
}
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Creación de la aplicación Spring Boot
Esta aplicación administra toda la lógica de negocios y tiene acceso al ecosistema completo de Spring Boot. Esta funcionalidad ofrece dos ventajas principales sobre una función estándar de Azure:
- No se basa en las API de Azure Functions, por lo que puede migrarla fácilmente a otros sistemas. Por ejemplo, puede reutilizarlo en una aplicación de Spring Boot normal.
- Puede usar todas las anotaciones de
@Enable
de Spring Boot para agregar nuevas características.
En la carpeta src/main/java/com/example, cree el siguiente archivo, que es una aplicación normal de Spring Boot:
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);
}
}
Ahora cree el siguiente archivo en la carpeta src/main/java/com/example/hello. Este código contiene un componente de Spring Boot que representa la función que queremos ejecutar:
Hello.java:
package com.example.hello;
import com.example.model.*;
import org.springframework.stereotype.Component;
import java.util.function.Function;
@Component
public class Hello implements Function<User, Greeting> {
@Override
public Greeting apply(User user) {
return new Greeting("Hello, " + user.getName() + "!\n");
}
}
Nota
La función Hello
es bastante específica:
- Es una
java.util.function.Function
. Contiene la lógica de negocios y usa una API de Java estándar para transformar un objeto en otro. - Dado que tiene la anotación
@Component
, es un Bean de Spring y, de forma predeterminada, su nombre es el mismo que la clase, pero a partir de un carácter en minúsculas:hello
. Seguir esta convención de nomenclatura es importante si desea crear otras funciones en la aplicación. El nombre debe coincidir con el nombre de Azure Functions que crearemos en la sección siguiente.
Creación de la función de Azure
Para beneficiarse de la API completa de Azure Functions, ahora codificamos una función de Azure que delega su ejecución en la función de Spring Cloud creada en el paso anterior.
En la carpeta src/main/java/com/example/hello, cree el siguiente archivo de clase de función de Azure:
HelloHandler.java:
package com.example.hello;
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 com.example.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class HelloHandler {
@Autowired
private Hello hello;
@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(hello.apply(user))
.header("Content-Type", "application/json")
.build();
}
}
Esta clase de Java es una función de Azure, con las siguientes características interesantes:
- La clase tiene la anotación
@Component
, por lo que es un Bean de Spring. - El nombre de la función, tal como se define en la anotación de
@FunctionName("hello")
, eshello
. - La clase implementa una función real de Azure, por lo que puede usar la API completa de Azure Functions aquí.
Agregar pruebas unitarias
Este paso es opcional, pero se recomienda validar que la aplicación funciona correctamente.
Cree una carpeta src/test/java/com/example y agregue las siguientes pruebas JUnit:
HelloTest.java:
package com.example;
import com.example.hello.Hello;
import com.example.model.Greeting;
import com.example.model.User;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class HelloTest {
@Test
public void test() {
Greeting result = new Hello().apply(new User("foo"));
assertThat(result.getMessage()).isEqualTo("Hello, foo!\n");
}
}
Ahora puede probar la función de Azure mediante Maven:
mvn clean test
Ejecución local de la función
Antes de implementar la aplicación en Azure Functions, vamos a probarla localmente.
En primer lugar, debe empaquetar la aplicación en un archivo Jar:
mvn package
Ahora que la aplicación está empaquetada, puede ejecutarla mediante el complemento azure-functions
Maven:
mvn azure-functions:run
La función de Azure ahora debe estar disponible en el host local mediante el puerto 7071. Puede probar la función mediante el envío de una solicitud POST, con un objeto User
en formato JSON. Por ejemplo, con cURL:
curl -X POST http://localhost:7071/api/hello -d "{\"name\":\"Azure\"}"
La función debe responderle con un objeto Greeting
, todavía en formato JSON:
{
"message": "Hello, Azure!\n"
}
Esta es una captura de pantalla de la solicitud cURL en la parte superior de la pantalla y la función local de Azure en la parte inferior:
Depuración local de la función
Las siguientes secciones describen cómo depurar la función.
Depuración mediante Intellij IDEA
Abra el proyecto en Intellij IDEA y, a continuación, cree la configuración de ejecución Depuración remota de JVM para adjuntarla. Para más información, consulte Tutorial: Depuración remota.
Ejecute la aplicación con el siguiente comando:
mvn azure-functions:run -DenableDebug
Cuando se inicia la aplicación, verá la salida siguiente:
Worker process started and initialized.
Listening for transport dt_socket at address: 5005
Comience a depurar el proyecto en IntelliJ IDEA. Verá la siguiente salida:
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Marque los puntos de interrupción que desea depurar. Intellij IDEA entrará en modo de depuración después de enviar una solicitud.
Depuración mediante Visual Studio Code
Abra el proyecto en Visual Studio Code y configure el siguiente contenido de archivo launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to Remote Program",
"request": "attach",
"hostName": "127.0.0.1",
"port": 5005
}
]
}
Ejecute la aplicación con el siguiente comando:
mvn azure-functions:run -DenableDebug
Cuando se inicia la aplicación, verá la salida siguiente:
Worker process started and initialized.
Listening for transport dt_socket at address: 5005
Inicie la depuración del proyecto en Visual Studio Code y, a continuación, marque los puntos de interrupción que desea depurar. Visual Studio Code entrará en modo de depuración después de enviar una solicitud. Para más información, consulte Ejecución y depuración en Java.
Implementación de la función en Azure Functions
Ahora, va a publicar la función de Azure en el entorno de producción. Recuerde que las propiedades <functionAppName>
, <functionAppRegion>
y <functionResourceGroup>
que ha definido en el archivo de pom.xml se usan para configurar la función.
Nota
El complemento maven debe autenticarse con Azure. Si tiene instalada la CLI de Azure, use az login
antes de continuar.
Para obtener más opciones de autenticación, consulte Autenticación en el repositorio azure-maven-plugins.
Ejecute Maven para implementar la función automáticamente:
mvn azure-functions:deploy
Ahora, vaya a Azure Portal para buscar el Function App
que se ha creado.
Seleccione la función :
- En la información general de la función, anote la dirección URL de la función.
- Para comprobar la función en ejecución, seleccione Streaming de registro en el menú de navegación.
Ahora, como hizo en la sección anterior, use cURL para acceder a la función en ejecución, como se muestra en el ejemplo siguiente. Asegúrese de reemplazar your-function-name
por el nombre de la función real.
curl https://your-function-name.azurewebsites.net/api/hello -d "{\"name\":\"Azure\"}"
Al igual que en la sección anterior, la función debe responderle con un objeto Greeting
, todavía en formato JSON:
{
"message": "Hello, Azure!\n"
}
Enhorabuena, tiene una función de Spring Cloud que se ejecuta en Azure Functions. Para obtener más información y ejemplos de funciones de Spring Cloud, consulte los siguientes recursos:
- Blog sobre Spring Cloud Function
- documentos de referencia de funciones de Spring Cloud
- ejemplos de funciones de Spring Cloud
Pasos siguientes
Para más información sobre Spring y Azure, continúe con el Centro de documentación de Spring en Azure.