add adapters as child module

This commit is contained in:
markfisher
2017-05-23 16:30:18 -04:00
parent 78a37ef8ad
commit 719237e9c7
17 changed files with 1071 additions and 0 deletions

View File

@@ -58,6 +58,7 @@
<module>spring-cloud-function-web</module>
<module>spring-cloud-function-samples</module>
<module>spring-cloud-function-deployer</module>
<module>spring-cloud-function-adapters</module>
</modules>
<build>

View File

@@ -0,0 +1,30 @@
<?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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-function-adapter-parent</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>spring-cloud-function-adapter-aws</module>
<module>spring-cloud-function-adapter-sample</module>
</modules>
</project>

View File

@@ -0,0 +1,111 @@
<?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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-cloud-function-adapter-aws</name>
<description>AWS Lambda Adapter for Spring Cloud Function</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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>
<reactor.version>3.0.7.RELEASE</reactor.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-context</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>${aws-lambda-events.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>

View File

@@ -0,0 +1,52 @@
/*
* 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.aws;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Date;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
/**
* @author Mark Fisher
*/
public class FunctionInvokingKinesisEventHandler extends SpringBootRequestHandler<KinesisEvent, String> {
public FunctionInvokingKinesisEventHandler(Class<?> configurationClass) {
super(configurationClass);
}
@Override
protected String convertEvent(KinesisEvent event) {
StringBuilder result = new StringBuilder();
for (KinesisEventRecord record : event.getRecords()) {
String id = record.getEventID();
String name = record.getEventName();
String source = record.getEventSource();
Date timestamp = record.getKinesis().getApproximateArrivalTimestamp();
String partitionKey = record.getKinesis().getPartitionKey();
String sequenceNumber = record.getKinesis().getSequenceNumber();
ByteBuffer data = record.getKinesis().getData();
String dataString = new String(data.array(), Charset.forName("UTF-8"));
result.append(String.format("id=%s,name=%s,source=%s,timestamp=%s,partitionKey=%s,sequenceNumber=%s,data=%s",
id, name, source, timestamp, partitionKey, sequenceNumber, dataString));
}
return result.toString();
}
}

View File

@@ -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 org.springframework.cloud.function.adapter.aws;
import com.amazonaws.services.lambda.runtime.events.S3Event;
/**
* @author Mark Fisher
*/
public class FunctionInvokingS3EventHandler extends SpringBootRequestHandler<S3Event, String> {
public FunctionInvokingS3EventHandler(Class<?> configurationClass) {
super(configurationClass);
}
@Override
protected String convertEvent(S3Event event) {
return event.toJson();
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.aws;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import reactor.core.publisher.Flux;
/**
* @author Mark Fisher
*/
public class SpringBootRequestHandler<E, O> extends SpringFunctionInitializer implements RequestHandler<E, List<O>> {
public SpringBootRequestHandler(Class<?> configurationClass) {
super(configurationClass);
}
public SpringBootRequestHandler() {
super();
}
@Override
public List<O> handleRequest(E event, Context context) {
initialize();
Object input = convertEvent(event);
Flux<?> output = apply(extract(input));
return result(output);
}
private List<O> result(Flux<?> output) {
List<Object> result = new ArrayList<>();
for (Object value : output.toIterable()) {
result.add(value);
}
return convertResult(result);
}
@SuppressWarnings("unchecked")
protected List<O> convertResult(List<Object> value) {
return (List<O>) value;
}
private Flux<?> extract(Object input) {
if (input instanceof Collection) {
return Flux.fromIterable((Iterable<?>) input);
}
return Flux.just(input);
}
protected Object convertEvent(E event) {
return event;
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.aws;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import reactor.core.publisher.Flux;
/**
* @author Dave Syer
*/
public class SpringBootStreamHandler extends SpringFunctionInitializer
implements RequestStreamHandler {
@Autowired
private ObjectMapper mapper;
public SpringBootStreamHandler() {
super();
}
public SpringBootStreamHandler(Class<?> configurationClass) {
super(configurationClass);
}
@Override
public void handleRequest(InputStream input, OutputStream output, Context context)
throws IOException {
initialize();
Object value = convertStream(input);
Flux<?> flux = apply(extract(value));
mapper.writeValue(output, result(flux));
}
private Object result(Flux<?> flux) {
List<Object> result = new ArrayList<>();
for (Object value : flux.toIterable()) {
result.add(value);
}
return result;
}
private Flux<?> extract(Object input) {
if (input instanceof Collection) {
return Flux.fromIterable((Iterable<?>) input);
}
return Flux.just(input);
}
private Object convertStream(InputStream input) {
try {
return mapper.readValue(input, getInputType());
}
catch (Exception e) {
throw new IllegalStateException("Cannot convert event", e);
}
}
}

View File

@@ -0,0 +1,191 @@
/*
* 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.aws;
import java.io.Closeable;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.jar.Manifest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.function.context.FunctionInspector;
import org.springframework.cloud.function.registry.FunctionCatalog;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.ClassUtils;
import reactor.core.publisher.Flux;
/**
* @author Dave Syer
*/
public class SpringFunctionInitializer implements Closeable {
private static Log logger = LogFactory.getLog(SpringFunctionInitializer.class);
private final Class<?> configurationClass;
private Function<Flux<?>, Flux<?>> function;
private Consumer<Flux<?>> consumer;
private Supplier<Flux<?>> supplier;
private AtomicBoolean initialized = new AtomicBoolean();
@Autowired(required = false)
private FunctionInspector inspector;
@Autowired(required = false)
private FunctionCatalog catalog;
private String name;
private ConfigurableApplicationContext context;
public SpringFunctionInitializer(Class<?> configurationClass) {
this.configurationClass = configurationClass;
}
public SpringFunctionInitializer() {
this(getStartClass());
}
@Override
public void close() {
if (this.context != null) {
this.context.close();
}
}
@SuppressWarnings("unchecked")
protected void initialize() {
if (!this.initialized.compareAndSet(false, true)) {
return;
}
logger.info("Initializing: " + configurationClass);
SpringApplicationBuilder builder = new SpringApplicationBuilder(
configurationClass);
ConfigurableApplicationContext context = builder.web(false).run();
context.getAutowireCapableBeanFactory().autowireBean(this);
String name = context.getEnvironment().getProperty("function.name");
boolean defaultName = false;
if (name == null) {
name = "function";
defaultName = true;
}
if (this.catalog == null) {
this.function = context.getBean(name, Function.class);
}
else {
this.function = this.catalog.lookupFunction(name);
this.name = name;
if (this.function == null) {
if (defaultName) {
name = "consumer";
}
this.consumer = this.catalog.lookupConsumer(name);
this.name = name;
if (this.consumer == null) {
if (defaultName) {
name = "supplier";
}
this.supplier = this.catalog.lookupSupplier(name);
this.name = name;
}
}
}
this.context = context;
}
protected Class<?> getInputType() {
if (inspector != null) {
return inspector.getInputType(this.name);
}
return Object.class;
}
protected Flux<?> apply(Flux<?> input) {
if (this.function != null) {
return function.apply(input);
}
if (this.consumer != null) {
this.consumer.accept(input);
return Flux.empty();
}
if (this.supplier != null) {
return this.supplier.get();
}
throw new IllegalStateException("No function defined");
}
private static Class<?> getStartClass() {
ClassLoader classLoader = SpringFunctionInitializer.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")));
}
logger.info("Main class: " + result);
return result;
}
catch (Exception ex) {
logger.error("Failed to find main class", ex);
return null;
}
}
private static Class<?> getStartClass(List<URL> list) {
logger.info("Searching manifests: " + list);
for (URL url : list) {
try {
logger.info("Searching manifest: " + url);
InputStream inputStream = url.openStream();
try {
Manifest manifest = new Manifest(inputStream);
String startClass = manifest.getMainAttributes()
.getValue("Start-Class");
if (startClass != null) {
return ClassUtils.forName(startClass,
SpringFunctionInitializer.class.getClassLoader());
}
}
finally {
inputStream.close();
}
}
catch (Exception ex) {
}
}
return null;
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright 2016-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.aws;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.junit.After;
import org.junit.Test;
import org.springframework.cloud.function.context.ContextFunctionCatalogAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import static org.assertj.core.api.Assertions.assertThat;
import reactor.core.publisher.Flux;
/**
* @author Dave Syer
*
*/
public class SpringFunctionInitializerTests {
private SpringFunctionInitializer initializer;
@After
public void after() {
System.clearProperty("function.name");
if (initializer!=null) {
initializer.close();
}
}
@Test
public void functionBean() {
initializer = new SpringFunctionInitializer(
FluxFunctionConfig.class);
initializer.initialize();
Flux<?> result = initializer.apply(Flux.just(new Foo()));
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Test
public void functionCatalog() {
initializer = new SpringFunctionInitializer(
FunctionConfig.class);
initializer.initialize();
Flux<?> result = initializer.apply(Flux.just(new Foo()));
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Test
public void namedFunctionCatalog() {
initializer = new SpringFunctionInitializer(
NamedFunctionConfig.class);
System.setProperty("function.name", "other");
initializer.initialize();
Flux<?> result = initializer.apply(Flux.just(new Foo()));
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Test
public void consumerCatalog() {
initializer = new SpringFunctionInitializer(
ConsumerConfig.class);
initializer.initialize();
Flux<?> result = initializer.apply(Flux.just(new Foo()));
assertThat(result.toStream().collect(Collectors.toList())).isEmpty();
}
@Test
public void supplierCatalog() {
initializer = new SpringFunctionInitializer(
SupplierConfig.class);
initializer.initialize();
Flux<?> result = initializer.apply(Flux.empty());
assertThat(result.blockFirst()).isInstanceOf(Bar.class);
}
@Configuration
protected static class FluxFunctionConfig {
@Bean
public Function<Flux<Foo>, Flux<Bar>> function() {
return flux -> flux.map(foo -> new Bar());
}
}
@Configuration
@Import(ContextFunctionCatalogAutoConfiguration.class)
protected static class FunctionConfig {
@Bean
public Function<Foo, Bar> function() {
return foo -> new Bar();
}
}
@Configuration
@Import(ContextFunctionCatalogAutoConfiguration.class)
protected static class NamedFunctionConfig {
@Bean
public Function<Foo, Bar> other() {
return foo -> new Bar();
}
}
@Configuration
@Import(ContextFunctionCatalogAutoConfiguration.class)
protected static class SupplierConfig {
@Bean
public Supplier<Bar> supplier() {
return () -> new Bar();
}
}
@Configuration
@Import(ContextFunctionCatalogAutoConfiguration.class)
protected static class ConsumerConfig {
@Bean
public Consumer<Foo> consumer() {
return foo -> {
};
}
}
protected static class Foo {
}
protected static class Bar {
}
}

View File

@@ -0,0 +1,146 @@
<?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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-sample</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-cloud-function-adapter-sample</name>
<description>Spring Cloud Function Sample</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<wrapper.version>1.0.3.BUILD-SNAPSHOT</wrapper.version>
<aws-lambda-events.version>1.2.1</aws-lambda-events.version>
<reactor.version>3.0.7.RELEASE</reactor.version>
<spring-cloud-function.version>1.0.0.BUILD-SNAPSHOT</spring-cloud-function.version>
<start-class>example.Config</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-aws</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>${aws-lambda-events.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<version>${spring-cloud-function.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${wrapper.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>aws</shadedClassifierName>
</configuration>
</plugin>
</plugins>
</build>
<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>

View File

@@ -0,0 +1,97 @@
/*
* 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.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableConfigurationProperties(Properties.class)
public class Config {
private Properties props;
@Autowired
public Config(Properties props) {
this.props = props;
}
@Bean
public Function<Foo, Bar> function() {
return value -> new Bar(value.uppercase()
+ (props.getFoo() != null ? "-" + props.getFoo() : ""));
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Config.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;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2016-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 org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler;
/**
* @author Dave Syer
*
*/
public class Handler extends SpringBootRequestHandler<Foo, Bar> {
}

View File

@@ -0,0 +1,33 @@
/*
* 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 org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("app")
public class Properties {
public String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}

View File

@@ -0,0 +1 @@
dependencies.spring-cloud-function-web: org.springframework.cloud:spring-cloud-function-web

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2016-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 org.junit.Test;
import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
*
*/
public class MapTests {
@Test
public void test() {
Bar result = new Config(new Properties()).function().apply(new Foo("foo"));
assertThat(result.getValue()).isEqualTo("FOO");
}
@Test
public void start() throws Exception {
SpringBootRequestHandler<Object, Object> handler = new SpringBootRequestHandler<>(Config.class);
handler.handleRequest(new Foo("foo"), null);
handler.close();
}
}