From f09f750c390503b5b849ce011528e2ce1ce4ff4f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 16 Aug 2018 15:18:59 +0100 Subject: [PATCH] Add support for different handler->function mappings in Azure --- .../README.adoc | 46 +--- .../azure/AzureSpringBootRequestHandler.java | 33 +-- .../azure/AzureSpringFunctionInitializer.java | 40 +++- .../AzureSpringBootRequestHandlerTests.java | 220 ++++++++++++++++++ .../adapter/azure/TestExecutionContext.java | 45 ++++ .../function-sample-azure/.gitignore | 6 +- .../function-sample-azure/pom.xml | 99 +++++--- .../src/assembly/azure.xml | 20 -- .../src/main/azure/local.settings.json | 3 +- .../src/main/azure/uppercase/function.json | 21 -- .../src/main/java/example/FooHandler.java | 11 +- .../function-sample-pojo/build.gradle | 4 +- .../function-sample-pojo/pom.xml | 2 +- 13 files changed, 410 insertions(+), 140 deletions(-) create mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandlerTests.java create mode 100644 spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/TestExecutionContext.java delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/assembly/azure.xml delete mode 100644 spring-cloud-function-samples/function-sample-azure/src/main/azure/uppercase/function.json diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc index bf93ca31a..2616a00b1 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/README.adoc @@ -3,44 +3,14 @@ This project provides an adapter layer for a Spring Cloud Function application onto Azure. You can write an app with a single `@Bean` of type `Function` and it will be deployable in Azure if you get the JAR file laid out right. -This project provides an adapter layer for a Spring Cloud Function application onto Azure. -You can write an app with a single `@Bean` of type `Function` and it will be deployable in Azure if you get the JAR file laid out right. +There is a `AzureSpringBootRequestHandler` which you must extend, and provide the input and output types as annotated method parameters (enabling Azure to inspect the class and create JSON bindings). The base class has two useful methods (`handleRequest` and `handleOutput`) to which you can delegate the actual function call, so mostly the function will only ever have one line. -The adapter has a generic HTTP request handler that you can use optionally. -There is a `AzureSpringBootRequestHandler` which you must extend, and provide the input and output types as type parameters (enabling Azure to inspect the class and do the JSON conversions itself). - -If your app has more than one `@Bean` of type `Function` etc. then you can choose the one to use by configuring `function.name`. -The functions are extracted from the Spring Cloud `FunctionCatalog`. +If your app has more than one `@Bean` of type `Function` etc. then you can choose the one to use by configuring `function.name`. Or if you make the `@FunctionName` in the Azure handler method match the function name it should work that way (also for function apps with multiple functions). The functions are extracted from the Spring Cloud `FunctionCatalog`. === Notes on JAR Layout -You don't need the Spring Cloud Function Web at runtime in Azure, so you need to exclude this before you create the JAR you deploy to Azure. -A function application on Azure has to be shaded, but a Spring Boot standalone application does not, so you can run the same app using 2 separate jars (as per the sample here). -The sample app creates the shaded jar file, with an `azure` classifier for deploying in Azure. - -=== JSON Configuration - -The Azure tooling needs to find some JSON configuration files to tell it how to deploy and integrate the function (e.g. which Java class to use as the entry point, and which triggers to use). Those files can be created with the Maven plugin for a non-Spring function, but the tooling doesn't work yet with the adapter in its current form. There is an example `function.json` in the sample which hooks the function up as an HTTP endpoint: - -``` -{ - "scriptFile" : "../function-sample-azure-2.0.0.BUILD-SNAPSHOT-azure.jar", - "entryPoint" : "example.FooHandler.execute", - "bindings" : [ { - "type" : "httpTrigger", - "name" : "foo", - "direction" : "in", - "authLevel" : "anonymous", - "methods" : [ "get", "post" ] - }, { - "type" : "http", - "name" : "$return", - "direction" : "out" - } ], - "disabled" : false -} -``` - +You don't need the Spring Cloud Function Web at runtime in Azure, so you can optionally exclude this before you create the JAR you deploy to Azure. +A function application on Azure is an archive generated by the Maven plugin. The function lives in the JAR file generated by this project. The sample creates it as an executable jar, using the thin layout, so that Azure can find the handler classes. If you prefer you can just use a regular flat JAR file. The dependencies should *not* be included. == Build @@ -58,7 +28,13 @@ You can run the sample locally, just like the other Spring Cloud Function sample and `curl -H "Content-Type: text/plain" localhost:8080/function -d '{"value": "hello foobar"}'`. -You will need the `az` CLI app and some node.js fu (see https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven for more detail). To deploy the function on Azure runtime: +Or you can run locally in an Azure host: + +--- +./mvnw azure-functions:run +--- + +You will need the `az` and `func` CLI apps (see https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven for more detail). To deploy the function on Azure runtime: ---- $ az login diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java index e7376474d..aafaeeabc 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandler.java @@ -20,6 +20,7 @@ import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; import com.microsoft.azure.functions.ExecutionContext; import com.microsoft.azure.functions.OutputBinding; @@ -45,14 +46,15 @@ public class AzureSpringBootRequestHandler extends AzureSpringFunctionInit String name = null; try { if (context != null) { - context.getLogger().fine("Handler processed a request."); name = context.getFunctionName(); + context.getLogger().info("Handler processing a request for: " + name); } initialize(context); - Object convertedEvent = convertEvent(input); - Publisher output = apply(name, extract(convertedEvent)); - return result(convertedEvent, output); + Function, Publisher> function = lookup(name); + Publisher events = extract(function, convertEvent(input)); + Publisher output = function.apply(events); + return result(function, input, output); } catch (Throwable ex) { if (context != null) { @@ -68,7 +70,7 @@ public class AzureSpringBootRequestHandler extends AzureSpringFunctionInit } finally { if (context != null) { - context.getLogger().fine("Handler processed a request."); + context.getLogger().fine("Handler processed a request for: " + name); } } } @@ -83,19 +85,26 @@ public class AzureSpringBootRequestHandler extends AzureSpringFunctionInit return input; } - private Flux extract(Object input) { - if (input instanceof Collection) { - return Flux.fromIterable((Iterable) input); + private Flux extract(Function function, Object input) { + if (!isSingleInput(function, input)) { + if (input instanceof Collection) { + return Flux.fromIterable((Iterable) input); + } } return Flux.just(input); } - private O result(Object input, Publisher output) { + private O result(Function function, Object input, Publisher output) { List result = new ArrayList<>(); for (Object value : Flux.from(output).toIterable()) { result.add(convertOutput(value)); } - if (isSingleValue(input) && result.size() == 1) { + if (isSingleInput(function, input) && result.size() == 1) { + @SuppressWarnings("unchecked") + O value = (O) result.get(0); + return value; + } + if (isSingleOutput(function, input) && result.size() == 1) { @SuppressWarnings("unchecked") O value = (O) result.get(0); return value; @@ -105,10 +114,6 @@ public class AzureSpringBootRequestHandler extends AzureSpringFunctionInit return value; } - private boolean isSingleValue(Object input) { - return !(input instanceof Collection); - } - @SuppressWarnings("unchecked") protected O convertOutput(Object output) { return (O) output; diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java index 58aa1d61a..c5a5d2f96 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/main/java/org/springframework/cloud/function/adapter/azure/AzureSpringFunctionInitializer.java @@ -20,6 +20,7 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -36,6 +37,7 @@ import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.function.context.FunctionCatalog; +import org.springframework.cloud.function.context.catalog.FunctionInspector; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.util.ClassUtils; @@ -53,6 +55,9 @@ public class AzureSpringFunctionInitializer implements Closeable { @Autowired(required = false) private FunctionCatalog catalog; + @Autowired(required = false) + private FunctionInspector inspector; + private volatile static ConfigurableApplicationContext context; public AzureSpringFunctionInitializer(Class configurationClass) { @@ -68,6 +73,7 @@ public class AzureSpringFunctionInitializer implements Closeable { public void close() throws IOException { if (AzureSpringFunctionInitializer.context != null) { AzureSpringFunctionInitializer.context.close(); + AzureSpringFunctionInitializer.context = null; } } @@ -80,7 +86,7 @@ public class AzureSpringFunctionInitializer implements Closeable { return; } if (ctxt != null) { - ctxt.getLogger().info("Initializing function"); + ctxt.getLogger().info("Initializing functions"); } if (context == null) { @@ -119,13 +125,37 @@ public class AzureSpringFunctionInitializer implements Closeable { } } - protected Publisher apply(String name, Publisher input) { + protected boolean isSingleInput(Function function, Object input) { + if (!(input instanceof Collection)) { + return true; + } + if (this.inspector != null) { + return Collection.class.isAssignableFrom(inspector.getInputType(function)); + } + return ((Collection)input).size() <= 1; + } + + protected boolean isSingleOutput(Function function, Object output) { + if (!(output instanceof Collection)) { + return true; + } + if (this.inspector != null) { + return Collection.class.isAssignableFrom(inspector.getOutputType(function)); + } + return ((Collection)output).size() <= 1; + } + + protected Function, Publisher> lookup(String name) { Function, Publisher> function = this.function; - if (function == null && name != null) { - function = this.catalog.lookup(Function.class, name); + if (name != null && this.catalog != null) { + Function, Publisher> preferred = this.catalog + .lookup(Function.class, name); + if (preferred != null) { + function = preferred; + } } if (function != null) { - return function.apply(input); + return function; } throw new IllegalStateException("No function defined"); } diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandlerTests.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandlerTests.java new file mode 100644 index 000000000..8c99e664e --- /dev/null +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/AzureSpringBootRequestHandlerTests.java @@ -0,0 +1,220 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.function.adapter.azure; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import reactor.core.publisher.Flux; + +/** + * @author Dave Syer + * + */ +public class AzureSpringBootRequestHandlerTests { + + private AzureSpringBootRequestHandler handler = null; + + AzureSpringBootRequestHandler handler(Class config) { + AzureSpringBootRequestHandler handler = new AzureSpringBootRequestHandler( + config); + this.handler = handler; + return handler; + } + + @Test + public void bareConfig() { + AzureSpringBootRequestHandler handler = handler(BareConfig.class); + Bar bar = handler.handleRequest(new Foo("bar"), + new TestExecutionContext("uppercase")); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @Test + public void autoConfig() { + AzureSpringBootRequestHandler handler = handler(AutoConfig.class); + Bar bar = handler.handleRequest(new Foo("bar"), + new TestExecutionContext("uppercase")); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @Test + public void multiConfig() { + AzureSpringBootRequestHandler handler = handler(MultiConfig.class); + Bar bar = handler.handleRequest(new Foo("bar"), + new TestExecutionContext("uppercase")); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @Test + public void implicitListConfig() { + AzureSpringBootRequestHandler, List> handler = handler( + AutoConfig.class); + List bar = handler.handleRequest(Arrays.asList(new Foo("bar")), + new TestExecutionContext("uppercase")); + assertThat(bar).hasSize(1); + assertThat(bar.get(0).getValue()).isEqualTo("BAR"); + } + + @Test + public void listToListConfig() { + AzureSpringBootRequestHandler, List> handler = handler( + ListConfig.class); + List bar = handler.handleRequest( + Arrays.asList(new Foo("bar"), new Foo("baz")), + new TestExecutionContext("uppercase")); + assertThat(bar).hasSize(2); + assertThat(bar.get(0).getValue()).isEqualTo("BAR"); + } + + @Test + public void listToListSingleConfig() { + AzureSpringBootRequestHandler, List> handler = handler( + ListConfig.class); + List bar = handler.handleRequest(Arrays.asList(new Foo("bar")), + new TestExecutionContext("uppercase")); + assertThat(bar).hasSize(1); + assertThat(bar.get(0).getValue()).isEqualTo("BAR"); + } + + @Test + public void collectConfig() { + AzureSpringBootRequestHandler, Bar> handler = handler(CollectConfig.class); + Bar bar = handler.handleRequest(Arrays.asList(new Foo("bar")), + new TestExecutionContext("uppercase")); + assertThat(bar.getValue()).isEqualTo("BAR"); + } + + @After + public void close() throws IOException { + if (handler != null) + handler.close(); + } + + @Configuration + protected static class BareConfig { + @Bean + public Function, Flux> function() { + return foos -> foos.map(foo -> new Bar(foo.getValue().toUpperCase())); + } + } + + @Configuration + @EnableAutoConfiguration + protected static class AutoConfig { + @Bean + public Function uppercase() { + return foo -> new Bar(foo.getValue().toUpperCase()); + } + } + + @Configuration + @EnableAutoConfiguration + protected static class ListConfig { + @Bean + public Function, List> uppercase() { + return foos -> foos.stream().map(foo -> new Bar(foo.getValue().toUpperCase())) + .collect(Collectors.toList()); + } + } + + @Configuration + @EnableAutoConfiguration + protected static class CollectConfig { + @Bean + public Function, Bar> uppercase() { + return foos -> new Bar(foos.stream().map(foo -> foo.getValue().toUpperCase()) + .collect(Collectors.joining(","))); + } + } + + @Configuration + @EnableAutoConfiguration + protected static class MultiConfig { + @Bean + public Function uppercase() { + return foo -> new Bar(foo.getValue().toUpperCase()); + } + + @Bean + public Function lowercase() { + return bar -> new Foo(bar.getValue().toLowerCase()); + } + } + +} + +class Foo { + + private String value; + + Foo() { + } + + public String lowercase() { + return value.toLowerCase(); + } + + public Foo(String value) { + this.value = value; + } + + public String uppercase() { + return value.toUpperCase(); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} + +class Bar { + + private String value; + + Bar() { + } + + public Bar(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/TestExecutionContext.java b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/TestExecutionContext.java new file mode 100644 index 000000000..38ffd02f4 --- /dev/null +++ b/spring-cloud-function-adapters/spring-cloud-function-adapter-azure/src/test/java/org/springframework/cloud/function/adapter/azure/TestExecutionContext.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.function.adapter.azure; + +import java.util.UUID; +import java.util.logging.Logger; + +import com.microsoft.azure.functions.ExecutionContext; + +public class TestExecutionContext implements ExecutionContext { + private String name; + + public TestExecutionContext(String name) { + this.name = name; + } + + @Override + public Logger getLogger() { + return Logger.getAnonymousLogger(); + } + + @Override + public String getInvocationId() { + return UUID.randomUUID().toString(); + } + + @Override + public String getFunctionName() { + return name; + } +} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure/.gitignore b/spring-cloud-function-samples/function-sample-azure/.gitignore index 9e4ebfc83..c7f1c2e74 100644 --- a/spring-cloud-function-samples/function-sample-azure/.gitignore +++ b/spring-cloud-function-samples/function-sample-azure/.gitignore @@ -1,6 +1,4 @@ +extensions.csproj +obj/ lib/ -node/ -package-lock.json -node_modules/ -etc/ diff --git a/spring-cloud-function-samples/function-sample-azure/pom.xml b/spring-cloud-function-samples/function-sample-azure/pom.xml index 49ecfd4bb..34fe77b7b 100644 --- a/spring-cloud-function-samples/function-sample-azure/pom.xml +++ b/spring-cloud-function-samples/function-sample-azure/pom.xml @@ -24,7 +24,9 @@ function-sample-azure westus java-function-group + ${project.build.directory}/azure-functions/${functionAppName} example.Config + 1.0.11.RELEASE @@ -61,6 +63,26 @@ + + org.apache.maven.plugins + maven-clean-plugin + + + + ${basedir} + + obj/** + + + + ${basedir} + + extensions.csproj + + + + + maven-resources-plugin 3.0.2 @@ -68,7 +90,7 @@ com.microsoft.azure azure-functions-maven-plugin - 1.0.0-beta-1 + 1.0.0-beta-4 @@ -81,6 +103,26 @@ true + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${stagingDirectory}/lib + false + false + true + runtime + + + + com.microsoft.azure azure-functions-maven-plugin @@ -93,8 +135,20 @@ FUNCTIONS_EXTENSION_VERSION beta + + MSDEPLOY_RENAME_LOCKED_FILES + 1 + + + + package-functions + + package + + + maven-resources-plugin @@ -121,42 +175,17 @@ - - org.apache.maven.plugins - maven-shade-plugin - - false - true - azure - ${project.build.directory}/azure-functions/${functionAppName} - + org.springframework.boot + spring-boot-maven-plugin + + + org.springframework.boot.experimental + spring-boot-thin-layout + ${wrapper.version} + + - - - org.apache.maven.plugins - maven-assembly-plugin - - - azure - package - - single - - false - - false - - ${basedir}/src/assembly/azure.xml - - ${project.build.directory}/azure-functions - false - ${functionAppName} - - - - - diff --git a/spring-cloud-function-samples/function-sample-azure/src/assembly/azure.xml b/spring-cloud-function-samples/function-sample-azure/src/assembly/azure.xml deleted file mode 100644 index 85bb6a3a9..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/assembly/azure.xml +++ /dev/null @@ -1,20 +0,0 @@ - - azure - - zip - - - - - ${project.build.directory}/azure-functions/${functionAppName} - - - *-azure.jar - **/*.json - - - - \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json b/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json index 1d9e4b780..df147e2c2 100644 --- a/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json +++ b/spring-cloud-function-samples/function-sample-azure/src/main/azure/local.settings.json @@ -2,6 +2,7 @@ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", - "AzureWebJobsDashboard": "" + "AzureWebJobsDashboard": "", + "FUNCTIONS_WORKER_RUNTIME": "java" } } diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/azure/uppercase/function.json b/spring-cloud-function-samples/function-sample-azure/src/main/azure/uppercase/function.json deleted file mode 100644 index f679900f5..000000000 --- a/spring-cloud-function-samples/function-sample-azure/src/main/azure/uppercase/function.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "scriptFile": "../function-sample-azure-2.0.0.BUILD-SNAPSHOT-azure.jar", - "entryPoint": "example.FooHandler.execute", - "bindings": [ - { - "type": "httpTrigger", - "name": "foo", - "direction": "in", - "authLevel": "anonymous", - "methods": [ - "post" - ] - }, - { - "type": "http", - "name": "$return", - "direction": "out" - } - ], - "disabled": false -} \ No newline at end of file diff --git a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/FooHandler.java b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/FooHandler.java index 7ef5e93b0..00a076372 100644 --- a/spring-cloud-function-samples/function-sample-azure/src/main/java/example/FooHandler.java +++ b/spring-cloud-function-samples/function-sample-azure/src/main/java/example/FooHandler.java @@ -17,6 +17,10 @@ package example; import com.microsoft.azure.functions.ExecutionContext; +import com.microsoft.azure.functions.HttpMethod; +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; @@ -24,8 +28,11 @@ import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHa * @author Soby Chacko */ public class FooHandler extends AzureSpringBootRequestHandler { - - public Bar execute(Foo foo, ExecutionContext context) { + @FunctionName("uppercase") + public Bar execute( + @HttpTrigger(name = "req", methods = { HttpMethod.GET, + HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) Foo foo, + ExecutionContext context) { return handleRequest(foo, context); } diff --git a/spring-cloud-function-samples/function-sample-pojo/build.gradle b/spring-cloud-function-samples/function-sample-pojo/build.gradle index 03e4ad9ec..b7467252d 100644 --- a/spring-cloud-function-samples/function-sample-pojo/build.gradle +++ b/spring-cloud-function-samples/function-sample-pojo/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { - springBootVersion = '1.5.12.RELEASE' - wrapperVersion = '1.0.11.RELEASE' + springBootVersion = '2.0.3.RELEASE' + wrapperVersion = '1.0.13.RELEASE' } repositories { mavenLocal() diff --git a/spring-cloud-function-samples/function-sample-pojo/pom.xml b/spring-cloud-function-samples/function-sample-pojo/pom.xml index c5a16b91a..2740181af 100644 --- a/spring-cloud-function-samples/function-sample-pojo/pom.xml +++ b/spring-cloud-function-samples/function-sample-pojo/pom.xml @@ -20,7 +20,7 @@ 1.8 2.0.0.BUILD-SNAPSHOT - 1.0.11.RELEASE + 1.0.13.RELEASE