Experimental Azure function adapter for HTTP trigger
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>spring-cloud-function-adapter-aws</module>
|
<module>spring-cloud-function-adapter-aws</module>
|
||||||
<module>spring-cloud-function-adapter-openwhisk</module>
|
<module>spring-cloud-function-adapter-openwhisk</module>
|
||||||
|
<module>spring-cloud-function-adapter-azure</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</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-compiler</module>
|
||||||
<module>function-sample-task</module>
|
<module>function-sample-task</module>
|
||||||
<module>function-sample-aws</module>
|
<module>function-sample-aws</module>
|
||||||
|
<module>function-sample-azure</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
Reference in New Issue
Block a user