Add support for Message<Foo> in stream apps
The FunctionInspector needs to be able to distinguish between a function of Flux<Foo> and a function of Flux<Message<Foo>>. Then it can do the conversion a level below. Only supports Message->Message or POJO->POJO (no mixtures), so there is only one new method in FunctionInspector. No support in the web endpoints yet. But it's probably not so hard to add.
This commit is contained in:
@@ -62,6 +62,7 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.type.StandardMethodMetadata;
|
||||
import org.springframework.core.type.classreading.MethodMetadataReadingVisitor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -108,6 +109,11 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMessage(String name) {
|
||||
return processor.isMessage(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getInputWrapper(String name) {
|
||||
return processor.findInputWrapper(name);
|
||||
@@ -472,14 +478,19 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
Type typeArgumentAtIndex = parameterizedType
|
||||
.getActualTypeArguments()[index];
|
||||
if (typeArgumentAtIndex instanceof ParameterizedType
|
||||
&& FunctionInspector.isWrapper(
|
||||
((ParameterizedType) typeArgumentAtIndex).getRawType())
|
||||
&& !paramType.isWrapper()) {
|
||||
param = ((ParameterizedType) typeArgumentAtIndex)
|
||||
.getActualTypeArguments()[0];
|
||||
if (FunctionInspector.isWrapper(
|
||||
((ParameterizedType) typeArgumentAtIndex).getRawType())) {
|
||||
param = ((ParameterizedType) typeArgumentAtIndex)
|
||||
.getActualTypeArguments()[0];
|
||||
param = extractNestedType(paramType, param);
|
||||
}
|
||||
else {
|
||||
param = extractNestedType(paramType, typeArgumentAtIndex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
param = typeArgumentAtIndex;
|
||||
param = extractNestedType(paramType, typeArgumentAtIndex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -488,6 +499,16 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
return param;
|
||||
}
|
||||
|
||||
private Type extractNestedType(ParamType paramType, Type param) {
|
||||
if (!paramType.isInnerWrapper()
|
||||
&& param.getTypeName().startsWith(Message.class.getName())) {
|
||||
if (param instanceof ParameterizedType) {
|
||||
param = ((ParameterizedType) param).getActualTypeArguments()[0];
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
private Object getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
if (field == null) {
|
||||
@@ -497,6 +518,19 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
return ReflectionUtils.getField(field, target);
|
||||
}
|
||||
|
||||
private boolean isMessage(String name) {
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return false;
|
||||
}
|
||||
return Message.class.isAssignableFrom(findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.INPUT_INNER_WRAPPER))
|
||||
|| Message.class.isAssignableFrom(findType(name,
|
||||
(AbstractBeanDefinition) registry.getBeanDefinition(name),
|
||||
ParamType.OUTPUT_INNER_WRAPPER));
|
||||
|
||||
}
|
||||
|
||||
private Class<?> findInputWrapper(String name) {
|
||||
if (name == null || !registry.containsBeanDefinition(name)) {
|
||||
return Object.class;
|
||||
@@ -533,19 +567,25 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
static enum ParamType {
|
||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER;
|
||||
INPUT, OUTPUT, INPUT_WRAPPER, OUTPUT_WRAPPER, INPUT_INNER_WRAPPER, OUTPUT_INNER_WRAPPER;
|
||||
|
||||
public boolean isOutput() {
|
||||
return this == OUTPUT || this == OUTPUT_WRAPPER;
|
||||
return this == OUTPUT || this == OUTPUT_WRAPPER
|
||||
|| this == OUTPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isInput() {
|
||||
return this == INPUT || this == INPUT_WRAPPER;
|
||||
return this == INPUT || this == INPUT_WRAPPER
|
||||
|| this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isWrapper() {
|
||||
return this == OUTPUT_WRAPPER || this == INPUT_WRAPPER;
|
||||
}
|
||||
|
||||
public boolean isInnerWrapper() {
|
||||
return this == OUTPUT_INNER_WRAPPER || this == INPUT_INNER_WRAPPER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import reactor.core.publisher.Mono;
|
||||
*/
|
||||
public interface FunctionInspector {
|
||||
|
||||
boolean isMessage(String name);
|
||||
|
||||
Class<?> getInputType(String name);
|
||||
|
||||
Class<?> getOutputType(String name);
|
||||
|
||||
Reference in New Issue
Block a user