В настоящее время я изучаю Spring Cloud Function и ее возможности для развертывания одной функции в разных облачных средах (функции AWS Lambda и Azure).
Моя функция выглядит так (конечно, очень упрощенно):
@Component
public class EchoFunction implements Function<String, String> {
@Override
public String apply(String m) {
String message = "Received message: " + m;
return message;
}
}
При его развертывании на AWS Lambda он работает отлично (полный проект можно найти здесь ).
Однако, если я запускаю ту же функцию, что и локальное развертывание функций Azure, используя основные инструменты функций Azure, я получаю следующее исключение при вызове функции:
24.01.19 21:58:50] Caused by: java.lang.ClassCastException: reactor.core.publisher.FluxJust cannot be cast to java.lang.String
[24.01.19 21:58:50] at de.margul.awstutorials.springcloudfunction.function.EchoFunction.apply(EchoFunction.java:9)
[24.01.19 21:58:50] at org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHandler.handleRequest(AzureSpringBootRequestHandler.java:56)
[24.01.19 21:58:50] at de.margul.awstutorials.springcloudfunction.azure.handler.FunctionHandler.execute(FunctionHandler.java:19)
[24.01.19 21:58:50] ... 16 more
По некоторым причинам, функция, кажется, ожидает поток вместо строки.
Я думаю, это может быть связано с тем, что [документация] (https://cloud.spring.io/spring-cloud-static/spring-cloud-function/2.0.0.RELEASE/single/spring-cloud-function.html#_function_catalog_and_flexible_function_signatures) говорит об этом:
Одной из основных функций Spring Cloud Function является адаптация и поддержка диапазона сигнатур типов для пользовательских функций, обеспечивая при этом согласованную модель выполнения. Вот почему все пользовательские функции преобразуются в каноническое представление с помощью FunctionCatalog с использованием примитивов, определенных в Project Reactor (то есть, Flux и Mono). Например, пользователи могут предоставить bean-компонент типа Function, а FunctionCatalog обернет его в Function, Flux>.
Так что проблема может быть связана с этим:
Если я изменю функцию следующим образом, она будет работать:
@Component
public class EchoFunction implements Function<String, Flux<String>> {
@Override
public Flux<String> apply(String m) {
String message = "Received message: "+m;
return Flux.just(message);
}
}
Мой обработчик функций выглядит так:
public class FunctionHandler extends AzureSpringBootRequestHandler<String, String> {
@FunctionName("createEntityFunction")
public String execute(@HttpTrigger(name = "req", methods = {
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<String> entity,
ExecutionContext context) {
return handleRequest(entity.getBody(), context);
}
@Bean
public EchoFunction createEntityFunction() {
return new EchoFunction();
}
}
Для развертывания AWS у меня были следующие зависимости:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.2.5</version>
</dependency>
</dependencies>
Для развертывания Azure у меня есть только одна зависимость:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
<version>2.0.0</version>
</dependency>
Я уже изучил исходный код обоих адаптеров:
В AWS SpringBootRequestHandler вызывает целевую функцию (в строке 48).
В Azure AzureSpringBootRequestHandler вызывает целевую функцию (в строке 56).
Для меня, похоже, в обоих случаях Флюс передается.
Однако для адаптера AWS Объект развернут где-то посередине, очевидно.
Но это не относится к адаптеру Azure.
Есть идеи, почему?