Turned on checkstyle
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -22,9 +22,7 @@ import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
* @since 2.0.1
|
||||
*
|
||||
*/
|
||||
@@ -33,12 +31,14 @@ public abstract class AbstractFunctionRegistry implements FunctionRegistry {
|
||||
@Autowired
|
||||
private Environment environment = new StandardEnvironment();
|
||||
|
||||
|
||||
public <T> T lookup(Class<?> type, String name) {
|
||||
String functionDefinitionName = !StringUtils.hasText(name) && environment.containsProperty("spring.cloud.function.definition")
|
||||
? environment.getProperty("spring.cloud.function.definition") : name;
|
||||
String functionDefinitionName = !StringUtils.hasText(name)
|
||||
&& this.environment.containsProperty("spring.cloud.function.definition")
|
||||
? this.environment.getProperty("spring.cloud.function.definition")
|
||||
: name;
|
||||
return this.doLookup(type, functionDefinitionName);
|
||||
}
|
||||
|
||||
protected abstract <T> T doLookup(Class<?> type, String name);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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
|
||||
* 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,
|
||||
@@ -25,20 +25,20 @@ import java.util.Set;
|
||||
public interface FunctionCatalog {
|
||||
|
||||
/**
|
||||
* Will look up the instance of the functional interface by name only
|
||||
*
|
||||
* Will look up the instance of the functional interface by name only.
|
||||
* @param <T> instance type
|
||||
* @param name the name of the functional interface. Must not be null;
|
||||
* @return instance of the functional interface registered with this catalog
|
||||
*/
|
||||
default public <T> T lookup(String name) {
|
||||
default <T> T lookup(String name) {
|
||||
return this.lookup(null, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will look up the instance of the functional interface by name and type
|
||||
* which can only be Supplier, Consumer or Function. If type is not provided, the lookup
|
||||
* will be made based on name only
|
||||
*
|
||||
* Will look up the instance of the functional interface by name and type which can
|
||||
* only be Supplier, Consumer or Function. If type is not provided, the lookup will be
|
||||
* made based on name only.
|
||||
* @param <T> instance type
|
||||
* @param type the type of functional interface. Can be null
|
||||
* @param name the name of the functional interface. Must not be null;
|
||||
* @return instance of the functional interface registered with this catalog
|
||||
@@ -48,11 +48,12 @@ public interface FunctionCatalog {
|
||||
Set<String> getNames(Class<?> type);
|
||||
|
||||
/**
|
||||
* Return the count of functions registered in this catalog
|
||||
* Return the count of functions registered in this catalog.
|
||||
* @return the count of functions registered in this catalog
|
||||
*/
|
||||
default int size() {
|
||||
throw new UnsupportedOperationException("This instance of FunctionCatalog does not support this operation");
|
||||
throw new UnsupportedOperationException(
|
||||
"This instance of FunctionCatalog does not support this operation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -27,6 +27,9 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.cloud.function.core.FluxConsumer;
|
||||
import org.springframework.cloud.function.core.FluxFunction;
|
||||
@@ -34,26 +37,23 @@ import org.springframework.cloud.function.core.FluxSupplier;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @param <T> target type
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class FunctionRegistration<T> implements BeanNameAware {
|
||||
|
||||
private T target;
|
||||
|
||||
private final Set<String> names = new LinkedHashSet<>();
|
||||
|
||||
private final Map<String, String> properties = new LinkedHashMap<>();
|
||||
|
||||
private T target;
|
||||
|
||||
private FunctionType type;
|
||||
|
||||
/**
|
||||
* Creates instance of FunctionRegistration.
|
||||
*
|
||||
* @param target instance of {@link Supplier}, {@link Function} or {@link Consumer}
|
||||
* @param names additional set of names for this registration. Additional names can be
|
||||
* provided {@link #name(String)} or {@link #names(String...)} operations.
|
||||
@@ -65,15 +65,11 @@ public class FunctionRegistration<T> implements BeanNameAware {
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public Set<String> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public FunctionType getType() {
|
||||
return type;
|
||||
return this.names;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,15 +77,19 @@ public class FunctionRegistration<T> implements BeanNameAware {
|
||||
* want to add a name or set or names to the existing set of names use
|
||||
* {@link #names(Collection)} or {@link #name(String)} or {@link #names(String...)}
|
||||
* operations.
|
||||
* @param names
|
||||
* @param names - bean names
|
||||
*/
|
||||
public void setNames(Set<String> names) {
|
||||
this.names.clear();
|
||||
this.names.addAll(names);
|
||||
}
|
||||
|
||||
public FunctionType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public T getTarget() {
|
||||
return target;
|
||||
return this.target;
|
||||
}
|
||||
|
||||
public FunctionRegistration<T> properties(Map<String, String> properties) {
|
||||
@@ -133,7 +133,7 @@ public class FunctionRegistration<T> implements BeanNameAware {
|
||||
}
|
||||
|
||||
public <S> FunctionRegistration<S> wrap() {
|
||||
if (type == null || type.isWrapper()) {
|
||||
if (this.type == null || this.type.isWrapper()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
FunctionRegistration<S> value = (FunctionRegistration<S>) this;
|
||||
return value;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
@@ -23,18 +24,21 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class FunctionType {
|
||||
|
||||
/**
|
||||
* Unclassified function types.
|
||||
*/
|
||||
public static FunctionType UNCLASSIFIED = new FunctionType(ResolvableType
|
||||
.forClassWithGenerics(Function.class, Object.class, Object.class).getType());
|
||||
|
||||
@@ -61,34 +65,6 @@ public class FunctionType {
|
||||
this.message = messageType();
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Class<?> getInputWrapper() {
|
||||
return inputWrapper;
|
||||
}
|
||||
|
||||
public Class<?> getOutputWrapper() {
|
||||
return outputWrapper;
|
||||
}
|
||||
|
||||
public Class<?> getInputType() {
|
||||
return inputType;
|
||||
}
|
||||
|
||||
public Class<?> getOutputType() {
|
||||
return outputType;
|
||||
}
|
||||
|
||||
public boolean isMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public boolean isWrapper() {
|
||||
return isWrapper(getInputWrapper()) || isWrapper(getOutputWrapper());
|
||||
}
|
||||
|
||||
public static boolean isWrapper(Type type) {
|
||||
if (type instanceof ParameterizedType) {
|
||||
type = ((ParameterizedType) type).getRawType();
|
||||
@@ -125,6 +101,91 @@ public class FunctionType {
|
||||
ResolvableType.forClassWithGenerics(Consumer.class, input).getType());
|
||||
}
|
||||
|
||||
public static FunctionType compose(FunctionType input, FunctionType output) {
|
||||
ResolvableType inputGeneric = input(input);
|
||||
ResolvableType outputGeneric = output(output);
|
||||
if (!isWrapper(outputGeneric.getType())) {
|
||||
ResolvableType inputOutput = output(input);
|
||||
if (isWrapper(inputOutput.getType())) {
|
||||
outputGeneric = wrap(input,
|
||||
extractClass(inputOutput.getType(), ParamType.OUTPUT_WRAPPER),
|
||||
extractClass(outputGeneric.getType(), ParamType.OUTPUT));
|
||||
}
|
||||
}
|
||||
return new FunctionType(ResolvableType
|
||||
.forClassWithGenerics(Function.class, inputGeneric, outputGeneric)
|
||||
.getType());
|
||||
}
|
||||
|
||||
private static ResolvableType wrap(FunctionType input, Class<?> wrapper,
|
||||
Class<?> type) {
|
||||
return input.isMessage() ? wrap(wrapper, message(type))
|
||||
: ResolvableType.forClassWithGenerics(wrapper, type);
|
||||
}
|
||||
|
||||
private static ResolvableType wrap(Class<?> wrapper, ResolvableType type) {
|
||||
return ResolvableType.forClassWithGenerics(wrapper, type);
|
||||
}
|
||||
|
||||
private static ResolvableType message(Class<?> type) {
|
||||
return ResolvableType.forClassWithGenerics(Message.class, type);
|
||||
}
|
||||
|
||||
private static ResolvableType input(FunctionType type) {
|
||||
return type.input(type.getInputType());
|
||||
}
|
||||
|
||||
private static ResolvableType output(FunctionType type) {
|
||||
return type.output(type.getOutputType());
|
||||
}
|
||||
|
||||
private static Class<?> extractClass(Type param, ParamType paramType) {
|
||||
if (param instanceof ParameterizedType) {
|
||||
ParameterizedType concrete = (ParameterizedType) param;
|
||||
param = concrete.getRawType();
|
||||
}
|
||||
if (param == null) {
|
||||
// Last ditch attempt to guess: Flux<String>
|
||||
if (paramType.isWrapper()) {
|
||||
param = Flux.class;
|
||||
}
|
||||
else {
|
||||
param = String.class;
|
||||
}
|
||||
}
|
||||
Class<?> result = param instanceof Class ? (Class<?>) param : null;
|
||||
// TODO: cache result
|
||||
return result;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Class<?> getInputWrapper() {
|
||||
return this.inputWrapper;
|
||||
}
|
||||
|
||||
public Class<?> getOutputWrapper() {
|
||||
return this.outputWrapper;
|
||||
}
|
||||
|
||||
public Class<?> getInputType() {
|
||||
return this.inputType;
|
||||
}
|
||||
|
||||
public Class<?> getOutputType() {
|
||||
return this.outputType;
|
||||
}
|
||||
|
||||
public boolean isMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public boolean isWrapper() {
|
||||
return isWrapper(getInputWrapper()) || isWrapper(getOutputWrapper());
|
||||
}
|
||||
|
||||
public FunctionType to(Class<?> output) {
|
||||
ResolvableType inputGeneric = input(this);
|
||||
ResolvableType outputGeneric = output(output);
|
||||
@@ -173,73 +234,69 @@ public class FunctionType {
|
||||
return wrap(wrapper, wrapper);
|
||||
}
|
||||
|
||||
public static FunctionType compose(FunctionType input, FunctionType output) {
|
||||
ResolvableType inputGeneric = input(input);
|
||||
ResolvableType outputGeneric = output(output);
|
||||
if (!isWrapper(outputGeneric.getType())) {
|
||||
ResolvableType inputOutput = output(input);
|
||||
if (isWrapper(inputOutput.getType())) {
|
||||
outputGeneric = wrap(input,
|
||||
extractClass(inputOutput.getType(), ParamType.OUTPUT_WRAPPER),
|
||||
extractClass(outputGeneric.getType(), ParamType.OUTPUT));
|
||||
}
|
||||
}
|
||||
return new FunctionType(ResolvableType
|
||||
.forClassWithGenerics(Function.class, inputGeneric, outputGeneric)
|
||||
.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((inputType == null) ? 0 : inputType.toString().hashCode());
|
||||
+ ((this.inputType == null) ? 0 : this.inputType.toString().hashCode());
|
||||
result = prime * result + ((this.inputWrapper == null) ? 0
|
||||
: this.inputWrapper.toString().hashCode());
|
||||
result = prime * result + (this.message ? 1231 : 1237);
|
||||
result = prime * result
|
||||
+ ((inputWrapper == null) ? 0 : inputWrapper.toString().hashCode());
|
||||
result = prime * result + (message ? 1231 : 1237);
|
||||
result = prime * result
|
||||
+ ((outputType == null) ? 0 : outputType.toString().hashCode());
|
||||
result = prime * result
|
||||
+ ((outputWrapper == null) ? 0 : outputWrapper.toString().hashCode());
|
||||
+ ((this.outputType == null) ? 0 : this.outputType.toString().hashCode());
|
||||
result = prime * result + ((this.outputWrapper == null) ? 0
|
||||
: this.outputWrapper.toString().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
if (this == obj) {
|
||||
return true;
|
||||
if (obj == null)
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
FunctionType other = (FunctionType) obj;
|
||||
if (inputType == null) {
|
||||
if (other.inputType != null)
|
||||
if (this.inputType == null) {
|
||||
if (other.inputType != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!inputType.toString().equals(other.inputType.toString()))
|
||||
else if (!this.inputType.toString().equals(other.inputType.toString())) {
|
||||
return false;
|
||||
if (inputWrapper == null) {
|
||||
if (other.inputWrapper != null)
|
||||
}
|
||||
if (this.inputWrapper == null) {
|
||||
if (other.inputWrapper != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!inputWrapper.toString().equals(other.inputWrapper.toString()))
|
||||
else if (!this.inputWrapper.toString().equals(other.inputWrapper.toString())) {
|
||||
return false;
|
||||
if (message != other.message)
|
||||
}
|
||||
if (this.message != other.message) {
|
||||
return false;
|
||||
if (outputType == null) {
|
||||
if (other.outputType != null)
|
||||
}
|
||||
if (this.outputType == null) {
|
||||
if (other.outputType != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!outputType.toString().equals(other.outputType.toString()))
|
||||
else if (!this.outputType.toString().equals(other.outputType.toString())) {
|
||||
return false;
|
||||
if (outputWrapper == null) {
|
||||
if (other.outputWrapper != null)
|
||||
}
|
||||
if (this.outputWrapper == null) {
|
||||
if (other.outputWrapper != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!outputWrapper.toString().equals(other.outputWrapper.toString()))
|
||||
else if (!this.outputWrapper.toString().equals(other.outputWrapper.toString())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -247,28 +304,6 @@ public class FunctionType {
|
||||
return wrap(this, wrapper, type);
|
||||
}
|
||||
|
||||
private static ResolvableType wrap(FunctionType input, Class<?> wrapper,
|
||||
Class<?> type) {
|
||||
return input.isMessage() ? wrap(wrapper, message(type))
|
||||
: ResolvableType.forClassWithGenerics(wrapper, type);
|
||||
}
|
||||
|
||||
private static ResolvableType wrap(Class<?> wrapper, ResolvableType type) {
|
||||
return ResolvableType.forClassWithGenerics(wrapper, type);
|
||||
}
|
||||
|
||||
private static ResolvableType message(Class<?> type) {
|
||||
return ResolvableType.forClassWithGenerics(Message.class, type);
|
||||
}
|
||||
|
||||
private static ResolvableType input(FunctionType type) {
|
||||
return type.input(type.getInputType());
|
||||
}
|
||||
|
||||
private static ResolvableType output(FunctionType type) {
|
||||
return type.output(type.getOutputType());
|
||||
}
|
||||
|
||||
private ResolvableType output(Class<?> type) {
|
||||
ResolvableType generic;
|
||||
ResolvableType raw = ResolvableType.forClass(type);
|
||||
@@ -331,25 +366,6 @@ public class FunctionType {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
private static Class<?> extractClass(Type param, ParamType paramType) {
|
||||
if (param instanceof ParameterizedType) {
|
||||
ParameterizedType concrete = (ParameterizedType) param;
|
||||
param = concrete.getRawType();
|
||||
}
|
||||
if (param == null) {
|
||||
// Last ditch attempt to guess: Flux<String>
|
||||
if (paramType.isWrapper()) {
|
||||
param = Flux.class;
|
||||
}
|
||||
else {
|
||||
param = String.class;
|
||||
}
|
||||
}
|
||||
Class<?> result = param instanceof Class ? (Class<?>) param : null;
|
||||
// TODO: cache result
|
||||
return result;
|
||||
}
|
||||
|
||||
private Type extractType(Type type, ParamType paramType, int index) {
|
||||
Type param;
|
||||
if (type instanceof ParameterizedType) {
|
||||
@@ -442,6 +458,7 @@ public class FunctionType {
|
||||
}
|
||||
|
||||
enum ParamType {
|
||||
|
||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
||||
|
||||
public boolean isOutput() {
|
||||
@@ -460,6 +477,7 @@ public class FunctionType {
|
||||
public boolean isInnerWrapper() {
|
||||
return this == OUTPUT_INNER_WRAPPER || this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -39,11 +40,6 @@ import org.springframework.util.ClassUtils;
|
||||
public class FunctionalSpringApplication
|
||||
extends org.springframework.boot.SpringApplication {
|
||||
|
||||
/**
|
||||
* Name of default property source.
|
||||
*/
|
||||
private static final String DEFAULT_PROPERTIES = "defaultProperties";
|
||||
|
||||
/**
|
||||
* Flag to say that context is functional beans.
|
||||
*/
|
||||
@@ -54,6 +50,23 @@ public class FunctionalSpringApplication
|
||||
*/
|
||||
public static final String SPRING_WEB_APPLICATION_TYPE = "spring.main.web-application-type";
|
||||
|
||||
/**
|
||||
* Name of default property source.
|
||||
*/
|
||||
private static final String DEFAULT_PROPERTIES = "defaultProperties";
|
||||
|
||||
public FunctionalSpringApplication(Class<?>... primarySources) {
|
||||
super(primarySources);
|
||||
setApplicationContextClass(GenericApplicationContext.class);
|
||||
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler",
|
||||
null)) {
|
||||
setWebApplicationType(WebApplicationType.REACTIVE);
|
||||
}
|
||||
else {
|
||||
setWebApplicationType(WebApplicationType.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
FunctionalSpringApplication.run(new Class<?>[0], args);
|
||||
}
|
||||
@@ -68,18 +81,6 @@ public class FunctionalSpringApplication
|
||||
return new FunctionalSpringApplication(primarySources).run(args);
|
||||
}
|
||||
|
||||
public FunctionalSpringApplication(Class<?>... primarySources) {
|
||||
super(primarySources);
|
||||
setApplicationContextClass(GenericApplicationContext.class);
|
||||
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler",
|
||||
null)) {
|
||||
setWebApplicationType(WebApplicationType.REACTIVE);
|
||||
}
|
||||
else {
|
||||
setWebApplicationType(WebApplicationType.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
|
||||
super.postProcessApplicationContext(context);
|
||||
@@ -108,7 +109,7 @@ public class FunctionalSpringApplication
|
||||
handler = BeanUtils.instantiateClass(type);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ApplicationContextInitializer<GenericApplicationContext> initializer = (ApplicationContextInitializer<GenericApplicationContext>) handler;
|
||||
ApplicationContextInitializer initializer = (ApplicationContextInitializer) handler;
|
||||
initializer.initialize(generic);
|
||||
functional = true;
|
||||
}
|
||||
@@ -118,8 +119,9 @@ public class FunctionalSpringApplication
|
||||
Class<?> functionType = type;
|
||||
Object function = handler;
|
||||
generic.registerBean("function", FunctionRegistration.class,
|
||||
() -> new FunctionRegistration<>(handler(generic, function, functionType))
|
||||
.type(FunctionType.of(functionType)));
|
||||
() -> new FunctionRegistration<>(
|
||||
handler(generic, function, functionType))
|
||||
.type(FunctionType.of(functionType)));
|
||||
functional = true;
|
||||
}
|
||||
}
|
||||
@@ -130,7 +132,8 @@ public class FunctionalSpringApplication
|
||||
}
|
||||
}
|
||||
|
||||
private Object handler(GenericApplicationContext generic, Object handler, Class<?> type) {
|
||||
private Object handler(GenericApplicationContext generic, Object handler,
|
||||
Class<?> type) {
|
||||
if (handler == null) {
|
||||
handler = generic.getAutowireCapableBeanFactory().createBean(type);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context.catalog;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context.catalog;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -26,6 +27,7 @@ import java.util.Set;
|
||||
public class FunctionRegistrationEvent extends FunctionCatalogEvent {
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private final Set<String> names;
|
||||
|
||||
public FunctionRegistrationEvent(Object source, Class<?> type, Set<String> names) {
|
||||
@@ -35,11 +37,11 @@ public class FunctionRegistrationEvent extends FunctionCatalogEvent {
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Set<String> getNames() {
|
||||
return names;
|
||||
return this.names;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context.catalog;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -26,6 +27,7 @@ import java.util.Set;
|
||||
public class FunctionUnregistrationEvent extends FunctionCatalogEvent {
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private final Set<String> names;
|
||||
|
||||
public FunctionUnregistrationEvent(Object source, Class<?> type, Set<String> names) {
|
||||
@@ -35,11 +37,11 @@ public class FunctionUnregistrationEvent extends FunctionCatalogEvent {
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Set<String> getNames() {
|
||||
return names;
|
||||
return this.names;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
* Copyright 2012-2019 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
|
||||
* 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,
|
||||
@@ -81,16 +81,17 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
FunctionRegistrationEvent event = new FunctionRegistrationEvent(this, type,
|
||||
registration.getNames());
|
||||
|
||||
registrations.put(registration.getTarget(), registration);
|
||||
this.registrations.put(registration.getTarget(), registration);
|
||||
FunctionRegistration<T> wrapped = registration.wrap();
|
||||
if (wrapped != registration) {
|
||||
registration = wrapped;
|
||||
registrations.put(wrapped.getTarget(), wrapped);
|
||||
this.registrations.put(wrapped.getTarget(), wrapped);
|
||||
if (type == Consumer.class) {
|
||||
type = Function.class;
|
||||
}
|
||||
}
|
||||
Map<String, Object> map = functions.computeIfAbsent(type, key -> new HashMap<>());
|
||||
Map<String, Object> map = this.functions.computeIfAbsent(type,
|
||||
key -> new HashMap<>());
|
||||
for (String name : registration.getNames()) {
|
||||
map.put(name, registration.getTarget());
|
||||
}
|
||||
@@ -104,19 +105,19 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (publisher != null && !functions.isEmpty()) {
|
||||
functions.keySet()
|
||||
if (this.publisher != null && !this.functions.isEmpty()) {
|
||||
this.functions.keySet()
|
||||
.forEach(type -> this.publishEvent(new FunctionRegistrationEvent(this,
|
||||
type, functions.get(type).keySet())));
|
||||
type, this.functions.get(type).keySet())));
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (publisher != null && !functions.isEmpty()) {
|
||||
functions.keySet().forEach(
|
||||
if (this.publisher != null && !this.functions.isEmpty()) {
|
||||
this.functions.keySet().forEach(
|
||||
type -> this.publishEvent(new FunctionUnregistrationEvent(this, type,
|
||||
functions.get(type).keySet())));
|
||||
this.functions.get(type).keySet())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +126,7 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
public <T> T doLookup(Class<?> type, String name) {
|
||||
T function = null;
|
||||
if (type == null) {
|
||||
function = (T) functions.values().stream()
|
||||
function = (T) this.functions.values().stream()
|
||||
.filter(map -> map.get(name) != null).map(map -> map.get(name))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
@@ -138,7 +139,7 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
@Override
|
||||
public Set<String> getNames(Class<?> type) {
|
||||
if (type == null) {
|
||||
return functions.values().stream().flatMap(map -> map.keySet().stream())
|
||||
return this.functions.values().stream().flatMap(map -> map.keySet().stream())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
Map<String, Object> map = this.extractTypeMap(type);
|
||||
@@ -146,10 +147,10 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
}
|
||||
|
||||
private Map<String, Object> extractTypeMap(Class<?> type) {
|
||||
return functions.keySet().stream()
|
||||
return this.functions.keySet().stream()
|
||||
.filter(key -> key != Object.class && key.isAssignableFrom(type))
|
||||
.map(key -> functions.get(key)).findFirst()
|
||||
.orElse(functions.get(Object.class));
|
||||
.map(key -> this.functions.get(key)).findFirst()
|
||||
.orElse(this.functions.get(Object.class));
|
||||
}
|
||||
|
||||
private void publishEvent(Object event) {
|
||||
@@ -157,4 +158,5 @@ public class InMemoryFunctionCatalog extends AbstractFunctionRegistry
|
||||
this.publisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
* Copyright 2012-2019 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
|
||||
* 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,
|
||||
@@ -32,6 +32,11 @@ import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -62,22 +67,16 @@ import org.springframework.cloud.function.json.JacksonMapper;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.type.StandardMethodMetadata;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
@@ -86,8 +85,10 @@ import reactor.core.publisher.Mono;
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(FunctionCatalog.class)
|
||||
@ComponentScan(basePackages = "${spring.cloud.function.scan.packages:functions}",
|
||||
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Supplier.class, Function.class, Consumer.class}))
|
||||
// @checkstyle:off
|
||||
@ComponentScan(basePackages = "${spring.cloud.function.scan.packages:functions}", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
|
||||
Supplier.class, Function.class, Consumer.class }))
|
||||
// @checkstyle:on
|
||||
public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
|
||||
@@ -104,11 +105,10 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
@Autowired(required = false)
|
||||
private Map<String, FunctionRegistration<?>> registrations = Collections.emptyMap();
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public FunctionRegistry functionCatalog(ContextFunctionRegistry processor) {
|
||||
processor.merge(registrations, consumers, suppliers, functions);
|
||||
processor.merge(this.registrations, this.consumers, this.suppliers,
|
||||
this.functions);
|
||||
return new BeanFactoryFunctionCatalog(processor);
|
||||
}
|
||||
|
||||
@@ -121,11 +121,15 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
private final ContextFunctionRegistry processor;
|
||||
|
||||
public BeanFactoryFunctionCatalog(ContextFunctionRegistry processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void register(FunctionRegistration<T> registration) {
|
||||
Assert.notEmpty(registration.getNames(),
|
||||
"'registration' must contain at least one name before it is registered in catalog.");
|
||||
processor.register(registration);
|
||||
this.processor.register(registration);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,22 +137,22 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
protected <T> T doLookup(Class<?> type, String name) {
|
||||
T function = null;
|
||||
if (type == null) {
|
||||
function = (T) processor.lookupFunction(name);
|
||||
function = (T) this.processor.lookupFunction(name);
|
||||
if (function == null) {
|
||||
function = (T) processor.lookupConsumer(name);
|
||||
function = (T) this.processor.lookupConsumer(name);
|
||||
}
|
||||
if (function == null) {
|
||||
function = (T) processor.lookupSupplier(name);
|
||||
function = (T) this.processor.lookupSupplier(name);
|
||||
}
|
||||
}
|
||||
else if (Supplier.class.isAssignableFrom(type)) {
|
||||
function = (T) processor.lookupSupplier(name);
|
||||
function = (T) this.processor.lookupSupplier(name);
|
||||
}
|
||||
else if (Consumer.class.isAssignableFrom(type)) {
|
||||
function = (T) processor.lookupConsumer(name);
|
||||
function = (T) this.processor.lookupConsumer(name);
|
||||
}
|
||||
else if (Function.class.isAssignableFrom(type)) {
|
||||
function = (T) processor.lookupFunction(name);
|
||||
function = (T) this.processor.lookupFunction(name);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
@@ -174,26 +178,6 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
+ this.processor.getConsumers().size();
|
||||
}
|
||||
|
||||
public BeanFactoryFunctionCatalog(ContextFunctionRegistry processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected class BeanFactoryFunctionInspector implements FunctionInspector {
|
||||
|
||||
private ContextFunctionRegistry processor;
|
||||
|
||||
public BeanFactoryFunctionInspector(ContextFunctionRegistry processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionRegistration<?> getRegistration(Object function) {
|
||||
FunctionRegistration<?> registration = processor.getRegistration(function);
|
||||
return registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -201,21 +185,27 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
@ConditionalOnBean(Gson.class)
|
||||
@Conditional(PreferGsonOrMissingJacksonCondition.class)
|
||||
protected static class GsonConfiguration {
|
||||
|
||||
@Bean
|
||||
public GsonMapper jsonMapper(Gson gson) {
|
||||
return new GsonMapper(gson);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(ObjectMapper.class)
|
||||
@ConditionalOnBean(ObjectMapper.class)
|
||||
// @checkstyle:off
|
||||
@ConditionalOnProperty(name = ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true)
|
||||
// @checkstyle:on
|
||||
protected static class JacksonConfiguration {
|
||||
|
||||
@Bean
|
||||
public JacksonMapper jsonMapper(ObjectMapper mapper) {
|
||||
return new JacksonMapper(mapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
@@ -242,10 +232,10 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
public FunctionRegistration<?> getRegistration(Object function) {
|
||||
if (function == null || !names.containsKey(function)) {
|
||||
if (function == null || !this.names.containsKey(function)) {
|
||||
return null;
|
||||
}
|
||||
return new FunctionRegistration<>(function, names.get(function))
|
||||
return new FunctionRegistration<>(function, this.names.get(function))
|
||||
.type(findType(function).getType());
|
||||
}
|
||||
|
||||
@@ -315,15 +305,15 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
final Object value = function;
|
||||
lookup.computeIfAbsent(name, key -> value);
|
||||
if (!types.containsKey(name)) {
|
||||
if (types.containsKey(stages[0])
|
||||
&& types.containsKey(stages[stages.length - 1])) {
|
||||
FunctionType input = types.get(stages[0]);
|
||||
FunctionType output = types.get(stages[stages.length - 1]);
|
||||
types.put(name, FunctionType.compose(input, output));
|
||||
if (!this.types.containsKey(name)) {
|
||||
if (this.types.containsKey(stages[0])
|
||||
&& this.types.containsKey(stages[stages.length - 1])) {
|
||||
FunctionType input = this.types.get(stages[0]);
|
||||
FunctionType output = this.types.get(stages[stages.length - 1]);
|
||||
this.types.put(name, FunctionType.compose(input, output));
|
||||
}
|
||||
}
|
||||
names.put(function, name);
|
||||
this.names.put(function, name);
|
||||
return function;
|
||||
}
|
||||
|
||||
@@ -341,12 +331,14 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
Supplier<Flux<Object>> supplier = (Supplier<Flux<Object>>) a;
|
||||
if (b instanceof FluxConsumer) {
|
||||
if (supplier instanceof FluxSupplier) {
|
||||
FluxConsumer<Object> fConsumer = ((FluxConsumer<Object>)b);
|
||||
return (Supplier<Mono<Void>>) () -> Mono.from(supplier.get().compose(v -> fConsumer.apply(supplier.get())));
|
||||
FluxConsumer<Object> fConsumer = ((FluxConsumer<Object>) b);
|
||||
return (Supplier<Mono<Void>>) () -> Mono.from(supplier.get()
|
||||
.compose(v -> fConsumer.apply(supplier.get())));
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("The provided supplier is finite (i.e., already composed with Consumer) "
|
||||
+ "therefore it can not be composed with another consumer");
|
||||
throw new IllegalStateException(
|
||||
"The provided supplier is finite (i.e., already composed with Consumer) "
|
||||
+ "therefore it can not be composed with another consumer");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -362,13 +354,16 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
return function1.andThen(function2);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("The provided function is finite (i.e., returns Mono<?>) "
|
||||
+ "therefore it can *only* be composed with compatible function (i.e., Function<Mono, Flux>");
|
||||
throw new IllegalStateException(
|
||||
"The provided function is finite (i.e., returns Mono<?>) "
|
||||
+ "therefore it can *only* be composed with compatible function (i.e., Function<Mono, Flux>");
|
||||
}
|
||||
}
|
||||
else if (function2 instanceof FluxToMonoFunction) {
|
||||
return new FluxToMonoFunction<Object, Object>(((Function<Flux<Object>, Flux<Object>>)a)
|
||||
.andThen(((FluxToMonoFunction<Object,Object>) b).getTarget()));
|
||||
return new FluxToMonoFunction<Object, Object>(
|
||||
((Function<Flux<Object>, Flux<Object>>) a)
|
||||
.andThen(((FluxToMonoFunction<Object, Object>) b)
|
||||
.getTarget()));
|
||||
}
|
||||
else {
|
||||
return function1.andThen(function2);
|
||||
@@ -391,18 +386,18 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (publisher != null) {
|
||||
if (!functions.isEmpty()) {
|
||||
publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Function.class, functions.keySet()));
|
||||
if (this.publisher != null) {
|
||||
if (!this.functions.isEmpty()) {
|
||||
this.publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Function.class, this.functions.keySet()));
|
||||
}
|
||||
if (!consumers.isEmpty()) {
|
||||
publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Consumer.class, consumers.keySet()));
|
||||
if (!this.consumers.isEmpty()) {
|
||||
this.publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Consumer.class, this.consumers.keySet()));
|
||||
}
|
||||
if (!suppliers.isEmpty()) {
|
||||
publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Supplier.class, suppliers.keySet()));
|
||||
if (!this.suppliers.isEmpty()) {
|
||||
this.publisher.publishEvent(new FunctionUnregistrationEvent(this,
|
||||
Supplier.class, this.suppliers.keySet()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -443,8 +438,8 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
private Collection<String> getAliases(String key) {
|
||||
Collection<String> names = new LinkedHashSet<>();
|
||||
String value = getQualifier(key);
|
||||
if (value.equals(key) && registry != null) {
|
||||
names.addAll(Arrays.asList(registry.getAliases(key)));
|
||||
if (value.equals(key) && this.registry != null) {
|
||||
names.addAll(Arrays.asList(this.registry.getAliases(key)));
|
||||
}
|
||||
names.add(value);
|
||||
return names;
|
||||
@@ -485,8 +480,8 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
// this.names.remove(target);
|
||||
this.names.put(registration.getTarget(), key);
|
||||
if (publisher != null) {
|
||||
publisher.publishEvent(new FunctionRegistrationEvent(
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new FunctionRegistrationEvent(
|
||||
registration.getTarget(), type, registration.getNames()));
|
||||
}
|
||||
}
|
||||
@@ -552,8 +547,8 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
private String getQualifier(String key) {
|
||||
if (registry != null && registry.containsBeanDefinition(key)) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(key);
|
||||
if (this.registry != null && this.registry.containsBeanDefinition(key)) {
|
||||
BeanDefinition beanDefinition = this.registry.getBeanDefinition(key);
|
||||
Object source = beanDefinition.getSource();
|
||||
if (source instanceof StandardMethodMetadata) {
|
||||
StandardMethodMetadata metadata = (StandardMethodMetadata) source;
|
||||
@@ -568,13 +563,13 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
private FunctionType findType(Object function) {
|
||||
String name = names.get(function);
|
||||
if (types.containsKey(name)) {
|
||||
return types.get(name);
|
||||
String name = this.names.get(function);
|
||||
if (this.types.containsKey(name)) {
|
||||
return this.types.get(name);
|
||||
}
|
||||
FunctionType param;
|
||||
if (name == null || registry == null
|
||||
|| !registry.containsBeanDefinition(name)) {
|
||||
if (name == null || this.registry == null
|
||||
|| !this.registry.containsBeanDefinition(name)) {
|
||||
if (function != null) {
|
||||
param = new FunctionType(function.getClass());
|
||||
}
|
||||
@@ -583,9 +578,10 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
}
|
||||
else {
|
||||
param = new FunctionType(FunctionContextUtils.findType(name, registry));
|
||||
param = new FunctionType(
|
||||
FunctionContextUtils.findType(name, this.registry));
|
||||
}
|
||||
types.computeIfAbsent(name, str -> param);
|
||||
this.types.computeIfAbsent(name, str -> param);
|
||||
return param;
|
||||
}
|
||||
|
||||
@@ -597,7 +593,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(name = ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
|
||||
@ConditionalOnProperty(name = PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
|
||||
static class GsonPreferred {
|
||||
|
||||
}
|
||||
@@ -609,4 +605,21 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
protected class BeanFactoryFunctionInspector implements FunctionInspector {
|
||||
|
||||
private ContextFunctionRegistry processor;
|
||||
|
||||
public BeanFactoryFunctionInspector(ContextFunctionRegistry processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionRegistration<?> getRegistration(Object function) {
|
||||
FunctionRegistration<?> registration = this.processor
|
||||
.getRegistration(function);
|
||||
return registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,14 @@ import org.springframework.util.ClassUtils;
|
||||
public class ContextFunctionCatalogInitializer
|
||||
implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||
|
||||
/**
|
||||
* Property name for ignoring pre initilizer.
|
||||
*/
|
||||
public static final String IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME = "spring.backgroundpreinitializer.ignore";
|
||||
|
||||
/**
|
||||
* Flag for enabling the context function catalog initializer.
|
||||
*/
|
||||
public static boolean enabled = true;
|
||||
|
||||
@Override
|
||||
@@ -69,7 +75,7 @@ public class ContextFunctionCatalogInitializer
|
||||
|
||||
private GenericApplicationContext context;
|
||||
|
||||
public ContextFunctionCatalogBeanRegistrar(
|
||||
ContextFunctionCatalogBeanRegistrar(
|
||||
GenericApplicationContext applicationContext) {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
@@ -101,65 +107,67 @@ public class ContextFunctionCatalogInitializer
|
||||
|
||||
performPreinitialization();
|
||||
|
||||
if (context.getBeanFactory().getBeanNamesForType(
|
||||
if (this.context.getBeanFactory().getBeanNamesForType(
|
||||
PropertySourcesPlaceholderConfigurer.class, false,
|
||||
false).length == 0) {
|
||||
context.registerBean(PropertySourcesPlaceholderConfigurer.class,
|
||||
this.context.registerBean(PropertySourcesPlaceholderConfigurer.class,
|
||||
() -> PropertyPlaceholderAutoConfiguration
|
||||
.propertySourcesPlaceholderConfigurer());
|
||||
}
|
||||
|
||||
if (!context.getBeanFactory().containsBean(
|
||||
if (!this.context.getBeanFactory().containsBean(
|
||||
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
// Switch off the ConfigurationClassPostProcessor
|
||||
context.registerBean(
|
||||
this.context.registerBean(
|
||||
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,
|
||||
DummyProcessor.class, () -> new DummyProcessor());
|
||||
// But switch on other annotation processing
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.context);
|
||||
}
|
||||
if (!context.getBeanFactory()
|
||||
if (!this.context.getBeanFactory()
|
||||
.containsBean(ConfigurationBeanFactoryMetadata.BEAN_NAME)) {
|
||||
context.registerBean(ConfigurationBeanFactoryMetadata.BEAN_NAME,
|
||||
this.context.registerBean(ConfigurationBeanFactoryMetadata.BEAN_NAME,
|
||||
ConfigurationBeanFactoryMetadata.class,
|
||||
() -> new ConfigurationBeanFactoryMetadata());
|
||||
context.registerBean(
|
||||
this.context.registerBean(
|
||||
ConfigurationPropertiesBindingPostProcessor.BEAN_NAME,
|
||||
ConfigurationPropertiesBindingPostProcessor.class,
|
||||
() -> new ConfigurationPropertiesBindingPostProcessor());
|
||||
}
|
||||
|
||||
if (ClassUtils.isPresent("com.google.gson.Gson", null)
|
||||
&& "gson".equals(context.getEnvironment().getProperty(
|
||||
&& "gson".equals(this.context.getEnvironment().getProperty(
|
||||
ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY,
|
||||
"gson"))) {
|
||||
if (context.getBeanFactory().getBeanNamesForType(Gson.class, false,
|
||||
if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false,
|
||||
false).length == 0) {
|
||||
context.registerBean(Gson.class, () -> new Gson());
|
||||
this.context.registerBean(Gson.class, () -> new Gson());
|
||||
}
|
||||
context.registerBean(JsonMapper.class,
|
||||
this.context.registerBean(JsonMapper.class,
|
||||
() -> new ContextFunctionCatalogAutoConfiguration.GsonConfiguration()
|
||||
.jsonMapper(context.getBean(Gson.class)));
|
||||
.jsonMapper(this.context.getBean(Gson.class)));
|
||||
}
|
||||
else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
|
||||
null)) {
|
||||
if (context.getBeanFactory().getBeanNamesForType(ObjectMapper.class,
|
||||
if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class,
|
||||
false, false).length == 0) {
|
||||
context.registerBean(ObjectMapper.class, () -> new ObjectMapper());
|
||||
this.context.registerBean(ObjectMapper.class,
|
||||
() -> new ObjectMapper());
|
||||
}
|
||||
context.registerBean(JsonMapper.class,
|
||||
this.context.registerBean(JsonMapper.class,
|
||||
() -> new ContextFunctionCatalogAutoConfiguration.JacksonConfiguration()
|
||||
.jsonMapper(context.getBean(ObjectMapper.class)));
|
||||
.jsonMapper(this.context.getBean(ObjectMapper.class)));
|
||||
|
||||
}
|
||||
|
||||
if (context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class, false,
|
||||
false).length == 0) {
|
||||
context.registerBean(InMemoryFunctionCatalog.class,
|
||||
if (this.context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class,
|
||||
false, false).length == 0) {
|
||||
this.context.registerBean(InMemoryFunctionCatalog.class,
|
||||
() -> new InMemoryFunctionCatalog());
|
||||
context.registerBean(FunctionRegistrationPostProcessor.class,
|
||||
() -> new FunctionRegistrationPostProcessor(
|
||||
context.getAutowireCapableBeanFactory()
|
||||
this.context
|
||||
.registerBean(FunctionRegistrationPostProcessor.class,
|
||||
() -> new FunctionRegistrationPostProcessor(this.context
|
||||
.getAutowireCapableBeanFactory()
|
||||
.getBeanProvider(FunctionRegistration.class)));
|
||||
}
|
||||
}
|
||||
@@ -193,10 +201,11 @@ public class ContextFunctionCatalogInitializer
|
||||
}
|
||||
|
||||
private class FunctionRegistrationPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final ObjectProvider<FunctionRegistration> functions;
|
||||
|
||||
public FunctionRegistrationPostProcessor(
|
||||
FunctionRegistrationPostProcessor(
|
||||
@SuppressWarnings("rawtypes") ObjectProvider<FunctionRegistration> functions) {
|
||||
this.functions = functions;
|
||||
}
|
||||
@@ -206,7 +215,7 @@ public class ContextFunctionCatalogInitializer
|
||||
throws BeansException {
|
||||
if (bean instanceof FunctionRegistry) {
|
||||
FunctionRegistry catalog = (FunctionRegistry) bean;
|
||||
for (FunctionRegistration<?> registration : functions) {
|
||||
for (FunctionRegistration<?> registration : this.functions) {
|
||||
Assert.notEmpty(registration.getNames(),
|
||||
"FunctionRegistration must define at least one name. Was empty");
|
||||
if (registration.getType() == null) {
|
||||
@@ -222,13 +231,19 @@ public class ContextFunctionCatalogInitializer
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy implementation of a processor.
|
||||
*/
|
||||
public static class DummyProcessor {
|
||||
|
||||
public void setMetadataReaderFactory(MetadataReaderFactory obj) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,103 +38,106 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class FunctionContextUtils {
|
||||
|
||||
public static Type findType(String name, ConfigurableListableBeanFactory registry) {
|
||||
AbstractBeanDefinition definition = (AbstractBeanDefinition) registry.getBeanDefinition(name);
|
||||
Object source = definition.getSource();
|
||||
Type param = null;
|
||||
// Start by assuming output -> Function
|
||||
if (source instanceof StandardMethodMetadata) {
|
||||
// Standard @Bean metadata
|
||||
param = ((StandardMethodMetadata) source).getIntrospectedMethod()
|
||||
.getGenericReturnType();
|
||||
}
|
||||
else if (source instanceof MethodMetadataReadingVisitor) {
|
||||
// A component scan with @Beans
|
||||
MethodMetadataReadingVisitor visitor = (MethodMetadataReadingVisitor) source;
|
||||
param = findBeanType(definition, visitor);
|
||||
}
|
||||
else if (source instanceof Resource) {
|
||||
param = registry.getType(name);
|
||||
}
|
||||
else {
|
||||
ResolvableType type = (ResolvableType) getField(definition, "targetType");
|
||||
if (type != null) {
|
||||
param = type.getType();
|
||||
}
|
||||
else {
|
||||
Class<?> beanClass = definition.getBeanClass();
|
||||
if (beanClass != null && !FunctionFactoryMetadata.class.isAssignableFrom(beanClass)) {
|
||||
param = beanClass;
|
||||
}
|
||||
else {
|
||||
//assume FunctionFactoryMetadata
|
||||
FunctionFactoryMetadata<?> factory = (FunctionFactoryMetadata<?>) registry.getBean(name);
|
||||
param = factory.getFactoryMethod().getGenericReturnType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
public static Type findType(String name, ConfigurableListableBeanFactory registry) {
|
||||
AbstractBeanDefinition definition = (AbstractBeanDefinition) registry
|
||||
.getBeanDefinition(name);
|
||||
Object source = definition.getSource();
|
||||
Type param = null;
|
||||
// Start by assuming output -> Function
|
||||
if (source instanceof StandardMethodMetadata) {
|
||||
// Standard @Bean metadata
|
||||
param = ((StandardMethodMetadata) source).getIntrospectedMethod()
|
||||
.getGenericReturnType();
|
||||
}
|
||||
else if (source instanceof MethodMetadataReadingVisitor) {
|
||||
// A component scan with @Beans
|
||||
MethodMetadataReadingVisitor visitor = (MethodMetadataReadingVisitor) source;
|
||||
param = findBeanType(definition, visitor);
|
||||
}
|
||||
else if (source instanceof Resource) {
|
||||
param = registry.getType(name);
|
||||
}
|
||||
else {
|
||||
ResolvableType type = (ResolvableType) getField(definition, "targetType");
|
||||
if (type != null) {
|
||||
param = type.getType();
|
||||
}
|
||||
else {
|
||||
Class<?> beanClass = definition.getBeanClass();
|
||||
if (beanClass != null
|
||||
&& !FunctionFactoryMetadata.class.isAssignableFrom(beanClass)) {
|
||||
param = beanClass;
|
||||
}
|
||||
else {
|
||||
// assume FunctionFactoryMetadata
|
||||
FunctionFactoryMetadata<?> factory = (FunctionFactoryMetadata<?>) registry
|
||||
.getBean(name);
|
||||
param = factory.getFactoryMethod().getGenericReturnType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
private static Type findBeanType(AbstractBeanDefinition definition,
|
||||
MethodMetadataReadingVisitor visitor) {
|
||||
Class<?> factory = ClassUtils
|
||||
.resolveClassName(visitor.getDeclaringClassName(), null);
|
||||
Class<?>[] params = getParamTypes(factory, definition);
|
||||
Method method = ReflectionUtils.findMethod(factory, visitor.getMethodName(),
|
||||
params);
|
||||
Type type = method.getGenericReturnType();
|
||||
return type;
|
||||
}
|
||||
private static Type findBeanType(AbstractBeanDefinition definition,
|
||||
MethodMetadataReadingVisitor visitor) {
|
||||
Class<?> factory = ClassUtils.resolveClassName(visitor.getDeclaringClassName(),
|
||||
null);
|
||||
Class<?>[] params = getParamTypes(factory, definition);
|
||||
Method method = ReflectionUtils.findMethod(factory, visitor.getMethodName(),
|
||||
params);
|
||||
Type type = method.getGenericReturnType();
|
||||
return type;
|
||||
}
|
||||
|
||||
private static Class<?>[] getParamTypes(Class<?> factory,
|
||||
AbstractBeanDefinition definition) {
|
||||
if (definition instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition root = (RootBeanDefinition) definition;
|
||||
for (Method method : getCandidateMethods(factory, root)) {
|
||||
if (root.isFactoryMethod(method)) {
|
||||
return method.getParameterTypes();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Class<?>> params = new ArrayList<>();
|
||||
for (ConstructorArgumentValues.ValueHolder holder : definition.getConstructorArgumentValues()
|
||||
.getIndexedArgumentValues().values()) {
|
||||
params.add(ClassUtils.resolveClassName(holder.getType(), null));
|
||||
}
|
||||
return params.toArray(new Class<?>[0]);
|
||||
}
|
||||
private static Class<?>[] getParamTypes(Class<?> factory,
|
||||
AbstractBeanDefinition definition) {
|
||||
if (definition instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition root = (RootBeanDefinition) definition;
|
||||
for (Method method : getCandidateMethods(factory, root)) {
|
||||
if (root.isFactoryMethod(method)) {
|
||||
return method.getParameterTypes();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Class<?>> params = new ArrayList<>();
|
||||
for (ConstructorArgumentValues.ValueHolder holder : definition
|
||||
.getConstructorArgumentValues().getIndexedArgumentValues().values()) {
|
||||
params.add(ClassUtils.resolveClassName(holder.getType(), null));
|
||||
}
|
||||
return params.toArray(new Class<?>[0]);
|
||||
}
|
||||
|
||||
private static Method[] getCandidateMethods(final Class<?> factoryClass,
|
||||
final RootBeanDefinition mbd) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
||||
@Override
|
||||
public Method[] run() {
|
||||
return (mbd.isNonPublicAccessAllowed()
|
||||
? ReflectionUtils.getAllDeclaredMethods(factoryClass)
|
||||
: factoryClass.getMethods());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return (mbd.isNonPublicAccessAllowed()
|
||||
? ReflectionUtils.getAllDeclaredMethods(factoryClass)
|
||||
: factoryClass.getMethods());
|
||||
}
|
||||
}
|
||||
private static Method[] getCandidateMethods(final Class<?> factoryClass,
|
||||
final RootBeanDefinition mbd) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
||||
@Override
|
||||
public Method[] run() {
|
||||
return (mbd.isNonPublicAccessAllowed()
|
||||
? ReflectionUtils.getAllDeclaredMethods(factoryClass)
|
||||
: factoryClass.getMethods());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return (mbd.isNonPublicAccessAllowed()
|
||||
? ReflectionUtils.getAllDeclaredMethods(factoryClass)
|
||||
: factoryClass.getMethods());
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, target);
|
||||
}
|
||||
|
||||
private static Object getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -39,7 +39,6 @@ public abstract class MessageUtils {
|
||||
* isolated class loader, then the message will be created with the target class
|
||||
* loader (therefore the {@link Message} class must be on the classpath of the target
|
||||
* class loader).
|
||||
*
|
||||
* @param handler the function that will be applied to the message
|
||||
* @param payload the payload of the message
|
||||
* @param headers the headers for the message
|
||||
@@ -74,7 +73,6 @@ public abstract class MessageUtils {
|
||||
* class loader. If the handler is a wrapper for a function in an isolated class
|
||||
* loader, then the message will be created with the target class loader (therefore
|
||||
* the {@link Message} class must be on the classpath of the target class loader).
|
||||
*
|
||||
* @param handler the function that generated the message
|
||||
* @param message the message to convert
|
||||
* @return a message with the correct class loader
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,16 +42,16 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
@ContextConfiguration(loader = FunctionalTestContextLoader.class)
|
||||
public @interface FunctionalSpringBootTest {
|
||||
|
||||
@AliasFor(annotation=SpringBootTest.class, attribute="properties")
|
||||
@AliasFor(annotation = SpringBootTest.class, attribute = "properties")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor(annotation=SpringBootTest.class, attribute="value")
|
||||
@AliasFor(annotation = SpringBootTest.class, attribute = "value")
|
||||
String[] properties() default {};
|
||||
|
||||
@AliasFor(annotation=SpringBootTest.class, attribute="classes")
|
||||
@AliasFor(annotation = SpringBootTest.class, attribute = "classes")
|
||||
Class<?>[] classes() default {};
|
||||
|
||||
@AliasFor(annotation=SpringBootTest.class, attribute="webEnvironment")
|
||||
@AliasFor(annotation = SpringBootTest.class, attribute = "webEnvironment")
|
||||
WebEnvironment webEnvironment() default WebEnvironment.MOCK;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -34,4 +34,5 @@ class FunctionalTestContextLoader extends SpringBootContextLoader {
|
||||
protected SpringApplication getSpringApplication() {
|
||||
return new FunctionalSpringApplication();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.json;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -34,11 +35,12 @@ public class GsonMapper implements JsonMapper {
|
||||
|
||||
@Override
|
||||
public <T> T toObject(String json, Type type) {
|
||||
return gson.fromJson(json, type);
|
||||
return this.gson.fromJson(json, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Object value) {
|
||||
return gson.toJson(value);
|
||||
return this.gson.toJson(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.json;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -36,7 +37,8 @@ public class JacksonMapper implements JsonMapper {
|
||||
@Override
|
||||
public <T> T toObject(String json, Type type) {
|
||||
try {
|
||||
return mapper.readValue(json, TypeFactory.defaultInstance().constructType(type));
|
||||
return this.mapper.readValue(json,
|
||||
TypeFactory.defaultInstance().constructType(type));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot convert JSON " + json, e);
|
||||
@@ -46,10 +48,11 @@ public class JacksonMapper implements JsonMapper {
|
||||
@Override
|
||||
public String toString(Object value) {
|
||||
try {
|
||||
return mapper.writeValueAsString(value);
|
||||
return this.mapper.writeValueAsString(value);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Cannot convert to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.json;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -28,6 +29,10 @@ import org.springframework.core.ResolvableType;
|
||||
public interface JsonMapper {
|
||||
|
||||
/**
|
||||
* @param <T> type for list arguments
|
||||
* @param json JSON input
|
||||
* @param type type of list arguments
|
||||
* @return list of elements
|
||||
* @deprecated since v2.0 in favor of {@link #toObject(String, Type)}
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -40,11 +45,19 @@ public interface JsonMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param <T> return type
|
||||
* @param json JSON input
|
||||
* @param type type
|
||||
* @return object
|
||||
* @since 2.0
|
||||
*/
|
||||
<T> T toObject(String json, Type type);
|
||||
|
||||
/**
|
||||
* @param <T> type for list arguments
|
||||
* @param json JSON input
|
||||
* @param type type of list arguments
|
||||
* @return single object
|
||||
* @deprecated since v2.0 in favor of {@link #toObject(String, Type)}
|
||||
*/
|
||||
default <T> T toSingle(String json, Class<T> type) {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"hints": [],
|
||||
"groups": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.cloud.function.scan.packages",
|
||||
"type": "java.lang.String",
|
||||
"description": "Triggers scanning within the specified base packages for any class that is assignable to java.util.function.Function. For each detected Function class, a bean instance will be added to the context.",
|
||||
"defaultValue": "functions"
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.function.definition",
|
||||
"type": "java.lang.String",
|
||||
"description": "Name (e.g., 'foo') or composition instruction (e.g., 'foo|bar') used to resolve default function especially for cases where there is more then once function available in catalog.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
"hints": [],
|
||||
"groups": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.cloud.function.scan.packages",
|
||||
"type": "java.lang.String",
|
||||
"description": "Triggers scanning within the specified base packages for any class that is assignable to java.util.function.Function. For each detected Function class, a bean instance will be added to the context.",
|
||||
"defaultValue": "functions"
|
||||
},
|
||||
{
|
||||
"name": "spring.cloud.function.definition",
|
||||
"type": "java.lang.String",
|
||||
"description": "Name (e.g., 'foo') or composition instruction (e.g., 'foo|bar') used to resolve default function especially for cases where there is more then once function available in catalog.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration
|
||||
|
||||
org.springframework.cloud.function.context.WrapperDetector=\
|
||||
org.springframework.cloud.function.context.config.FluxWrapperDetector
|
||||
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer
|
||||
org.springframework.cloud.function.context.config.ContextFunctionCatalogInitializer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -46,10 +46,12 @@ public class FunctionRegistrationTests {
|
||||
}
|
||||
|
||||
private static class Foos implements Function<Integer, String> {
|
||||
|
||||
@Override
|
||||
public String apply(Integer t) {
|
||||
return "i=" + t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -23,6 +23,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -30,8 +31,6 @@ import org.springframework.messaging.support.MessageBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -50,7 +49,8 @@ public class FunctionTypeTests {
|
||||
|
||||
@Test
|
||||
public void supplierOfRegistration() {
|
||||
FunctionType function = new FunctionType(SupplierOfRegistrationOfIntegerToString.class);
|
||||
FunctionType function = new FunctionType(
|
||||
SupplierOfRegistrationOfIntegerToString.class);
|
||||
assertThat(function.getInputType()).isEqualTo(Integer.class);
|
||||
assertThat(function.getOutputType()).isEqualTo(String.class);
|
||||
assertThat(function.getInputWrapper()).isEqualTo(Integer.class);
|
||||
@@ -247,60 +247,80 @@ public class FunctionTypeTests {
|
||||
assertThat(function).isSameAs(function.wrap(Object.class));
|
||||
}
|
||||
|
||||
private static class SupplierOfRegistrationOfIntegerToString implements Supplier<FunctionRegistration<Function<Integer, String>>> {
|
||||
private static class SupplierOfRegistrationOfIntegerToString
|
||||
implements Supplier<FunctionRegistration<Function<Integer, String>>> {
|
||||
|
||||
@Override
|
||||
public FunctionRegistration<Function<Integer, String>> get() {
|
||||
return new FunctionRegistration<Function<Integer,String>>(new IntegerToString(), "ints");
|
||||
return new FunctionRegistration<Function<Integer, String>>(
|
||||
new IntegerToString(), "ints");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SupplierOfIntegerToString implements Supplier<Function<Integer, String>> {
|
||||
|
||||
private static class SupplierOfIntegerToString
|
||||
implements Supplier<Function<Integer, String>> {
|
||||
|
||||
@Override
|
||||
public Function<Integer, String> get() {
|
||||
return new IntegerToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class IntegerToString implements Function<Integer, String> {
|
||||
|
||||
@Override
|
||||
public String apply(Integer t) {
|
||||
return "" + t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class StringToMap implements Function<String, Map<String, Integer>> {
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> apply(String t) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FooToFoo implements Function<Foo, Bar> {
|
||||
|
||||
@Override
|
||||
public Bar apply(Foo t) {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FluxToFlux implements Function<Flux<Foo>, Flux<Bar>> {
|
||||
|
||||
@Override
|
||||
public Flux<Bar> apply(Flux<Foo> t) {
|
||||
return t.map(f -> new Bar());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FluxMessageToFluxMessage
|
||||
implements Function<Flux<Message<Foo>>, Flux<Message<Bar>>> {
|
||||
|
||||
@Override
|
||||
public Flux<Message<Bar>> apply(Flux<Message<Foo>> t) {
|
||||
return t.map(f -> MessageBuilder.withPayload(new Bar())
|
||||
.copyHeadersIfAbsent(f.getHeaders()).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Foo {
|
||||
|
||||
}
|
||||
|
||||
private static class Bar {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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
|
||||
* 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,
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package org.springframework.cloud.function.context.catalog;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionType;
|
||||
import org.springframework.cloud.function.core.FluxFunction;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionType;
|
||||
import org.springframework.cloud.function.core.FluxFunction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
@@ -38,8 +38,8 @@ public class InMemoryFunctionCatalogTests {
|
||||
@Test
|
||||
public void testFunctionRegistration() {
|
||||
TestFunction function = new TestFunction();
|
||||
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(function, "foo")
|
||||
.type(FunctionType.of(TestFunction.class).getType());
|
||||
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(
|
||||
function, "foo").type(FunctionType.of(TestFunction.class).getType());
|
||||
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
||||
catalog.register(registration);
|
||||
FunctionRegistration<?> registration2 = catalog.getRegistration(function);
|
||||
@@ -49,8 +49,8 @@ public class InMemoryFunctionCatalogTests {
|
||||
@Test
|
||||
public void testFunctionLookup() {
|
||||
TestFunction function = new TestFunction();
|
||||
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(function, "foo")
|
||||
.type(FunctionType.of(TestFunction.class).getType());
|
||||
FunctionRegistration<TestFunction> registration = new FunctionRegistration<>(
|
||||
function, "foo").type(FunctionType.of(TestFunction.class).getType());
|
||||
InMemoryFunctionCatalog catalog = new InMemoryFunctionCatalog();
|
||||
catalog.register(registration);
|
||||
|
||||
@@ -63,9 +63,12 @@ public class InMemoryFunctionCatalogTests {
|
||||
}
|
||||
|
||||
private static class TestFunction implements Function<Integer, String> {
|
||||
|
||||
@Override
|
||||
public String apply(Integer t) {
|
||||
return "i=" + t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -26,6 +26,8 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionType;
|
||||
@@ -34,9 +36,6 @@ import org.springframework.cloud.function.context.config.ContextFunctionCatalogA
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -48,56 +47,59 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
|
||||
@Test
|
||||
public void basicRegistrationFeatures() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup(Function.class,
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup(Function.class,
|
||||
"foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupFunctionWithEmptyName() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup(Function.class, "");
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup(Function.class,
|
||||
"");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookupFunctionWithNoType() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup("foos");
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerFunctionWithType() {
|
||||
processor.register(new FunctionRegistration<Function<Integer, String>>(
|
||||
this.processor.register(new FunctionRegistration<Function<Integer, String>>(
|
||||
(Integer i) -> "i=" + i, "foos").type(
|
||||
FunctionType.from(Integer.class).to(String.class).getType()));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup(Function.class, "");
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup(Function.class,
|
||||
"");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("i=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerFunctionWithFluxType() {
|
||||
processor
|
||||
this.processor
|
||||
.register(new FunctionRegistration<Function<Flux<Integer>, Flux<String>>>(
|
||||
ints -> ints.map(i -> "i=" + i), "foos")
|
||||
.type(FunctionType.from(Integer.class).to(String.class)
|
||||
.wrap(Flux.class).getType()));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup(Function.class, "");
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup(Function.class,
|
||||
"");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("i=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerFunctionWithMonoType() {
|
||||
processor.register(
|
||||
this.processor.register(
|
||||
new FunctionRegistration<Function<Flux<String>, Mono<Map<String, Integer>>>>(
|
||||
flux -> flux.collect(HashMap::new,
|
||||
(map, word) -> map.merge(word, 1, Integer::sum)), "foos")
|
||||
.type(FunctionType.from(String.class)
|
||||
.to(Map.class)
|
||||
.wrap(Flux.class, Mono.class).getType()));
|
||||
Function<Flux<String>, Mono<Map<String, Integer>>> foos = processor
|
||||
(map, word) -> map.merge(word, 1, Integer::sum)),
|
||||
"foos").type(
|
||||
FunctionType.from(String.class).to(Map.class)
|
||||
.wrap(Flux.class, Mono.class).getType()));
|
||||
Function<Flux<String>, Mono<Map<String, Integer>>> foos = this.processor
|
||||
.lookup(Function.class, "");
|
||||
assertThat(foos.apply(Flux.just("one", "one", "two")).block())
|
||||
.containsEntry("one", 2);
|
||||
@@ -105,16 +107,16 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
|
||||
@Test
|
||||
public void lookupNonExistentConsumerWithEmptyName() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Consumer<Flux<String>> foos = processor.lookup(Consumer.class, "");
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Consumer<Flux<String>> foos = this.processor.lookup(Consumer.class, "");
|
||||
assertThat(foos).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeFunction() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = processor.lookup(Function.class,
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
Function<Flux<Integer>, Flux<String>> foos = this.processor.lookup(Function.class,
|
||||
"foos,bars");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("Hello 4");
|
||||
}
|
||||
@@ -122,51 +124,60 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
@Test
|
||||
public void composeWithFiniteFunction() {
|
||||
Function<String, String> func1 = x -> x.toUpperCase();
|
||||
processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
processor.register(new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
Function<Flux<String>, Mono<Long>> foos = processor.lookup(Function.class, "func1,func2");
|
||||
assertThat(foos.apply(Flux.fromArray(new String[] {"a", "b", "c"})).block()).isEqualTo(3);
|
||||
this.processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
this.processor.register(
|
||||
new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
Function<Flux<String>, Mono<Long>> foos = this.processor.lookup(Function.class,
|
||||
"func1,func2");
|
||||
assertThat(foos.apply(Flux.fromArray(new String[] { "a", "b", "c" })).block())
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeWithFiniteFunctionAndContinueWithCompatible() {
|
||||
Function<String, String> func1 = x -> x.toUpperCase();
|
||||
processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
processor.register(new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
processor.register(new FunctionRegistration<>(new MonoThenFluxFunction(), "func3"));
|
||||
Function<Flux<String>, Flux<Integer>> foos = processor.lookup(Function.class, "func1,func2,func3");
|
||||
assertThat(foos.apply(Flux.fromArray(new String[] {"a", "b", "c"})).collectList().block().size()).isEqualTo(3);
|
||||
this.processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
this.processor.register(
|
||||
new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
this.processor.register(
|
||||
new FunctionRegistration<>(new MonoThenFluxFunction(), "func3"));
|
||||
Function<Flux<String>, Flux<Integer>> foos = this.processor.lookup(Function.class,
|
||||
"func1,func2,func3");
|
||||
assertThat(foos.apply(Flux.fromArray(new String[] { "a", "b", "c" }))
|
||||
.collectList().block().size()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void composeIncompatibleFunctions() {
|
||||
Function<String, String> func1 = x -> x.toUpperCase();
|
||||
processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
processor.register(new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
processor.lookup(Function.class, "func2,func1");
|
||||
this.processor.register(new FunctionRegistration<>(func1, "func1"));
|
||||
this.processor.register(
|
||||
new FunctionRegistration<>(new FluxThenMonoFunction(), "func2"));
|
||||
this.processor.lookup(Function.class, "func2,func1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeSupplier() {
|
||||
processor.register(new FunctionRegistration<>(new Source(), "numbers"));
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Supplier<Flux<String>> foos = processor.lookup(Supplier.class, "numbers,foos");
|
||||
this.processor.register(new FunctionRegistration<>(new Source(), "numbers"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Supplier<Flux<String>> foos = this.processor.lookup(Supplier.class,
|
||||
"numbers,foos");
|
||||
assertThat(foos.get().blockFirst()).isEqualTo("6");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeUniqueSupplier() {
|
||||
processor.register(new FunctionRegistration<>(new Source(), "numbers"));
|
||||
Supplier<Flux<Integer>> foos = processor.lookup(Supplier.class, "");
|
||||
this.processor.register(new FunctionRegistration<>(new Source(), "numbers"));
|
||||
Supplier<Flux<Integer>> foos = this.processor.lookup(Supplier.class, "");
|
||||
assertThat(foos.get().blockFirst()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeConsumer() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
Sink sink = new Sink();
|
||||
processor.register(new FunctionRegistration<>(sink, "sink"));
|
||||
Function<Flux<Integer>, Mono<Void>> foos = processor.lookup(Function.class,
|
||||
this.processor.register(new FunctionRegistration<>(sink, "sink"));
|
||||
Function<Flux<Integer>, Mono<Void>> foos = this.processor.lookup(Function.class,
|
||||
"foos,sink");
|
||||
foos.apply(Flux.just(2)).subscribe();
|
||||
assertThat(sink.values).contains("4");
|
||||
@@ -175,8 +186,9 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
@Test
|
||||
public void composeUniqueConsumer() {
|
||||
Sink sink = new Sink();
|
||||
processor.register(new FunctionRegistration<>(sink, "sink"));
|
||||
Function<Flux<String>, Mono<Void>> foos = processor.lookup(Function.class, "");
|
||||
this.processor.register(new FunctionRegistration<>(sink, "sink"));
|
||||
Function<Flux<String>, Mono<Void>> foos = this.processor.lookup(Function.class,
|
||||
"");
|
||||
foos.apply(Flux.just("2")).subscribe();
|
||||
assertThat(sink.values).contains("2");
|
||||
}
|
||||
@@ -185,36 +197,36 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
public void composeSupplierAndConsumer() {
|
||||
AtomicReference<String> ref = new AtomicReference<String>();
|
||||
Supplier<String> s = () -> "hello";
|
||||
processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
this.processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
Consumer<String> c = x -> ref.set(x.toUpperCase());
|
||||
processor.register(new FunctionRegistration<>(c, "consumer"));
|
||||
Supplier<Mono<Void>> f = processor.lookup("supplier|consumer");
|
||||
((Mono<Void>)f.get()).block();
|
||||
this.processor.register(new FunctionRegistration<>(c, "consumer"));
|
||||
Supplier<Mono<Void>> f = this.processor.lookup("supplier|consumer");
|
||||
((Mono<Void>) f.get()).block();
|
||||
assertThat(ref.get()).isEqualTo("HELLO");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void failComposeSupplierWithMultipleConsumers() {
|
||||
AtomicReference<String> ref = new AtomicReference<String>();
|
||||
Supplier<String> s = () -> "hello";
|
||||
processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
this.processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
Consumer<String> c = x -> ref.set(x.toUpperCase());
|
||||
processor.register(new FunctionRegistration<>(c, "consumer"));
|
||||
this.processor.register(new FunctionRegistration<>(c, "consumer"));
|
||||
Consumer<String> z = x -> ref.set(x.toUpperCase());
|
||||
processor.register(new FunctionRegistration<>(z, "z"));
|
||||
processor.lookup("supplier|consumer|z");
|
||||
this.processor.register(new FunctionRegistration<>(z, "z"));
|
||||
this.processor.lookup("supplier|consumer|z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeSupplierAndMultipleFunctions() {
|
||||
Supplier<String> s = () -> "hello";
|
||||
processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
this.processor.register(new FunctionRegistration<>(s, "supplier"));
|
||||
Function<String, String> uppercase = x -> x.toUpperCase();
|
||||
processor.register(new FunctionRegistration<>(uppercase, "uppercase"));
|
||||
this.processor.register(new FunctionRegistration<>(uppercase, "uppercase"));
|
||||
Function<String, String> concat = x -> x + x;
|
||||
processor.register(new FunctionRegistration<>(concat, "concat"));
|
||||
this.processor.register(new FunctionRegistration<>(concat, "concat"));
|
||||
|
||||
Supplier<Flux<String>> f = processor.lookup("supplier|uppercase|concat");
|
||||
Supplier<Flux<String>> f = this.processor.lookup("supplier|uppercase|concat");
|
||||
|
||||
assertThat(f.get().blockFirst()).isEqualTo("HELLOHELLO");
|
||||
}
|
||||
@@ -234,7 +246,7 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
|
||||
@Override
|
||||
public void accept(String value) {
|
||||
values.add(value);
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -257,20 +269,24 @@ public class BeanFactoryFunctionCatalogTests {
|
||||
|
||||
}
|
||||
|
||||
protected static class FluxThenMonoFunction implements Function<Flux<String>, Mono<Long>> {
|
||||
protected static class FluxThenMonoFunction
|
||||
implements Function<Flux<String>, Mono<Long>> {
|
||||
|
||||
@Override
|
||||
public Mono<Long> apply(Flux<String> t) {
|
||||
return t.count();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class MonoThenFluxFunction implements Function<Mono<Long>, Flux<Integer>> {
|
||||
protected static class MonoThenFluxFunction
|
||||
implements Function<Mono<Long>, Flux<Integer>> {
|
||||
|
||||
@Override
|
||||
public Flux<Integer> apply(Mono<Long> t) {
|
||||
return Flux.range(0, Integer.parseInt(t.block().toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
* Copyright 2012-2019-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.
|
||||
@@ -30,6 +30,8 @@ import java.util.stream.Collectors;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -65,9 +67,6 @@ import org.springframework.util.StreamUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Artem Bilan
|
||||
@@ -75,15 +74,22 @@ import reactor.core.publisher.Mono;
|
||||
*/
|
||||
public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
private FunctionCatalog catalog;
|
||||
private FunctionInspector inspector;
|
||||
private static String value;
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private FunctionCatalog catalog;
|
||||
|
||||
private FunctionInspector inspector;
|
||||
|
||||
public static void set(Object value) {
|
||||
ContextFunctionCatalogAutoConfigurationTests.value = value.toString();
|
||||
}
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
ContextFunctionCatalogAutoConfigurationTests.value = null;
|
||||
}
|
||||
@@ -91,280 +97,325 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
@Test
|
||||
public void lookUps() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(context.getBean("function2")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function,function2"))
|
||||
.isInstanceOf(Function.class);
|
||||
Function<Flux<String>, Flux<String>> f = catalog.lookup(Function.class,
|
||||
assertThat(this.context.getBean("function2")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class,
|
||||
"function,function2")).isInstanceOf(Function.class);
|
||||
Function<Flux<String>, Flux<String>> f = this.catalog.lookup(Function.class,
|
||||
"function,function2,function3");
|
||||
assertThat(f).isInstanceOf(Function.class);
|
||||
assertThat(f.apply(Flux.just("hello")).blockFirst())
|
||||
.isEqualTo("HELLOfunction2function3");
|
||||
assertThat(context.getBean("supplierFoo")).isInstanceOf(Supplier.class);
|
||||
assertThat((Supplier<?>) catalog.lookup(Supplier.class, "supplierFoo"))
|
||||
assertThat(this.context.getBean("supplierFoo")).isInstanceOf(Supplier.class);
|
||||
assertThat((Supplier<?>) this.catalog.lookup(Supplier.class, "supplierFoo"))
|
||||
.isInstanceOf(Supplier.class);
|
||||
assertThat(context.getBean("supplier_Foo")).isInstanceOf(Supplier.class);
|
||||
assertThat((Supplier<?>) catalog.lookup(Supplier.class, "supplier_Foo"))
|
||||
assertThat(this.context.getBean("supplier_Foo")).isInstanceOf(Supplier.class);
|
||||
assertThat((Supplier<?>) this.catalog.lookup(Supplier.class, "supplier_Foo"))
|
||||
.isInstanceOf(Supplier.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguousFunction() {
|
||||
create(AmbiguousConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat((Supplier<?>) catalog.lookup(Supplier.class, "foos"))
|
||||
assertThat((Supplier<?>) this.catalog.lookup(Supplier.class, "foos"))
|
||||
.isInstanceOf(Supplier.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Supplier.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getOutputType(this.catalog.lookup(Supplier.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationFunction() {
|
||||
create(FunctionConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getOutputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dependencyInjection() {
|
||||
create(DependencyInjectionConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void externalDependencyInjection() {
|
||||
create(ExternalDependencyConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composedFunction() {
|
||||
create(MultipleConfiguration.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos,bars"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos,bars"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "names,foos"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "names,foos"))
|
||||
.isNull();
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos,bars")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Function.class, "foos,bars")))
|
||||
.isAssignableFrom(Bar.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "foos,bars")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getOutputType(this.catalog.lookup(Function.class, "foos,bars")))
|
||||
.isAssignableFrom(Bar.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composedSupplier() {
|
||||
create(MultipleConfiguration.class);
|
||||
assertThat((Supplier<?>) catalog.lookup(Supplier.class, "names,foos"))
|
||||
assertThat((Supplier<?>) this.catalog.lookup(Supplier.class, "names,foos"))
|
||||
.isInstanceOf(Supplier.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "names,foos"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "names,foos"))
|
||||
.isNull();
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Supplier.class, "names,foos")))
|
||||
.isAssignableFrom(Foo.class);
|
||||
assertThat(this.inspector
|
||||
.getOutputType(this.catalog.lookup(Supplier.class, "names,foos")))
|
||||
.isAssignableFrom(Foo.class);
|
||||
// The input type is the same as the input type of the first element in the chain
|
||||
assertThat(inspector.getInputType(catalog.lookup(Supplier.class, "names,foos")))
|
||||
.isAssignableFrom(Void.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Supplier.class, "names,foos")))
|
||||
.isAssignableFrom(Void.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composedConsumer() {
|
||||
create(MultipleConfiguration.class);
|
||||
assertThat((Consumer<?>) catalog.lookup(Consumer.class, "foos,print")).isNull();
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos,print"))
|
||||
assertThat((Consumer<?>) this.catalog.lookup(Consumer.class, "foos,print"))
|
||||
.isNull();
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos,print"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos,print")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "foos,print")))
|
||||
.isAssignableFrom(String.class);
|
||||
// The output type is the same as the output type of the last element in the chain
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Function.class, "foos,print")))
|
||||
.isAssignableFrom(Void.class);
|
||||
assertThat(this.inspector
|
||||
.getOutputType(this.catalog.lookup(Function.class, "foos,print")))
|
||||
.isAssignableFrom(Void.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericFunction() {
|
||||
create(GenericConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fluxMessageFunction() {
|
||||
create(FluxMessageConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.isMessage(catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
assertThat(
|
||||
this.inspector.isMessage(this.catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publisherMessageFunction() {
|
||||
create(PublisherMessageConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.isMessage(catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Publisher.class);
|
||||
assertThat(
|
||||
this.inspector.isMessage(this.catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Publisher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void monoFunction() {
|
||||
create(MonoConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.isMessage(catalog.lookup(Function.class, "function")))
|
||||
.isFalse();
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
assertThat(inspector.getOutputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Mono.class);
|
||||
assertThat(
|
||||
this.inspector.isMessage(this.catalog.lookup(Function.class, "function")))
|
||||
.isFalse();
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
assertThat(this.inspector
|
||||
.getOutputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Mono.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageFunction() {
|
||||
create(MessageConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.isMessage(catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(
|
||||
this.inspector.isMessage(this.catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericFluxFunction() {
|
||||
create(GenericFluxConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Flux.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void externalFunction() {
|
||||
create(ExternalConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singletonFunction() {
|
||||
create(SingletonConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singletonMessageFunction() {
|
||||
create(SingletonMessageConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(inspector.isMessage(catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(
|
||||
this.inspector.isMessage(this.catalog.lookup(Function.class, "function")))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonParametericTypeFunction() {
|
||||
create(NonParametricTypeSingletonConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentScanBeanFunction() {
|
||||
create(ComponentScanBeanConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentScanFunction() {
|
||||
create(ComponentScanConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "function")))
|
||||
.isAssignableFrom(Map.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentScanJarFunction() {
|
||||
try {
|
||||
create("greeter.jar", ComponentScanJarConfiguration.class);
|
||||
assertThat(context.getBean("greeter")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "greeter"))
|
||||
assertThat(this.context.getBean("greeter")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "greeter"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "greeter")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(
|
||||
inspector.getInputWrapper(catalog.lookup(Function.class, "greeter")))
|
||||
assertThat(this.inspector
|
||||
.getInputType(this.catalog.lookup(Function.class, "greeter")))
|
||||
.isAssignableFrom(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "greeter")))
|
||||
.isAssignableFrom(String.class);
|
||||
}
|
||||
finally {
|
||||
@@ -372,7 +423,6 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void create(String jarfile, Class<?> config, String... props) {
|
||||
try {
|
||||
URL[] urls = new URL[] { new ClassPathResource(jarfile).getURL() };
|
||||
@@ -388,64 +438,67 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
@Test
|
||||
public void simpleFunction() {
|
||||
create(SimpleConfiguration.class);
|
||||
Object bean = context.getBean("function");
|
||||
Object bean = this.context.getBean("function");
|
||||
assertThat(bean).isInstanceOf(Function.class);
|
||||
Function<Flux<String>, Flux<String>> function = catalog.lookup(Function.class,
|
||||
"function");
|
||||
Function<Flux<String>, Flux<String>> function = this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO");
|
||||
assertThat(bean).isNotSameAs(function);
|
||||
assertThat(inspector.getRegistration(bean)).isNotNull();
|
||||
assertThat(inspector.getRegistration(bean).getType())
|
||||
.isEqualTo(inspector.getRegistration(function).getType());
|
||||
assertThat(this.inspector.getRegistration(bean)).isNotNull();
|
||||
assertThat(this.inspector.getRegistration(bean).getType())
|
||||
.isEqualTo(this.inspector.getRegistration(function).getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleSupplier() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("supplier")).isInstanceOf(Supplier.class);
|
||||
Supplier<Flux<String>> supplier = catalog.lookup(Supplier.class, "supplier");
|
||||
assertThat(this.context.getBean("supplier")).isInstanceOf(Supplier.class);
|
||||
Supplier<Flux<String>> supplier = this.catalog.lookup(Supplier.class, "supplier");
|
||||
assertThat(supplier.get().blockFirst()).isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleConsumer() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("consumer")).isInstanceOf(Consumer.class);
|
||||
Function<Flux<String>, Mono<Void>> consumer = catalog.lookup(Function.class,
|
||||
assertThat(this.context.getBean("consumer")).isInstanceOf(Consumer.class);
|
||||
Function<Flux<String>, Mono<Void>> consumer = this.catalog.lookup(Function.class,
|
||||
"consumer");
|
||||
consumer.apply(Flux.just("foo", "bar")).subscribe();
|
||||
assertThat(context.getBean(SimpleConfiguration.class).list).hasSize(2);
|
||||
assertThat(this.context.getBean(SimpleConfiguration.class).list).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void qualifiedBean() {
|
||||
create(QualifiedConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function")).isNull();
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "other"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isNull();
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "other"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "other")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "other")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aliasBean() {
|
||||
create(AliasConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isNotNull();
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "other"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "other"))
|
||||
.isInstanceOf(Function.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registrationBean() {
|
||||
create(RegistrationConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function")).isNull();
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "registration"))
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isNull();
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "other"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "registration"))
|
||||
.isNull();
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "other"))
|
||||
.isInstanceOf(Function.class);
|
||||
}
|
||||
|
||||
@@ -455,11 +508,12 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
"spring.cloud.function.compile.foos.lambda=v -> v.toUpperCase()",
|
||||
"spring.cloud.function.compile.foos.inputType=String",
|
||||
"spring.cloud.function.compile.foos.outputType=String");
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -471,11 +525,12 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
StreamUtils.copy(compiled.getGeneratedClassBytes(), resource.getOutputStream());
|
||||
create(EmptyConfiguration.class,
|
||||
"spring.cloud.function.imports.foos.location=file:./target/foos.fun");
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -485,12 +540,13 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
+ "::set",
|
||||
"spring.cloud.function.compile.foos.type=consumer",
|
||||
"spring.cloud.function.compile.foos.inputType=String");
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Consumer<String> consumer = (Consumer<String>) context.getBean("foos");
|
||||
Consumer<String> consumer = (Consumer<String>) this.context.getBean("foos");
|
||||
consumer.accept("hello");
|
||||
assertThat(ContextFunctionCatalogAutoConfigurationTests.value).isEqualTo("hello");
|
||||
}
|
||||
@@ -501,12 +557,13 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
"spring.cloud.function.compile.foos.lambda=f -> f.subscribe("
|
||||
+ getClass().getName() + "::set)",
|
||||
"spring.cloud.function.compile.foos.type=consumer");
|
||||
assertThat((Consumer<?>) catalog.lookup(Consumer.class, "foos"))
|
||||
assertThat((Consumer<?>) this.catalog.lookup(Consumer.class, "foos"))
|
||||
.isInstanceOf(Consumer.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Consumer.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Consumer.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Consumer<Flux<String>> consumer = (Consumer<Flux<String>>) context
|
||||
Consumer<Flux<String>> consumer = (Consumer<Flux<String>>) this.context
|
||||
.getBean("foos");
|
||||
consumer.accept(Flux.just("hello"));
|
||||
assertThat(ContextFunctionCatalogAutoConfigurationTests.value).isEqualTo("hello");
|
||||
@@ -516,7 +573,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public void factoryBeanFunction() {
|
||||
create(FactoryBeanConfiguration.class);
|
||||
assertThat(this.context.getBean("function")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
Function<Flux<String>, Flux<String>> f = this.catalog.lookup(Function.class,
|
||||
"function");
|
||||
@@ -528,23 +585,21 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
}
|
||||
|
||||
private void create(Class<?>[] types, String... props) {
|
||||
context = new SpringApplicationBuilder(types).properties(props).run();
|
||||
catalog = context.getBean(FunctionCatalog.class);
|
||||
inspector = context.getBean(FunctionInspector.class);
|
||||
}
|
||||
|
||||
public static void set(Object value) {
|
||||
ContextFunctionCatalogAutoConfigurationTests.value = value.toString();
|
||||
this.context = new SpringApplicationBuilder(types).properties(props).run();
|
||||
this.catalog = this.context.getBean(FunctionCatalog.class);
|
||||
this.inspector = this.context.getBean(FunctionInspector.class);
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class SimpleConfiguration {
|
||||
|
||||
private List<String> list = new ArrayList<>();
|
||||
|
||||
@Bean
|
||||
@@ -574,8 +629,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
|
||||
@Bean
|
||||
public Consumer<String> consumer() {
|
||||
return value -> list.add(value);
|
||||
return value -> this.list.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -591,6 +647,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public String value() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -607,6 +664,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public String value() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -618,6 +676,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public String value() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -634,11 +693,13 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public Supplier<Foo> supplier() {
|
||||
return () -> new Foo("bar");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class MultipleConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<String, Foo> foos() {
|
||||
return value -> new Foo(value.toUpperCase());
|
||||
@@ -658,22 +719,26 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public Supplier<String> names() {
|
||||
return () -> "Mark";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class GenericConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Map<String, String>, Map<String, String>> function() {
|
||||
return m -> m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
|
||||
e -> e.getValue().toString().toUpperCase()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
@Import(GenericFunction.class)
|
||||
protected static class ExternalConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -685,6 +750,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
throws BeansException {
|
||||
beanFactory.registerSingleton("function", new SingletonFunction());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -697,15 +763,18 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
throws BeansException {
|
||||
beanFactory.registerSingleton("function", new SingletonMessageFunction());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class NonParametricTypeSingletonConfiguration {
|
||||
|
||||
@Bean
|
||||
public SingletonFunction function() {
|
||||
return new SingletonFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class SingletonFunction implements Function<Integer, String> {
|
||||
@@ -731,90 +800,108 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = GenericFunction.class)
|
||||
protected static class ComponentScanBeanConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = ScannedFunction.class)
|
||||
protected static class ComponentScanConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class ComponentScanJarConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class GenericFluxConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Flux<Map<String, String>>, Flux<Map<String, String>>> function() {
|
||||
return flux -> flux.map(m -> m.entrySet().stream().collect(Collectors
|
||||
.toMap(e -> e.getKey(), e -> e.getValue().toString().toUpperCase())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class FluxMessageConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Flux<Message<String>>, Flux<Message<String>>> function() {
|
||||
return flux -> flux.map(m -> MessageBuilder
|
||||
.withPayload(m.getPayload().toUpperCase()).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class PublisherMessageConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Publisher<Message<String>>, Publisher<Message<String>>> function() {
|
||||
return flux -> Flux.from(flux).map(m -> MessageBuilder
|
||||
.withPayload(m.getPayload().toUpperCase()).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class MonoConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Flux<String>, Mono<Map<String, Integer>>> function() {
|
||||
return flux -> flux.collect(HashMap::new,
|
||||
(map, word) -> map.merge(word, 1, Integer::sum));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class MessageConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<Message<String>, Message<String>> function() {
|
||||
return m -> MessageBuilder.withPayload(m.getPayload().toUpperCase()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class QualifiedConfiguration {
|
||||
|
||||
@Bean
|
||||
@Qualifier("other")
|
||||
public Function<String, String> function() {
|
||||
return value -> value.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class AliasConfiguration {
|
||||
|
||||
@Bean({ "function", "other" })
|
||||
public Function<String, String> function() {
|
||||
return value -> value.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class RegistrationConfiguration {
|
||||
|
||||
@Bean
|
||||
public FunctionRegistration<Function<String, String>> registration() {
|
||||
return new FunctionRegistration<Function<String, String>>(function(),
|
||||
@@ -825,6 +912,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
public Function<String, String> function() {
|
||||
return value -> value.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -865,6 +953,7 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String value;
|
||||
|
||||
public Foo(String value) {
|
||||
@@ -875,15 +964,17 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Bar {
|
||||
|
||||
private String message;
|
||||
|
||||
public Bar(String value) {
|
||||
@@ -902,4 +993,5 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
* Copyright 2012-2019-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.
|
||||
@@ -26,10 +26,11 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
@@ -47,9 +48,6 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -57,30 +55,34 @@ import reactor.core.publisher.Mono;
|
||||
public class ContextFunctionCatalogInitializerTests {
|
||||
|
||||
private GenericApplicationContext context;
|
||||
|
||||
private FunctionCatalog catalog;
|
||||
|
||||
private FunctionInspector inspector;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lookUps() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properties() {
|
||||
create(PropertiesConfiguration.class, "app.greeting=hello");
|
||||
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat(this.context.getBean("function"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) catalog
|
||||
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function).isInstanceOf(Function.class);
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo");
|
||||
@@ -89,9 +91,10 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
@Test
|
||||
public void value() {
|
||||
create(ValueConfiguration.class, "app.greeting=hello");
|
||||
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat(this.context.getBean("function"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) catalog
|
||||
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function).isInstanceOf(Function.class);
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo");
|
||||
@@ -101,9 +104,10 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
@Ignore
|
||||
public void compose() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat(this.context.getBean("function"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) catalog
|
||||
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) this.catalog
|
||||
.lookup(Supplier.class, "supplier|function");
|
||||
assertThat(supplier).isInstanceOf(Supplier.class);
|
||||
assertThat(supplier.get().blockFirst()).isEqualTo("HELLO");
|
||||
@@ -113,8 +117,9 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void missingType() {
|
||||
create(MissingTypeConfiguration.class);
|
||||
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
|
||||
assertThat(this.context.getBean("function"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "function"))
|
||||
.isInstanceOf(Function.class);
|
||||
// TODO: support for type inference from functional bean registrations
|
||||
}
|
||||
@@ -122,64 +127,70 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
@Test
|
||||
public void configurationFunction() {
|
||||
create(FunctionConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(Function.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(inspector.getOutputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getOutputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Foo.class);
|
||||
assertThat(this.inspector
|
||||
.getInputWrapper(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(Flux.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dependencyInjection() {
|
||||
create(DependencyInjectionConfiguration.class);
|
||||
assertThat(context.getBean("foos")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) catalog.lookup(Function.class, "foos"))
|
||||
assertThat(this.context.getBean("foos")).isInstanceOf(FunctionRegistration.class);
|
||||
assertThat((Function<?, ?>) this.catalog.lookup(Function.class, "foos"))
|
||||
.isInstanceOf(Function.class);
|
||||
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
assertThat(
|
||||
this.inspector.getInputType(this.catalog.lookup(Function.class, "foos")))
|
||||
.isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleFunction() {
|
||||
create(SimpleConfiguration.class);
|
||||
Object bean = context.getBean("function");
|
||||
Object bean = this.context.getBean("function");
|
||||
assertThat(bean).isInstanceOf(FunctionRegistration.class);
|
||||
Function<Flux<String>, Flux<String>> function = catalog.lookup(Function.class,
|
||||
"function");
|
||||
Function<Flux<String>, Flux<String>> function = this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO");
|
||||
assertThat(bean).isNotSameAs(function);
|
||||
assertThat(inspector.getRegistration(function)).isNotNull();
|
||||
assertThat(inspector.getRegistration(function).getType()).isEqualTo(
|
||||
assertThat(this.inspector.getRegistration(function)).isNotNull();
|
||||
assertThat(this.inspector.getRegistration(function).getType()).isEqualTo(
|
||||
FunctionType.from(String.class).to(String.class).wrap(Flux.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleSupplier() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("supplier")).isInstanceOf(FunctionRegistration.class);
|
||||
Supplier<Flux<String>> supplier = catalog.lookup(Supplier.class, "supplier");
|
||||
assertThat(this.context.getBean("supplier"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
Supplier<Flux<String>> supplier = this.catalog.lookup(Supplier.class, "supplier");
|
||||
assertThat(supplier.get().blockFirst()).isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleConsumer() {
|
||||
create(SimpleConfiguration.class);
|
||||
assertThat(context.getBean("consumer")).isInstanceOf(FunctionRegistration.class);
|
||||
Function<Flux<String>, Mono<Void>> consumer = catalog.lookup(Function.class,
|
||||
assertThat(this.context.getBean("consumer"))
|
||||
.isInstanceOf(FunctionRegistration.class);
|
||||
Function<Flux<String>, Mono<Void>> consumer = this.catalog.lookup(Function.class,
|
||||
"consumer");
|
||||
consumer.apply(Flux.just("foo", "bar")).subscribe();
|
||||
assertThat(context.getBean(SimpleConfiguration.class).list).hasSize(2);
|
||||
assertThat(this.context.getBean(SimpleConfiguration.class).list).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overrideGson() {
|
||||
create(GsonConfiguration.class);
|
||||
Gson user = context.getBean(GsonConfiguration.class).gson();
|
||||
Gson bean = context.getBean(Gson.class);
|
||||
Gson user = this.context.getBean(GsonConfiguration.class).gson();
|
||||
Gson bean = this.context.getBean(Gson.class);
|
||||
assertThat(user).isSameAs(bean);
|
||||
}
|
||||
|
||||
@@ -193,7 +204,7 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
|
||||
private void create(ApplicationContextInitializer<GenericApplicationContext>[] types,
|
||||
String... props) {
|
||||
context = new GenericApplicationContext();
|
||||
this.context = new GenericApplicationContext();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
for (String prop : props) {
|
||||
String[] array = StringUtils.delimitedListToStringArray(prop, "=");
|
||||
@@ -202,17 +213,17 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
map.put(key, value);
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
context.getEnvironment().getPropertySources()
|
||||
this.context.getEnvironment().getPropertySources()
|
||||
.addFirst(new MapPropertySource("testProperties", map));
|
||||
}
|
||||
for (ApplicationContextInitializer<GenericApplicationContext> type : types) {
|
||||
type.initialize(context);
|
||||
type.initialize(this.context);
|
||||
}
|
||||
new ContextFunctionCatalogInitializer.ContextFunctionCatalogBeanRegistrar(context)
|
||||
.postProcessBeanDefinitionRegistry(context);
|
||||
context.refresh();
|
||||
catalog = context.getBean(FunctionCatalog.class);
|
||||
inspector = context.getBean(FunctionInspector.class);
|
||||
new ContextFunctionCatalogInitializer.ContextFunctionCatalogBeanRegistrar(
|
||||
this.context).postProcessBeanDefinitionRegistry(this.context);
|
||||
this.context.refresh();
|
||||
this.catalog = this.context.getBean(FunctionCatalog.class);
|
||||
this.inspector = this.context.getBean(FunctionInspector.class);
|
||||
}
|
||||
|
||||
protected static class EmptyConfiguration
|
||||
@@ -221,6 +232,7 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
@Override
|
||||
public void initialize(GenericApplicationContext applicationContext) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class MissingTypeConfiguration
|
||||
@@ -270,8 +282,9 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
|
||||
@Bean
|
||||
public Consumer<String> consumer() {
|
||||
return value -> list.add(value);
|
||||
return value -> this.list.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties("app")
|
||||
@@ -298,7 +311,7 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
|
||||
@Bean
|
||||
public Function<String, String> function() {
|
||||
return value -> greeting + " " + value;
|
||||
return value -> this.greeting + " " + value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -319,7 +332,7 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
|
||||
@Bean
|
||||
public Function<String, String> function() {
|
||||
return value -> greeting + " " + value;
|
||||
return value -> this.greeting + " " + value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -363,6 +376,7 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
public String value() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class FunctionConfiguration
|
||||
@@ -386,9 +400,11 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
public String value() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String value;
|
||||
|
||||
public Foo(String value) {
|
||||
@@ -399,12 +415,13 @@ public class ContextFunctionCatalogInitializerTests {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.function.context.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
@@ -33,14 +30,17 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.ContextFunctionRegistry;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -51,7 +51,9 @@ import reactor.core.publisher.Mono;
|
||||
public class ContextFunctionPostProcessorTests {
|
||||
|
||||
private ContextFunctionRegistry processor = new ContextFunctionRegistry();
|
||||
|
||||
private URLClassLoader classLoader;
|
||||
|
||||
private ClassLoader contextClassLoader;
|
||||
|
||||
@After
|
||||
@@ -60,128 +62,136 @@ public class ContextFunctionPostProcessorTests {
|
||||
this.classLoader.close();
|
||||
}
|
||||
if (Thread.currentThread().getContextClassLoader() != null) {
|
||||
ClassUtils.overrideThreadContextClassLoader(contextClassLoader);
|
||||
ClassUtils.overrideThreadContextClassLoader(this.contextClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicRegistrationFeatures() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registrationThroughMerge() {
|
||||
FunctionRegistration<Foos> registration = new FunctionRegistration<>(new Foos(), "foos");
|
||||
processor.merge(Collections.singletonMap("foos", registration),
|
||||
FunctionRegistration<Foos> registration = new FunctionRegistration<>(new Foos(),
|
||||
"foos");
|
||||
this.processor.merge(Collections.singletonMap("foos", registration),
|
||||
Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap());
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registrationThroughMergeFromNamedFunction() {
|
||||
processor.merge(Collections.emptyMap(), Collections.emptyMap(),
|
||||
this.processor.merge(Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), Collections.singletonMap("foos", new Foos()));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeWithComma() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos,bars");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("Hello 4");
|
||||
assertThat(processor.getRegistration(foos).getNames())
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("foos|bars");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supplierAndFunction() {
|
||||
processor.register(new FunctionRegistration<Supplier<String>>(() -> "foo", "supplier"));
|
||||
processor.register(new FunctionRegistration<Function<String, String>>((x) -> x.toUpperCase(), "function"));
|
||||
this.processor.register(
|
||||
new FunctionRegistration<Supplier<String>>(() -> "foo", "supplier"));
|
||||
this.processor.register(new FunctionRegistration<Function<String, String>>(
|
||||
(x) -> x.toUpperCase(), "function"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) processor.lookupSupplier("supplier|function");
|
||||
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) this.processor
|
||||
.lookupSupplier("supplier|function");
|
||||
assertThat(supplier.get().blockFirst()).isEqualTo("FOO");
|
||||
assertThat(processor.getRegistration(supplier).getNames()).containsExactly("supplier|function");
|
||||
assertThat(this.processor.getRegistration(supplier).getNames())
|
||||
.containsExactly("supplier|function");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void supplierAndConsumer() {
|
||||
processor.register(new FunctionRegistration<Supplier<String>>(() -> "foo", "supplier"));
|
||||
processor.register(new FunctionRegistration<Consumer<String>>(System.out::println, "consumer"));
|
||||
Supplier<Mono<Void>> supplier = (Supplier<Mono<Void>>) processor.lookupSupplier("supplier|consumer");
|
||||
this.processor.register(
|
||||
new FunctionRegistration<Supplier<String>>(() -> "foo", "supplier"));
|
||||
this.processor.register(new FunctionRegistration<Consumer<String>>(
|
||||
System.out::println, "consumer"));
|
||||
Supplier<Mono<Void>> supplier = (Supplier<Mono<Void>>) this.processor
|
||||
.lookupSupplier("supplier|consumer");
|
||||
assertNull(supplier.get().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compose() {
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new Bars(), "bars"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos|bars");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("Hello 4");
|
||||
assertThat(processor.getRegistration(foos).getNames())
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("foos|bars");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void composeWrapper() {
|
||||
processor.register(new FunctionRegistration<>(new WrappedSource(), "ints"));
|
||||
processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(new WrappedSource(), "ints"));
|
||||
this.processor.register(new FunctionRegistration<>(new Foos(), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<String>> foos = (Supplier<Flux<String>>) processor
|
||||
Supplier<Flux<String>> foos = (Supplier<Flux<String>>) this.processor
|
||||
.lookupSupplier("ints|foos");
|
||||
assertThat(foos.get().blockFirst()).isEqualTo("8");
|
||||
assertThat(processor.getRegistration(foos).getNames())
|
||||
assertThat(this.processor.getRegistration(foos).getNames())
|
||||
.containsExactly("ints|foos");
|
||||
assertThat(processor.getRegistration(foos).getType().getOutputWrapper())
|
||||
assertThat(this.processor.getRegistration(foos).getType().getOutputWrapper())
|
||||
.isEqualTo(Flux.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isolatedFunction() {
|
||||
contextClassLoader = ClassUtils
|
||||
this.contextClassLoader = ClassUtils
|
||||
.overrideThreadContextClassLoader(getClass().getClassLoader());
|
||||
processor.register(new FunctionRegistration<>(create(Foos.class), "foos"));
|
||||
this.processor.register(new FunctionRegistration<>(create(Foos.class), "foos"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) processor
|
||||
Function<Flux<Integer>, Flux<String>> foos = (Function<Flux<Integer>, Flux<String>>) this.processor
|
||||
.lookupFunction("foos");
|
||||
assertThat(foos.apply(Flux.just(2)).blockFirst()).isEqualTo("4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isolatedSupplier() {
|
||||
contextClassLoader = ClassUtils
|
||||
this.contextClassLoader = ClassUtils
|
||||
.overrideThreadContextClassLoader(getClass().getClassLoader());
|
||||
processor.register(
|
||||
new FunctionRegistration<>(create(Source.class), "source"));
|
||||
this.processor
|
||||
.register(new FunctionRegistration<>(create(Source.class), "source"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<Flux<Integer>> source = (Supplier<Flux<Integer>>) processor
|
||||
Supplier<Flux<Integer>> source = (Supplier<Flux<Integer>>) this.processor
|
||||
.lookupSupplier("source");
|
||||
assertThat(source.get().blockFirst()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isolatedConsumer() {
|
||||
contextClassLoader = ClassUtils
|
||||
this.contextClassLoader = ClassUtils
|
||||
.overrideThreadContextClassLoader(getClass().getClassLoader());
|
||||
Object target = create(Sink.class);
|
||||
processor.register(new FunctionRegistration<>(target, "sink"));
|
||||
this.processor.register(new FunctionRegistration<>(target, "sink"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Flux<String>, Mono<Void>> sink = (Function<Flux<String>, Mono<Void>>) processor
|
||||
Function<Flux<String>, Mono<Void>> sink = (Function<Flux<String>, Mono<Void>>) this.processor
|
||||
.lookupFunction("sink");
|
||||
sink.apply(Flux.just("Hello")).subscribe();
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -199,14 +209,14 @@ public class ContextFunctionPostProcessorTests {
|
||||
String pathEntry = jcpEntries.nextToken();
|
||||
try {
|
||||
urls.add(new File(pathEntry).toURI().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
}
|
||||
}
|
||||
this.classLoader = new URLClassLoader(
|
||||
urls.toArray(new URL[0]),
|
||||
this.classLoader = new URLClassLoader(urls.toArray(new URL[0]),
|
||||
getClass().getClassLoader().getParent());
|
||||
return BeanUtils
|
||||
.instantiateClass(ClassUtils.resolveClassName(type.getName(), classLoader));
|
||||
return BeanUtils.instantiateClass(
|
||||
ClassUtils.resolveClassName(type.getName(), this.classLoader));
|
||||
}
|
||||
|
||||
public static class Foos implements Function<Integer, String> {
|
||||
@@ -239,7 +249,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
public void accept(String t) {
|
||||
assertThat(ClassUtils.resolveClassName(Bar.class.getName(), null)
|
||||
.getClassLoader()).isEqualTo(getClass().getClassLoader());
|
||||
values.add(t);
|
||||
this.values.add(t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -263,6 +273,7 @@ public class ContextFunctionPostProcessorTests {
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String value;
|
||||
|
||||
public Foo(String value) {
|
||||
@@ -273,15 +284,17 @@ public class ContextFunctionPostProcessorTests {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Bar {
|
||||
|
||||
private String message;
|
||||
|
||||
public Bar(String value) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||
@@ -28,11 +29,9 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* Test that spring.main.sources works with the functional approach.
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@@ -45,15 +44,18 @@ public class FunctionalStringSourceTests {
|
||||
|
||||
@Test
|
||||
public void words() throws Exception {
|
||||
Function<Flux<String>, Flux<String>> function = catalog.lookup(Function.class,
|
||||
"function");
|
||||
Function<Flux<String>, Flux<String>> function = this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO");
|
||||
}
|
||||
|
||||
protected static class TestConfiguration implements Function<String, String> {
|
||||
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
@@ -28,8 +29,6 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -43,16 +42,19 @@ public class FunctionalTests {
|
||||
|
||||
@Test
|
||||
public void words() throws Exception {
|
||||
Function<Flux<String>, Flux<String>> function = catalog.lookup(Function.class,
|
||||
"function");
|
||||
Function<Flux<String>, Flux<String>> function = this.catalog
|
||||
.lookup(Function.class, "function");
|
||||
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("FOO");
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
protected static class TestConfiguration implements Function<String, String> {
|
||||
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return value.toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -23,8 +23,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class FooConfiguration {
|
||||
|
||||
@Bean
|
||||
public Function<String, Foo> foos(String foo) {
|
||||
return value -> new Foo(foo + ": " + value.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,9 +29,11 @@ import org.springframework.stereotype.Component;
|
||||
@Component("function")
|
||||
public class ScannedFunction
|
||||
implements Function<Map<String, String>, Map<String, String>> {
|
||||
|
||||
@Override
|
||||
public Map<String, String> apply(Map<String, String> m) {
|
||||
return m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
|
||||
e -> e.getValue().toString().toUpperCase()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,10 +29,11 @@ import org.springframework.context.annotation.Configuration;
|
||||
*/
|
||||
@Configuration
|
||||
public class GenericFunction {
|
||||
|
||||
@Bean
|
||||
public Function<Map<String, String>, Map<String, String>> function() {
|
||||
return m -> m.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
|
||||
e -> e.getValue().toString().toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -43,29 +42,29 @@ public class JsonMapperTests {
|
||||
|
||||
private JsonMapper mapper;
|
||||
|
||||
public JsonMapperTests(JsonMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Parameters
|
||||
public static List<Object[]> params() {
|
||||
return Arrays.asList(new Object[] { new GsonMapper(new Gson()) },
|
||||
new Object[] { new JacksonMapper(new ObjectMapper()) });
|
||||
}
|
||||
|
||||
public JsonMapperTests(JsonMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vanillaArray() {
|
||||
String json = "[{\"value\":\"foo\"},{\"value\":\"foo\"}]";
|
||||
List<Foo> list = mapper.toObject(json,
|
||||
List<Foo> list = this.mapper.toObject(json,
|
||||
ResolvableType.forClassWithGenerics(List.class, Foo.class).getType());
|
||||
assertThat(list).hasSize(2);
|
||||
assertThat(list.get(0).getValue()).isEqualTo("foo");
|
||||
assertThat(mapper.toString(list)).isEqualTo(json);
|
||||
assertThat(this.mapper.toString(list)).isEqualTo(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intArray() {
|
||||
List<Integer> list = mapper.toObject("[123,456]",
|
||||
List<Integer> list = this.mapper.toObject("[123,456]",
|
||||
ResolvableType.forClassWithGenerics(List.class, Integer.class).getType());
|
||||
assertThat(list).hasSize(2);
|
||||
assertThat(list.get(0)).isEqualTo(123);
|
||||
@@ -73,7 +72,7 @@ public class JsonMapperTests {
|
||||
|
||||
@Test
|
||||
public void emptyArray() {
|
||||
List<Foo> list = mapper.toObject("[]",
|
||||
List<Foo> list = this.mapper.toObject("[]",
|
||||
ResolvableType.forClassWithGenerics(List.class, Foo.class).getType());
|
||||
assertThat(list).hasSize(0);
|
||||
}
|
||||
@@ -81,28 +80,29 @@ public class JsonMapperTests {
|
||||
@Test
|
||||
public void vanillaObject() {
|
||||
String json = "{\"value\":\"foo\"}";
|
||||
Foo foo = mapper.toObject(json, Foo.class);
|
||||
Foo foo = this.mapper.toObject(json, Foo.class);
|
||||
assertThat(foo.getValue()).isEqualTo("foo");
|
||||
assertThat(mapper.toString(foo)).isEqualTo(json);
|
||||
assertThat(this.mapper.toString(foo)).isEqualTo(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intValue() {
|
||||
int foo = mapper.toObject("123", Integer.class);
|
||||
int foo = this.mapper.toObject("123", Integer.class);
|
||||
assertThat(foo).isEqualTo(123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty() {
|
||||
Foo foo = mapper.toObject("{}", Foo.class);
|
||||
Foo foo = this.mapper.toObject("{}", Foo.class);
|
||||
assertThat(foo.getValue()).isNull();
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
@@ -110,4 +110,5 @@ public class JsonMapperTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user