use of org.springframework.cloud.function.context.FunctionCatalog in project spring-cloud-stream by spring-cloud.
the class FunctionConfiguration method supplierInitializer.
/*
* Binding initializer responsible only for Suppliers
*/
@Bean
InitializingBean supplierInitializer(FunctionCatalog functionCatalog, StreamFunctionProperties functionProperties, GenericApplicationContext context, BindingServiceProperties serviceProperties, @Nullable List<BindableFunctionProxyFactory> proxyFactories, StreamBridge streamBridge, TaskScheduler taskScheduler) {
if (CollectionUtils.isEmpty(proxyFactories)) {
return null;
}
return new InitializingBean() {
@SuppressWarnings("rawtypes")
@Override
public void afterPropertiesSet() throws Exception {
for (BindableFunctionProxyFactory proxyFactory : proxyFactories) {
FunctionInvocationWrapper functionWrapper = functionCatalog.lookup(proxyFactory.getFunctionDefinition());
if (functionWrapper != null && functionWrapper.isSupplier()) {
// gather output content types
List<String> contentTypes = new ArrayList<String>();
if (proxyFactory.getOutputs().size() == 0) {
return;
}
Assert.isTrue(proxyFactory.getOutputs().size() == 1, "Supplier with multiple outputs is not supported at the moment.");
String outputName = proxyFactory.getOutputs().iterator().next();
BindingProperties bindingProperties = serviceProperties.getBindingProperties(outputName);
ProducerProperties producerProperties = bindingProperties.getProducer();
if (!(bindingProperties.getProducer() != null && producerProperties.isUseNativeEncoding())) {
contentTypes.add(bindingProperties.getContentType());
}
// see https://github.com/spring-cloud/spring-cloud-stream/issues/2027
String functionDefinition = proxyFactory.getFunctionDefinition();
String[] functionNames = StringUtils.delimitedListToStringArray(functionDefinition.replaceAll(",", "|").trim(), "|");
Function supplier = null;
Function function = null;
if (!ObjectUtils.isEmpty(functionNames) && functionNames.length > 1) {
String supplierName = functionNames[0];
String remainingFunctionDefinition = StringUtils.arrayToCommaDelimitedString(Arrays.copyOfRange(functionNames, 1, functionNames.length));
supplier = functionCatalog.lookup(supplierName);
function = functionCatalog.lookup(remainingFunctionDefinition, contentTypes.toArray(new String[0]));
if (!((FunctionInvocationWrapper) supplier).isOutputTypePublisher() && ((FunctionInvocationWrapper) function).isInputTypePublisher()) {
functionWrapper = null;
} else {
functionWrapper = functionCatalog.lookup(proxyFactory.getFunctionDefinition(), contentTypes.toArray(new String[0]));
}
} else {
functionWrapper = functionCatalog.lookup(proxyFactory.getFunctionDefinition(), contentTypes.toArray(new String[0]));
}
Publisher<Object> beginPublishingTrigger = setupBindingTrigger(context);
if (!functionProperties.isComposeFrom() && !functionProperties.isComposeTo()) {
String integrationFlowName = proxyFactory.getFunctionDefinition() + "_integrationflow";
PollableBean pollable = extractPollableAnnotation(functionProperties, context, proxyFactory);
if (functionWrapper != null) {
// Type functionType = functionWrapper.getFunctionType();
IntegrationFlow integrationFlow = integrationFlowFromProvidedSupplier(new PartitionAwareFunctionWrapper(functionWrapper, context, producerProperties), beginPublishingTrigger, pollable, context, taskScheduler, producerProperties, outputName).route(Message.class, message -> {
if (message.getHeaders().get("spring.cloud.stream.sendto.destination") != null) {
String destinationName = (String) message.getHeaders().get("spring.cloud.stream.sendto.destination");
return streamBridge.resolveDestination(destinationName, producerProperties, null);
}
return outputName;
}).get();
IntegrationFlow postProcessedFlow = (IntegrationFlow) context.getAutowireCapableBeanFactory().applyBeanPostProcessorsBeforeInitialization(integrationFlow, integrationFlowName);
context.registerBean(integrationFlowName, IntegrationFlow.class, () -> postProcessedFlow);
} else {
// Type functionType = ((FunctionInvocationWrapper) supplier).getFunctionType();
IntegrationFlow integrationFlow = integrationFlowFromProvidedSupplier(new PartitionAwareFunctionWrapper(supplier, context, producerProperties), beginPublishingTrigger, pollable, context, taskScheduler, producerProperties, outputName).channel(c -> c.direct()).fluxTransform((Function<? super Flux<Message<Object>>, ? extends Publisher<Object>>) function).route(Message.class, message -> {
if (message.getHeaders().get("spring.cloud.stream.sendto.destination") != null) {
String destinationName = (String) message.getHeaders().get("spring.cloud.stream.sendto.destination");
return streamBridge.resolveDestination(destinationName, producerProperties, null);
}
return outputName;
}).get();
IntegrationFlow postProcessedFlow = (IntegrationFlow) context.getAutowireCapableBeanFactory().applyBeanPostProcessorsBeforeInitialization(integrationFlow, integrationFlowName);
context.registerBean(integrationFlowName, IntegrationFlow.class, () -> postProcessedFlow);
}
}
}
}
}
};
}
use of org.springframework.cloud.function.context.FunctionCatalog in project spring-cloud-stream by spring-cloud.
the class DefaultBinderFactory method getBinderInstance.
@SuppressWarnings("unchecked")
private <T> Binder<T, ConsumerProperties, ProducerProperties> getBinderInstance(String configurationName) {
if (!this.binderInstanceCache.containsKey(configurationName)) {
logger.info("Creating binder: " + configurationName);
BinderConfiguration binderConfiguration = this.binderConfigurations.get(configurationName);
Assert.state(binderConfiguration != null, "Unknown binder configuration: " + configurationName);
BinderType binderType = this.binderTypeRegistry.get(binderConfiguration.getBinderType());
Assert.notNull(binderType, "Binder type " + binderConfiguration.getBinderType() + " is not defined");
Map<String, Object> binderProperties = new HashMap<>();
this.flatten(null, binderConfiguration.getProperties(), binderProperties);
ConfigurableApplicationContext binderProducingContext = this.initializeBinderContextSimple(configurationName, binderProperties, binderType, binderConfiguration);
Map<String, MessageConverter> messageConverters = binderProducingContext.getBeansOfType(MessageConverter.class);
if (!CollectionUtils.isEmpty(messageConverters) && !ObjectUtils.isEmpty(context.getBeansOfType(FunctionCatalog.class))) {
FunctionCatalog functionCatalog = this.context.getBean(FunctionCatalog.class);
if (functionCatalog instanceof SimpleFunctionRegistry) {
((SimpleFunctionRegistry) functionCatalog).addMessageConverters(messageConverters.values());
}
}
Binder<T, ?, ?> binder = binderProducingContext.getBean(Binder.class);
/*
* This will ensure that application defined errorChannel and other beans are
* accessible within binder's context (see
* https://github.com/spring-cloud/spring-cloud-stream/issues/1384)
*/
if (this.context != null && binder instanceof ApplicationContextAware) {
((ApplicationContextAware) binder).setApplicationContext(this.context);
}
if (!CollectionUtils.isEmpty(this.listeners)) {
for (Listener binderFactoryListener : this.listeners) {
binderFactoryListener.afterBinderContextInitialized(configurationName, binderProducingContext);
}
}
logger.info("Caching the binder: " + configurationName);
this.binderInstanceCache.put(configurationName, new SimpleImmutableEntry<>(binder, binderProducingContext));
}
logger.info("Retrieving cached binder: " + configurationName);
return (Binder<T, ConsumerProperties, ProducerProperties>) this.binderInstanceCache.get(configurationName).getKey();
}
Aggregations