/* * Copyright 2014-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.amqp.dsl; import org.springframework.amqp.core.MessageDeliveryMode; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.support.MessagePropertiesConverter; import org.springframework.amqp.support.AmqpHeaders; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.integration.amqp.channel.AbstractAmqpChannel; import org.springframework.integration.amqp.config.AmqpChannelFactoryBean; import org.springframework.integration.amqp.support.AmqpHeaderMapper; import org.springframework.integration.dsl.channel.MessageChannelSpec; import org.springframework.util.Assert; /** * A {@link MessageChannelSpec} for a {@link AbstractAmqpChannel}s. * * @param <S> the target {@link AmqpPollableMessageChannelSpec} implementation type. * * @author Artem Bilan * @author Gary Russell * @since 5.0 */ public class AmqpPollableMessageChannelSpec<S extends AmqpPollableMessageChannelSpec<S>> extends MessageChannelSpec<S, AbstractAmqpChannel> { protected final AmqpChannelFactoryBean amqpChannelFactoryBean; AmqpPollableMessageChannelSpec(ConnectionFactory connectionFactory) { this(new AmqpChannelFactoryBean(false), connectionFactory); } AmqpPollableMessageChannelSpec(AmqpChannelFactoryBean amqpChannelFactoryBean, ConnectionFactory connectionFactory) { this.amqpChannelFactoryBean = amqpChannelFactoryBean; this.amqpChannelFactoryBean.setConnectionFactory(connectionFactory); this.amqpChannelFactoryBean.setSingleton(false); this.amqpChannelFactoryBean.setPubSub(false); /* We need this artificial BeanFactory to overcome AmqpChannelFactoryBean initialization. The real BeanFactory will be applied later for the target AbstractAmqpChannel instance. */ this.amqpChannelFactoryBean.setBeanFactory(new DefaultListableBeanFactory()); } @Override protected S id(String id) { this.amqpChannelFactoryBean.setBeanName(id); return super.id(id); } /** * Also implicitly sets the {@link #id(String)} (if not explicitly set). * @param queueName the queueName. * @return the spec. * @see AmqpChannelFactoryBean#setQueueName(String) */ public S queueName(String queueName) { if (getId() == null) { id(queueName + ".channel"); } this.amqpChannelFactoryBean.setQueueName(queueName); return _this(); } /** * @param encoding the encoding. * @return the spec. * @see org.springframework.amqp.rabbit.core.RabbitTemplate#setEncoding(String) */ public S encoding(String encoding) { this.amqpChannelFactoryBean.setEncoding(encoding); return _this(); } /** * @param messageConverter the messageConverter. * @return the spec. * @see org.springframework.amqp.rabbit.core.RabbitTemplate#setMessageConverter(MessageConverter) */ public S amqpMessageConverter(MessageConverter messageConverter) { this.amqpChannelFactoryBean.setMessageConverter(messageConverter); return _this(); } /** * Configure {@code channelTransacted} on both the * {@link org.springframework.amqp.rabbit.core.RabbitTemplate} (for sends) and * {@link org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer} * (for receives) when using Spring Integration 4.0. When using Spring Integration * 4.1, only the container is configured. See {@link #templateChannelTransacted(boolean)}. * @param channelTransacted the channelTransacted. * @return the spec. * @see org.springframework.amqp.rabbit.core.RabbitTemplate#setChannelTransacted(boolean) * @see org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer#setChannelTransacted(boolean) */ public S channelTransacted(boolean channelTransacted) { this.amqpChannelFactoryBean.setChannelTransacted(channelTransacted); return _this(); } /** * Configure {@code channelTransacted} on the * {@link org.springframework.amqp.rabbit.core.RabbitTemplate} used when sending * messages to the channel. Only applies when Spring Integration 4.1 or greater is * being used. Otherwise, see {@link #channelTransacted(boolean)}. * @param channelTransacted the channelTransacted. * @return the spec. * @see org.springframework.amqp.rabbit.core.RabbitTemplate#setChannelTransacted(boolean) */ public S templateChannelTransacted(boolean channelTransacted) { this.amqpChannelFactoryBean.setTemplateChannelTransacted(channelTransacted); return _this(); } /** * Configure {@code messagePropertiesConverter} on both the * {@link org.springframework.amqp.rabbit.core.RabbitTemplate} (for sends) and * {@link org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer} * (for receives). * @param messagePropertiesConverter the messagePropertiesConverter. * @return the spec. * @see org.springframework.amqp.rabbit.core.RabbitTemplate#setMessagePropertiesConverter * @see org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer#setMessagePropertiesConverter */ public S messagePropertiesConverter(MessagePropertiesConverter messagePropertiesConverter) { this.amqpChannelFactoryBean.setMessagePropertiesConverter(messagePropertiesConverter); return _this(); } /** * Configure the delivery mode for messages that don't have an * {@link AmqpHeaders#DELIVERY_MODE} header. Default is {@link MessageDeliveryMode#PERSISTENT}. * @param mode the mode. * @return the spec. */ public S defaultDeliveryMode(MessageDeliveryMode mode) { this.amqpChannelFactoryBean.setDefaultDeliveryMode(mode); return _this(); } /** * Configure whether normal spring-messaging to AMQP message mapping is enabled. * Default false. * @param extract true to enable mapping. * @return the spec. * @see #outboundHeaderMapper(AmqpHeaderMapper) * @see #inboundHeaderMapper(AmqpHeaderMapper) */ public S extractPayload(boolean extract) { this.amqpChannelFactoryBean.setExtractPayload(extract); return _this(); } /** * Configure the outbound header mapper to use when {@link #extractPayload(boolean)} * is true. Defaults to a {@code DefaultAmqpHeaderMapper}. * @param mapper the mapper. * @return the spec. * @see #extractPayload(boolean) */ public S outboundHeaderMapper(AmqpHeaderMapper mapper) { this.amqpChannelFactoryBean.setOutboundHeaderMapper(mapper); return _this(); } /** * Configure the inbound header mapper to use when {@link #extractPayload(boolean)} * is true. Defaults to a {@code DefaultAmqpHeaderMapper}. * @param mapper the mapper. * @return the spec. * @see #extractPayload(boolean) */ public S inboundHeaderMapper(AmqpHeaderMapper mapper) { this.amqpChannelFactoryBean.setInboundHeaderMapper(mapper); return _this(); } /** * @param headersLast true to map headers last. * @return the spec. * @see AbstractAmqpChannel#setHeadersMappedLast(boolean) */ public S headersMappedLast(boolean headersLast) { this.target.setHeadersMappedLast(headersLast); return _this(); } @Override protected AbstractAmqpChannel doGet() { Assert.notNull(getId(), "The 'id' or 'queueName' must be specified"); try { this.channel = this.amqpChannelFactoryBean.getObject(); } catch (Exception e) { throw new BeanCreationException("Cannot create the AMQP MessageChannel", e); } return super.doGet(); } }