Turned on checkstyle

This commit is contained in:
Marcin Grzejszczak
2019-02-01 15:48:32 +01:00
parent 94e9b8f2f8
commit e4b08a083c
268 changed files with 5114 additions and 3993 deletions

View File

@@ -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);
}

View File

@@ -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");
}
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;
}
}
}

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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.

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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": ""
}
]
}

View File

@@ -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