Use Void as input type for Supplier, etc.
This commit is contained in:
@@ -18,7 +18,9 @@ package org.springframework.cloud.function.context;
|
|||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
|
|
||||||
@@ -219,6 +221,9 @@ public class FunctionType {
|
|||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||||
if (parameterizedType.getActualTypeArguments().length == 1) {
|
if (parameterizedType.getActualTypeArguments().length == 1) {
|
||||||
|
if (isVoid(parameterizedType, paramType)) {
|
||||||
|
return Void.class;
|
||||||
|
}
|
||||||
// There's only one
|
// There's only one
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
@@ -245,6 +250,17 @@ public class FunctionType {
|
|||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isVoid(ParameterizedType parameterizedType, ParamType paramType) {
|
||||||
|
Class<?> rawType = extractClass(parameterizedType.getRawType(), paramType);
|
||||||
|
if (Consumer.class.isAssignableFrom(rawType) && paramType.isOutput()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Supplier.class.isAssignableFrom(rawType) && paramType.isInput()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private Type extractNestedType(ParamType paramType, Type param) {
|
private Type extractNestedType(ParamType paramType, Type param) {
|
||||||
if (!paramType.isInnerWrapper() && param instanceof ParameterizedType) {
|
if (!paramType.isInnerWrapper() && param instanceof ParameterizedType) {
|
||||||
if (((ParameterizedType) param).getRawType().getTypeName()
|
if (((ParameterizedType) param).getRawType().getTypeName()
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ package org.springframework.cloud.function.context;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -99,6 +101,30 @@ public class FunctionTypeTests {
|
|||||||
assertThat(function.isMessage()).isEqualTo(false);
|
assertThat(function.isMessage()).isEqualTo(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void pojoConsumerFromType() {
|
||||||
|
Type type = ResolvableType.forClassWithGenerics(Consumer.class, Foo.class)
|
||||||
|
.getType();
|
||||||
|
FunctionType function = new FunctionType(type);
|
||||||
|
assertThat(function.getInputType()).isEqualTo(Foo.class);
|
||||||
|
assertThat(function.getOutputType()).isEqualTo(Void.class);
|
||||||
|
assertThat(function.getInputWrapper()).isEqualTo(Foo.class);
|
||||||
|
assertThat(function.getOutputWrapper()).isEqualTo(Void.class);
|
||||||
|
assertThat(function.isMessage()).isEqualTo(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void pojoSupplierFromType() {
|
||||||
|
Type type = ResolvableType.forClassWithGenerics(Supplier.class, Foo.class)
|
||||||
|
.getType();
|
||||||
|
FunctionType function = new FunctionType(type);
|
||||||
|
assertThat(function.getInputType()).isEqualTo(Void.class);
|
||||||
|
assertThat(function.getOutputType()).isEqualTo(Foo.class);
|
||||||
|
assertThat(function.getInputWrapper()).isEqualTo(Void.class);
|
||||||
|
assertThat(function.getOutputWrapper()).isEqualTo(Foo.class);
|
||||||
|
assertThat(function.isMessage()).isEqualTo(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void plainFunctionFromApi() {
|
public void plainFunctionFromApi() {
|
||||||
FunctionType function = FunctionType.from(Integer.class).to(String.class);
|
FunctionType function = FunctionType.from(Integer.class).to(String.class);
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
assertThat(catalog.lookupFunction("names,foos")).isNull();
|
assertThat(catalog.lookupFunction("names,foos")).isNull();
|
||||||
assertThat(inspector.getOutputType(catalog.lookupSupplier("names,foos")))
|
assertThat(inspector.getOutputType(catalog.lookupSupplier("names,foos")))
|
||||||
.isAssignableFrom(Foo.class);
|
.isAssignableFrom(Foo.class);
|
||||||
// The input type is the same as the output type of the first element in the chain
|
// The input type is the same as the input type of the first element in the chain
|
||||||
assertThat(inspector.getInputType(catalog.lookupSupplier("names,foos")))
|
assertThat(inspector.getInputType(catalog.lookupSupplier("names,foos")))
|
||||||
.isAssignableFrom(String.class);
|
.isAssignableFrom(Void.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -148,9 +148,9 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
assertThat(catalog.lookupFunction("foos,print")).isNull();
|
assertThat(catalog.lookupFunction("foos,print")).isNull();
|
||||||
assertThat(inspector.getInputType(catalog.lookupConsumer("foos,print")))
|
assertThat(inspector.getInputType(catalog.lookupConsumer("foos,print")))
|
||||||
.isAssignableFrom(String.class);
|
.isAssignableFrom(String.class);
|
||||||
// The output type is the same as the input type of the last element in the chain
|
// The output type is the same as the output type of the last element in the chain
|
||||||
assertThat(inspector.getOutputType(catalog.lookupConsumer("foos,print")))
|
assertThat(inspector.getOutputType(catalog.lookupConsumer("foos,print")))
|
||||||
.isAssignableFrom(Foo.class);
|
.isAssignableFrom(Void.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -543,7 +543,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
|
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class SingletonMessageConfiguration implements BeanFactoryPostProcessor {
|
protected static class SingletonMessageConfiguration
|
||||||
|
implements BeanFactoryPostProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||||
@@ -570,7 +571,8 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class SingletonMessageFunction implements Function<Message<Integer>, Message<String>> {
|
protected static class SingletonMessageFunction
|
||||||
|
implements Function<Message<Integer>, Message<String>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message<String> apply(Message<Integer> input) {
|
public Message<String> apply(Message<Integer> input) {
|
||||||
@@ -672,24 +674,28 @@ public class ContextFunctionCatalogAutoConfigurationTests {
|
|||||||
|
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class FactoryBeanConfiguration implements BeanDefinitionRegistryPostProcessor {
|
protected static class FactoryBeanConfiguration
|
||||||
|
implements BeanDefinitionRegistryPostProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(FunctionFactoryBean.class);
|
throws BeansException {
|
||||||
|
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||||
|
FunctionFactoryBean.class);
|
||||||
beanDefinition.setSource(new DescriptiveResource("Function"));
|
beanDefinition.setSource(new DescriptiveResource("Function"));
|
||||||
registry.registerBeanDefinition("function", beanDefinition);
|
registry.registerBeanDefinition("function", beanDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||||
|
throws BeansException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FunctionFactoryBean
|
||||||
private static class FunctionFactoryBean extends AbstractFactoryBean<Function<String, String>> {
|
extends AbstractFactoryBean<Function<String, String>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getObjectType() {
|
public Class<?> getObjectType() {
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ public class BetterGsonHttpMessageConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
|
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
|
||||||
throws IOException, HttpMessageNotReadableException {
|
throws IOException, HttpMessageNotReadableException {
|
||||||
|
|
||||||
@@ -123,7 +122,6 @@ public class BetterGsonHttpMessageConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
||||||
throws IOException, HttpMessageNotReadableException {
|
throws IOException, HttpMessageNotReadableException {
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ public class FluxReturnValueHandler implements AsyncHandlerMethodReturnValueHand
|
|||||||
}
|
}
|
||||||
|
|
||||||
MediaType mediaType = null;
|
MediaType mediaType = null;
|
||||||
if (isPlainText(webRequest) && CharSequence.class.isAssignableFrom(type)) {
|
if (isPlainText(webRequest) && (CharSequence.class.isAssignableFrom(type)
|
||||||
|
|| Void.class.isAssignableFrom(type))) {
|
||||||
mediaType = MediaType.TEXT_PLAIN;
|
mediaType = MediaType.TEXT_PLAIN;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user