Cleanup of Azure sample
This commit is contained in:
@@ -106,9 +106,7 @@ public class FunctionInvoker<I, O> {
|
|||||||
binding.setValue(result);
|
binding.setValue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
private FunctionInvocationWrapper discoverFunction(String functionDefinition) {
|
||||||
public O handleRequest(I input, ExecutionContext executionContext) {
|
|
||||||
String functionDefinition = executionContext.getFunctionName();
|
|
||||||
FunctionInvocationWrapper function = FUNCTION_CATALOG.lookup(functionDefinition);
|
FunctionInvocationWrapper function = FUNCTION_CATALOG.lookup(functionDefinition);
|
||||||
if (function != null && StringUtils.hasText(functionDefinition) && !function.getFunctionDefinition().equals(functionDefinition)) {
|
if (function != null && StringUtils.hasText(functionDefinition) && !function.getFunctionDefinition().equals(functionDefinition)) {
|
||||||
this.registerFunction(functionDefinition);
|
this.registerFunction(functionDefinition);
|
||||||
@@ -118,6 +116,13 @@ public class FunctionInvoker<I, O> {
|
|||||||
this.registerFunction(functionDefinition);
|
this.registerFunction(functionDefinition);
|
||||||
function = FUNCTION_CATALOG.lookup(functionDefinition);
|
function = FUNCTION_CATALOG.lookup(functionDefinition);
|
||||||
}
|
}
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
public O handleRequest(I input, ExecutionContext executionContext) {
|
||||||
|
String functionDefinition = executionContext.getFunctionName();
|
||||||
|
FunctionInvocationWrapper function = this.discoverFunction(functionDefinition);
|
||||||
Object enhancedInput = enhanceInputIfNecessary(input, executionContext);
|
Object enhancedInput = enhanceInputIfNecessary(input, executionContext);
|
||||||
|
|
||||||
Object output = function.apply(enhancedInput);
|
Object output = function.apply(enhancedInput);
|
||||||
|
|||||||
@@ -2,32 +2,19 @@ You can run this Azure function locally, similar to other Spring Cloud Function
|
|||||||
this time by using the Azure Maven plugin, as the Microsoft Azure functions execution context must be available.
|
this time by using the Azure Maven plugin, as the Microsoft Azure functions execution context must be available.
|
||||||
|
|
||||||
----
|
----
|
||||||
# Build and package
|
# Build and run package
|
||||||
$ mvn clean package
|
$ mvn clean package
|
||||||
|
|
||||||
# Previously, for other examples
|
|
||||||
$ mvn spring-boot:run
|
|
||||||
|
|
||||||
# For Azure Functions
|
|
||||||
$ mvn clean package azure-functions:run
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
$ mvn azure-functions:run
|
$ mvn azure-functions:run
|
||||||
----
|
----
|
||||||
|
|
||||||
The `uppercase` function takes `Function<String, String> uppercase()` and its expected input is JSON map, therefore we need to
|
The `uppercase` function is of the following signature `Function<Message<String>, String> uppercase()`. Its expected input is JSON,
|
||||||
provide the appropriate content-type (in this case `application/json`). The function iterates then over each element
|
therefore we need t0 provide the appropriate content-type (in this case `application/json`).
|
||||||
and returns its `uppercase` mapped value.
|
|
||||||
|
|
||||||
Test the function using cURL or HTTPie and notice that the URL is formed by concatenating `<function url>/api/<function name>`
|
Test the function using _curl_ and notice that the URL is formed by concatenating `<function url>/api/<function name>`
|
||||||
----
|
----
|
||||||
# testing with cURL
|
# testing with cURL
|
||||||
$ curl -H "Content-Type: application/json" localhost:7071/api/uppercase -d '{"greeting": "hello", "name": "your name"}'
|
$ curl -H "Content-Type: application/json" localhost:7071/api/uppercase -d '{"greeting": "hello", "name": "your name"}'
|
||||||
|
|
||||||
# testing with HTTPie
|
|
||||||
$ http POST localhost:7071/api/uppercase greeting=hello name='your name'
|
|
||||||
|
|
||||||
# result
|
# result
|
||||||
{
|
{
|
||||||
"greeting": "HELLO",
|
"greeting": "HELLO",
|
||||||
@@ -35,7 +22,27 @@ $ http POST localhost:7071/api/uppercase greeting=hello name='your name'
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
The same is for `echo` function, however it will take any input since all it does is just echos it back.
|
The HTTP headers of the incoming request will be copied into input Message's MessageHeaders, so they become accessible if need to.
|
||||||
|
It is done in implementation of `UppercaseHandler` which extends `FunctionInvoker`.
|
||||||
|
|
||||||
|
NOTE: Implementation of FunctionInvoker, should contain the least amount of code. Everything should be delegated to the base FunctionInvoker.
|
||||||
|
These implementations of FunctionInvoker are really a type-safe way to define and configure function to be recognized as Azure Function.
|
||||||
|
Look at it as _configuration with the callback_ (e.g., `this.handleRequest(..)`).
|
||||||
|
----
|
||||||
|
@FunctionName("uppercase")
|
||||||
|
public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
||||||
|
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
|
||||||
|
ExecutionContext context) {
|
||||||
|
Message<String> message = MessageBuilder.withPayload(request.getBody().get()).copyHeaders(request.getHeaders()).build();
|
||||||
|
return handleRequest(message, context);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
The `echo` function does the same as the `uppercase` less the actual uppercasing. However, the important difference to notice is that function itself
|
||||||
|
takes primitive `String` as its input while the actual handler passes instance of `Message` the same way as with `uppercase`. The framework recognizes that
|
||||||
|
you only care about the payload and extracts it from the message before calling the function.
|
||||||
|
|
||||||
|
|
||||||
There is also a reactive version of 'uppercase' - `uppercaseReactive` which will produce the same result, but
|
There is also a reactive version of 'uppercase' - `uppercaseReactive` which will produce the same result, but
|
||||||
demonstrates and validates the ability to use reactive functions with Azure.
|
demonstrates and validates the ability to use reactive functions with Azure.
|
||||||
@@ -73,10 +80,6 @@ curl https://<azure-function-url-from-the-log>/api/uppercase -d '{"greeting": "h
|
|||||||
|
|
||||||
# testing with cURL
|
# testing with cURL
|
||||||
$ curl -H "Content-Type: application/json" https://function-sample-azure.azurewebsites.net/api/uppercase -d '{"greeting": "hello", "name": "your name"}'
|
$ curl -H "Content-Type: application/json" https://function-sample-azure.azurewebsites.net/api/uppercase -d '{"greeting": "hello", "name": "your name"}'
|
||||||
|
|
||||||
# testing with HTTPie
|
|
||||||
$ http POST https://function-sample-azure.azurewebsites.net/api/uppercase greeting=hello name='your name'
|
|
||||||
|
|
||||||
# result
|
# result
|
||||||
{
|
{
|
||||||
"greeting": "HELLO",
|
"greeting": "HELLO",
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ public class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Function<Message<String>, String> echo() {
|
public Function<String, String> echo() {
|
||||||
return message -> message.getPayload();
|
return payload -> payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -26,17 +26,21 @@ import com.microsoft.azure.functions.annotation.HttpTrigger;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
|
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.support.MessageBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Soby Chacko
|
* @author Soby Chacko
|
||||||
|
* @author Oleg Zhurakousky
|
||||||
*/
|
*/
|
||||||
public class EchoHandler extends FunctionInvoker<String, String> {
|
public class EchoHandler extends FunctionInvoker<Message<String>, String> {
|
||||||
|
|
||||||
@FunctionName("echo")
|
@FunctionName("echo")
|
||||||
public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
||||||
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
|
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
|
||||||
ExecutionContext context) {
|
ExecutionContext context) {
|
||||||
return handleRequest(request.getBody().get(), context);
|
Message<String> message = MessageBuilder.withPayload(request.getBody().get()).copyHeaders(request.getHeaders()).build();
|
||||||
|
return handleRequest(message, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2018-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,17 +26,21 @@ import com.microsoft.azure.functions.annotation.HttpTrigger;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
|
import org.springframework.cloud.function.adapter.azure.FunctionInvoker;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.support.MessageBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Soby Chacko
|
* @author Soby Chacko
|
||||||
|
* @author Oleg Zhurakousky
|
||||||
*/
|
*/
|
||||||
public class UppercaseHandler extends FunctionInvoker<String, String> {
|
public class UppercaseHandler extends FunctionInvoker<Message<String>, String> {
|
||||||
|
|
||||||
@FunctionName("uppercase")
|
@FunctionName("uppercase")
|
||||||
public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
public String execute(@HttpTrigger(name = "req", methods = {HttpMethod.GET,
|
||||||
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
|
HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
|
||||||
ExecutionContext context) {
|
ExecutionContext context) {
|
||||||
return handleRequest(request.getBody().get(), context);
|
Message<String> message = MessageBuilder.withPayload(request.getBody().get()).copyHeaders(request.getHeaders()).build();
|
||||||
|
return handleRequest(message, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user