/*
* Copyright 2014-2017 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.amqp.rabbit.config;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import org.aopalliance.aop.Advice;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpoint;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.ErrorHandler;
import org.springframework.util.backoff.BackOff;
import org.springframework.util.backoff.FixedBackOff;
/**
* Base {@link RabbitListenerContainerFactory} for Spring's base container implementation.
* @param <C> the container type.
* @author Stephane Nicoll
* @author Gary Russell
* @author Artem Bilan
*
* @since 1.4
*
* @see AbstractMessageListenerContainer
*/
public abstract class AbstractRabbitListenerContainerFactory<C extends AbstractMessageListenerContainer>
implements RabbitListenerContainerFactory<C>, ApplicationContextAware, ApplicationEventPublisherAware {
protected final Log logger = LogFactory.getLog(getClass());
private ConnectionFactory connectionFactory;
private ErrorHandler errorHandler;
private MessageConverter messageConverter;
private AcknowledgeMode acknowledgeMode;
private Boolean channelTransacted;
private Executor taskExecutor;
private PlatformTransactionManager transactionManager;
private Integer prefetchCount;
private Boolean defaultRequeueRejected;
private Advice[] adviceChain;
private BackOff recoveryBackOff;
private Boolean missingQueuesFatal;
private Boolean mismatchedQueuesFatal;
private ConsumerTagStrategy consumerTagStrategy;
private Long idleEventInterval;
private Long failedDeclarationRetryInterval;
private ApplicationEventPublisher applicationEventPublisher;
private ApplicationContext applicationContext;
private Boolean autoStartup;
private Integer phase;
protected final AtomicInteger counter = new AtomicInteger();
/**
* @param connectionFactory The connection factory.
* @see AbstractMessageListenerContainer#setConnectionFactory(ConnectionFactory)
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
* @param errorHandler The error handler.
* @see AbstractMessageListenerContainer#setErrorHandler(org.springframework.util.ErrorHandler)
*/
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
/**
* @param messageConverter the message converter to use
* @see AbstractMessageListenerContainer#setMessageConverter(MessageConverter)
*/
public void setMessageConverter(MessageConverter messageConverter) {
this.messageConverter = messageConverter;
}
/**
* @param acknowledgeMode the acknowledge mode to set. Defaults to {@link AcknowledgeMode#AUTO}
* @see AbstractMessageListenerContainer#setAcknowledgeMode(AcknowledgeMode)
*/
public void setAcknowledgeMode(AcknowledgeMode acknowledgeMode) {
this.acknowledgeMode = acknowledgeMode;
}
/**
* @param channelTransacted the flag value to set
* @see AbstractMessageListenerContainer#setChannelTransacted
*/
public void setChannelTransacted(Boolean channelTransacted) {
this.channelTransacted = channelTransacted;
}
/**
* @param taskExecutor the {@link Executor} to use.
* @see SimpleMessageListenerContainer#setTaskExecutor
*/
public void setTaskExecutor(Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
* @param transactionManager the {@link PlatformTransactionManager} to use.
* @see SimpleMessageListenerContainer#setTransactionManager
*/
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* @param prefetch the prefetch count
* @see SimpleMessageListenerContainer#setPrefetchCount(int)
*/
public void setPrefetchCount(Integer prefetch) {
this.prefetchCount = prefetch;
}
/**
* @param requeueRejected true to reject by default.
* @see SimpleMessageListenerContainer#setDefaultRequeueRejected
*/
public void setDefaultRequeueRejected(Boolean requeueRejected) {
this.defaultRequeueRejected = requeueRejected;
}
/**
* @param adviceChain the advice chain to set.
* @see SimpleMessageListenerContainer#setAdviceChain
*/
public void setAdviceChain(Advice... adviceChain) {
this.adviceChain = adviceChain;
}
/**
* @param recoveryInterval The recovery interval.
* @see SimpleMessageListenerContainer#setRecoveryInterval
*/
public void setRecoveryInterval(Long recoveryInterval) {
this.recoveryBackOff = new FixedBackOff(recoveryInterval, FixedBackOff.UNLIMITED_ATTEMPTS);
}
/**
* @param recoveryBackOff The BackOff to recover.
* @since 1.5
* @see SimpleMessageListenerContainer#setRecoveryBackOff(BackOff)
*/
public void setRecoveryBackOff(BackOff recoveryBackOff) {
this.recoveryBackOff = recoveryBackOff;
}
/**
* @param missingQueuesFatal the missingQueuesFatal to set.
* @see SimpleMessageListenerContainer#setMissingQueuesFatal
*/
public void setMissingQueuesFatal(Boolean missingQueuesFatal) {
this.missingQueuesFatal = missingQueuesFatal;
}
/**
* @param mismatchedQueuesFatal the mismatchedQueuesFatal to set.
* @since 1.6
* @see SimpleMessageListenerContainer#setMismatchedQueuesFatal(boolean)
*/
public void setMismatchedQueuesFatal(Boolean mismatchedQueuesFatal) {
this.mismatchedQueuesFatal = mismatchedQueuesFatal;
}
/**
* @param consumerTagStrategy the consumerTagStrategy to set
* @see SimpleMessageListenerContainer#setConsumerTagStrategy(ConsumerTagStrategy)
*/
public void setConsumerTagStrategy(ConsumerTagStrategy consumerTagStrategy) {
this.consumerTagStrategy = consumerTagStrategy;
}
/**
* How often to publish idle container events.
* @param idleEventInterval the interval.
*/
public void setIdleEventInterval(Long idleEventInterval) {
this.idleEventInterval = idleEventInterval;
}
public void setFailedDeclarationRetryInterval(Long failedDeclarationRetryInterval) {
this.failedDeclarationRetryInterval = failedDeclarationRetryInterval;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* @param autoStartup true for auto startup.
* @see AbstractMessageListenerContainer#setAutoStartup(boolean)
*/
public void setAutoStartup(Boolean autoStartup) {
this.autoStartup = autoStartup;
}
/**
* @param phase The phase.
* @see AbstractMessageListenerContainer#setPhase(int)
*/
public void setPhase(int phase) {
this.phase = phase;
}
@Override
public C createListenerContainer(RabbitListenerEndpoint endpoint) {
C instance = createContainerInstance();
if (this.connectionFactory != null) {
instance.setConnectionFactory(this.connectionFactory);
}
if (this.errorHandler != null) {
instance.setErrorHandler(this.errorHandler);
}
if (this.messageConverter != null) {
instance.setMessageConverter(this.messageConverter);
}
if (this.acknowledgeMode != null) {
instance.setAcknowledgeMode(this.acknowledgeMode);
}
if (this.channelTransacted != null) {
instance.setChannelTransacted(this.channelTransacted);
}
if (this.applicationContext != null) {
instance.setApplicationContext(this.applicationContext);
}
if (this.taskExecutor != null) {
instance.setTaskExecutor(this.taskExecutor);
}
if (this.transactionManager != null) {
instance.setTransactionManager(this.transactionManager);
}
if (this.prefetchCount != null) {
instance.setPrefetchCount(this.prefetchCount);
}
if (this.defaultRequeueRejected != null) {
instance.setDefaultRequeueRejected(this.defaultRequeueRejected);
}
if (this.adviceChain != null) {
instance.setAdviceChain(this.adviceChain);
}
if (this.recoveryBackOff != null) {
instance.setRecoveryBackOff(this.recoveryBackOff);
}
if (this.mismatchedQueuesFatal != null) {
instance.setMismatchedQueuesFatal(this.mismatchedQueuesFatal);
}
if (this.missingQueuesFatal != null) {
instance.setMissingQueuesFatal(this.missingQueuesFatal);
}
if (this.consumerTagStrategy != null) {
instance.setConsumerTagStrategy(this.consumerTagStrategy);
}
if (this.idleEventInterval != null) {
instance.setIdleEventInterval(this.idleEventInterval);
}
if (this.failedDeclarationRetryInterval != null) {
instance.setFailedDeclarationRetryInterval(this.failedDeclarationRetryInterval);
}
if (this.applicationEventPublisher != null) {
instance.setApplicationEventPublisher(this.applicationEventPublisher);
}
if (this.autoStartup != null) {
instance.setAutoStartup(this.autoStartup);
}
if (this.phase != null) {
instance.setPhase(this.phase);
}
instance.setListenerId(endpoint.getId());
endpoint.setupListenerContainer(instance);
initializeContainer(instance, endpoint);
return instance;
}
/**
* Create an empty container instance.
* @return the new container instance.
*/
protected abstract C createContainerInstance();
/**
* Further initialize the specified container.
* <p>Subclasses can inherit from this method to apply extra
* configuration if necessary.
* @param instance the container instance to configure.
* @param endpoint the endpoint.
*/
protected void initializeContainer(C instance, RabbitListenerEndpoint endpoint) {
}
}