Experimental Azure function adapter for HTTP trigger
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
<modules>
|
||||
<module>spring-cloud-function-adapter-aws</module>
|
||||
<module>spring-cloud-function-adapter-openwhisk</module>
|
||||
<module>spring-cloud-function-adapter-azure</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
This work is experimental.
|
||||
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.
|
||||
|
||||
The adapter has a generic http request handler that you can use.
|
||||
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`.
|
||||
|
||||
=== 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.
|
||||
|
||||
== Build
|
||||
|
||||
----
|
||||
./mvnw -U clean package
|
||||
----
|
||||
|
||||
== Running the sample
|
||||
|
||||
Before running the sample, we need to install a custom azure maven plugin.
|
||||
Checkout this fork: https://github.com/sobychacko/azure-maven-plugins/tree/for-spring-boot-apps
|
||||
----
|
||||
cd azure-functions-maven-plugin
|
||||
mvn clean install -Dcheckstyle.skip=true -DskipTests -Dfindbugs.skip=true
|
||||
----
|
||||
|
||||
Build the sample under `spring-cloud-function-samples/function-sample-azure`.
|
||||
|
||||
----
|
||||
mvn clean package
|
||||
----
|
||||
|
||||
Running Azure function locally.
|
||||
|
||||
----
|
||||
mvn azure-functions:run
|
||||
|
||||
On another terminal try this: curl localhost:7071/api/uppercase -d '{"value": "hello foobar"}'
|
||||
----
|
||||
|
||||
Deploying the function that ran locally on Azure runtime.
|
||||
|
||||
----
|
||||
az login
|
||||
|
||||
mvn azure-functions:deploy
|
||||
|
||||
On another terminal try this: curl https://<azure-function-url-from-the-log>/api/uppercase -d '{"value": "hello foobar!"}'
|
||||
|
||||
Please ensure that you use the right URL for the function above.
|
||||
----
|
||||
|
||||
Running the function as a standalone Spring Boot app
|
||||
|
||||
Go to the samples project and uncomment `spring-cloud-function-web` dependency and `spring-boot-maven-plugin`.
|
||||
|
||||
----
|
||||
mvn clean package
|
||||
java -jar target/<spring boot uber jar>
|
||||
|
||||
On another terminal: curl -H "Content-Type: text/plain" localhost:8080/function -d '{"value": "hello foobar"}'
|
||||
----
|
||||
|
||||
The input type for the function in the Azure sample is a Foo with a single property called "value". So you would need this to test it with something as below.
|
||||
|
||||
----
|
||||
{
|
||||
"value": "foobar"
|
||||
}
|
||||
----
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-function-adapter-azure</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-function-adapter-aws</name>
|
||||
<description>Azure Function Adapter for Spring Cloud Function</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-function-adapter-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<aws-lambda-events.version>1.2.1</aws-lambda-events.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-function-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-functions-java-core</artifactId>
|
||||
<version>[1.0.0-beta-1,1.0.0)</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2017 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.microsoft.azure.serverless.functions.ExecutionContext;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Soby Chacko
|
||||
*/
|
||||
public class AzureSpringBootRequestHandler<I,O> extends AzureSpringFunctionInitializer {
|
||||
|
||||
public Object handleRequest(I foo, ExecutionContext context) {
|
||||
context.getLogger().info("Handler Java HTTP trigger processed a request.");
|
||||
initialize(context);
|
||||
|
||||
Object convertedEvent = convertEvent(foo);
|
||||
Flux<?> output = apply(extract(convertedEvent));
|
||||
return result(convertedEvent, output);
|
||||
}
|
||||
|
||||
protected Object convertEvent(I input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
private Flux<?> extract(Object input) {
|
||||
if (input instanceof Collection) {
|
||||
return Flux.fromIterable((Iterable<?>) input);
|
||||
}
|
||||
return Flux.just(input);
|
||||
}
|
||||
|
||||
private Object result(Object input, Flux<?> output) {
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (Object value : output.toIterable()) {
|
||||
result.add(value);
|
||||
}
|
||||
if (isSingleValue(input) && result.size()==1) {
|
||||
return result.get(0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isSingleValue(Object input) {
|
||||
return !(input instanceof Collection);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2017 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.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import com.microsoft.azure.serverless.functions.ExecutionContext;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.function.core.FunctionCatalog;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Soby Chacko
|
||||
*/
|
||||
public class AzureSpringFunctionInitializer implements Closeable {
|
||||
|
||||
private Function<Flux<?>, Flux<?>> function;
|
||||
|
||||
private AtomicBoolean initialized = new AtomicBoolean();
|
||||
|
||||
private Class<?> configurationClass;
|
||||
|
||||
@Autowired(required = false)
|
||||
private FunctionCatalog catalog;
|
||||
|
||||
private static ConfigurableApplicationContext context;
|
||||
|
||||
public AzureSpringFunctionInitializer(Class<?> configurationClass) {
|
||||
this.configurationClass = configurationClass;
|
||||
}
|
||||
|
||||
public AzureSpringFunctionInitializer() {
|
||||
this(getStartClass());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (AzureSpringFunctionInitializer.context != null) {
|
||||
AzureSpringFunctionInitializer.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void initialize(ExecutionContext ctxt) {
|
||||
|
||||
ConfigurableApplicationContext context = AzureSpringFunctionInitializer.context;
|
||||
|
||||
if (!this.initialized.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
ctxt.getLogger().info("Initializing function");
|
||||
|
||||
if (context==null) {
|
||||
synchronized (AzureSpringFunctionInitializer.class) {
|
||||
if (context==null) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(
|
||||
configurationClass);
|
||||
ClassUtils.overrideThreadContextClassLoader(AzureSpringFunctionInitializer.class.getClassLoader());
|
||||
|
||||
context = builder.web(false).run();
|
||||
AzureSpringFunctionInitializer.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
context.getAutowireCapableBeanFactory().autowireBean(this);
|
||||
String name = context.getEnvironment().getProperty("function.name");
|
||||
|
||||
if (name == null) {
|
||||
name = "function";
|
||||
}
|
||||
if (this.catalog == null) {
|
||||
this.function = context.getBean(name, Function.class);
|
||||
}
|
||||
else {
|
||||
Set<String> functionNames = this.catalog.getFunctionNames();
|
||||
this.function = this.catalog.lookupFunction(functionNames.iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
protected Flux<?> apply(Flux<?> input) {
|
||||
if (this.function != null) {
|
||||
return function.apply(input);
|
||||
}
|
||||
throw new IllegalStateException("No function defined");
|
||||
}
|
||||
|
||||
private static Class<?> getStartClass() {
|
||||
ClassLoader classLoader = org.springframework.cloud.function.adapter.azure.AzureSpringFunctionInitializer.class.getClassLoader();
|
||||
if (System.getenv("MAIN_CLASS") != null) {
|
||||
return ClassUtils.resolveClassName(System.getenv("MAIN_CLASS"), classLoader);
|
||||
}
|
||||
try {
|
||||
Class<?> result = getStartClass(
|
||||
Collections.list(classLoader.getResources("META-INF/MANIFEST.MF")));
|
||||
if (result == null) {
|
||||
result = getStartClass(Collections
|
||||
.list(classLoader.getResources("meta-inf/manifest.mf")));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getStartClass(List<URL> list) {
|
||||
for (URL url : list) {
|
||||
try {
|
||||
InputStream inputStream = url.openStream();
|
||||
try {
|
||||
Manifest manifest = new Manifest(inputStream);
|
||||
String startClass = manifest.getMainAttributes()
|
||||
.getValue("Main-Class");
|
||||
if (startClass != null) {
|
||||
Class<?> aClass = ClassUtils.forName(startClass,
|
||||
org.springframework.cloud.function.adapter.azure.AzureSpringFunctionInitializer.class.getClassLoader());
|
||||
SpringBootApplication declaredAnnotation = aClass.getDeclaredAnnotation(SpringBootApplication.class);
|
||||
if (declaredAnnotation != null) {
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"IsEncrypted": false,
|
||||
"Values": {
|
||||
"AzureWebJobsStorage": "",
|
||||
"AzureWebJobsDashboard": ""
|
||||
}
|
||||
}
|
||||
155
spring-cloud-function-samples/function-sample-azure/pom.xml
Normal file
155
spring-cloud-function-samples/function-sample-azure/pom.xml
Normal file
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>io.spring.sample</groupId>
|
||||
<artifactId>function-sample-azure</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Azure Java Functions</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.8.RELEASE</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<functionAppName>function-sample-azure-11262017190909</functionAppName>
|
||||
<functionAppRegion>westus</functionAppRegion>
|
||||
<start-class>example.FooConfig</start-class>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-functions-java-core</artifactId>
|
||||
<version>[1.0.0-beta-1,1.0.0)</version>
|
||||
</dependency>
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.springframework.cloud</groupId>-->
|
||||
<!--<artifactId>spring-cloud-function-web</artifactId>-->
|
||||
<!--<version>1.0.0.BUILD-SNAPSHOT</version>-->
|
||||
<!--</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-function-adapter-azure</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-functions-maven-plugin</artifactId>
|
||||
<version>0.1.7-SNAPSHOT</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-functions-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<resourceGroup>java-functions-group</resourceGroup>
|
||||
<appName>${functionAppName}</appName>
|
||||
<region>${functionAppRegion}</region>
|
||||
<appSettings>
|
||||
<property>
|
||||
<name>FUNCTIONS_EXTENSION_VERSION</name>
|
||||
<value>beta</value>
|
||||
</property>
|
||||
</appSettings>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>package-functions</id>
|
||||
<goals>
|
||||
<goal>package</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-resources</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<overwrite>true</overwrite>
|
||||
<outputDirectory>${project.build.directory}/azure-functions/${functionAppName}
|
||||
</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.basedir}</directory>
|
||||
<includes>
|
||||
<include>host.json</include>
|
||||
<include>local.settings.json</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!--<plugin>-->
|
||||
<!--<groupId>org.springframework.boot</groupId>-->
|
||||
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!--</plugin>-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<shadedClassifierName>azure</shadedClassifierName>
|
||||
<outputDirectory>${project.build.directory}/azure-functions/${functionAppName}</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2017 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 example;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@SpringBootApplication
|
||||
class FooConfig {
|
||||
|
||||
@Bean
|
||||
public Function<Foo, Bar> uppercase() {
|
||||
return value -> new Bar(value.getValue().toUpperCase());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(FooConfig.class, args);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2017 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 example;
|
||||
|
||||
import com.microsoft.azure.serverless.functions.ExecutionContext;
|
||||
|
||||
import org.springframework.cloud.function.adapter.azure.AzureSpringBootRequestHandler;
|
||||
|
||||
/**
|
||||
* @author Soby Chacko
|
||||
*/
|
||||
public class FooHandler extends AzureSpringBootRequestHandler {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Bar handleRequest(Foo foo, ExecutionContext context) {
|
||||
context.getLogger().info("Invoking entry point method");
|
||||
return (Bar)super.handleRequest(foo,context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
<module>function-sample-compiler</module>
|
||||
<module>function-sample-task</module>
|
||||
<module>function-sample-aws</module>
|
||||
<module>function-sample-azure</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
||||
Reference in New Issue
Block a user