/*
* Copyright 2016 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.dsl.context;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.Lifecycle;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.StandardIntegrationFlow;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
/**
* Instances of this classes are returned as a result of
* {@link IntegrationFlowContext#registration(IntegrationFlow)} invocation
* and provide an API for some useful {@link IntegrationFlow} options and its lifecycle.
*
* @author Artem Bilan
* @since 5.0
*
* @see IntegrationFlowContext
*/
public class IntegrationFlowRegistration {
private IntegrationFlow integrationFlow;
private IntegrationFlowContext integrationFlowContext;
private String id;
private MessageChannel inputChannel;
private MessagingTemplate messagingTemplate;
private ConfigurableListableBeanFactory beanFactory;
IntegrationFlowRegistration(IntegrationFlow integrationFlow) {
this.integrationFlow = integrationFlow;
}
void setBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory; // NOSONAR (synchronization)
}
void setIntegrationFlowContext(IntegrationFlowContext integrationFlowContext) {
this.integrationFlowContext = integrationFlowContext;
}
void setId(String id) {
this.id = id;
}
void setIntegrationFlow(IntegrationFlow integrationFlow) {
this.integrationFlow = integrationFlow;
}
public String getId() {
return this.id;
}
public IntegrationFlow getIntegrationFlow() {
return this.integrationFlow;
}
public MessageChannel getInputChannel() {
if (this.inputChannel == null) {
if (this.integrationFlow instanceof StandardIntegrationFlow) {
StandardIntegrationFlow integrationFlow = (StandardIntegrationFlow) this.integrationFlow;
Object next = integrationFlow.getIntegrationComponents().iterator().next();
if (next instanceof MessageChannel) {
this.inputChannel = (MessageChannel) next;
}
else {
throw new IllegalStateException("The 'IntegrationFlow' [" + integrationFlow + "] " +
"doesn't start with 'MessageChannel' for direct message sending.");
}
}
else {
throw new IllegalStateException("Only 'StandardIntegrationFlow' instances " +
"(e.g. extracted from 'IntegrationFlow' Lambdas) can be used " +
"for direct 'send' operation. " +
"But [" + this.integrationFlow + "] ins't one of them.\n" +
"Consider 'BeanFactory.getBean()' usage for sending messages " +
"to the required 'MessageChannel'.");
}
}
return this.inputChannel;
}
/**
* Obtain a {@link MessagingTemplate} with its default destination set to the input channel
* of the {@link IntegrationFlow}.
* <p> Any {@link IntegrationFlow} bean (not only manually registered) can be used for this method.
* <p> If {@link IntegrationFlow} doesn't start with the {@link MessageChannel}, the
* {@link IllegalStateException} is thrown.
* @return the {@link MessagingTemplate} instance
*/
public MessagingTemplate getMessagingTemplate() {
if (this.messagingTemplate == null) {
this.messagingTemplate = new MessagingTemplate(getInputChannel()) {
@Override
public Message<?> receive() {
return receiveAndConvert(Message.class);
}
@Override
public <T> T receiveAndConvert(Class<T> targetClass) {
throw new UnsupportedOperationException("The 'receive()/receiveAndConvert()' " +
"isn't supported on the 'IntegrationFlow' input channel.");
}
};
this.messagingTemplate.setBeanFactory(this.beanFactory);
}
return this.messagingTemplate;
}
public void start() {
if (this.integrationFlow instanceof Lifecycle) {
((Lifecycle) this.integrationFlow).start();
}
else {
throw new IllegalStateException("For 'autoStartup' mode the 'IntegrationFlow' " +
"must be an instance of 'Lifecycle'.\n" +
"Consider to implement it for [" + this.integrationFlow + "]. " +
"Or start dependent components on their own.");
}
}
public void stop() {
if (this.integrationFlow instanceof Lifecycle) {
((Lifecycle) this.integrationFlow).stop();
}
}
/**
* Destroy the {@link IntegrationFlow} bean (as well as all its dependant beans)
* and clean up all the local cache for it.
*/
public void destroy() {
this.integrationFlowContext.remove(this.id);
}
}