@Override
  public void bindRequestor(
      String name, MessageChannel requests, MessageChannel replies, Properties properties) {
    if (logger.isInfoEnabled()) {
      logger.info("binding requestor: " + name);
    }
    validateProducerProperties(name, properties, SUPPORTED_REQUESTING_PRODUCER_PROPERTIES);
    Assert.isInstanceOf(SubscribableChannel.class, requests);
    RabbitPropertiesAccessor accessor = new RabbitPropertiesAccessor(properties);
    String queueName = applyRequests(name);
    AmqpOutboundEndpoint queue =
        this.buildOutboundEndpoint(queueName, accessor, this.rabbitTemplate);
    queue.setBeanFactory(this.getBeanFactory());

    String replyQueueName =
        accessor.getPrefix(this.defaultPrefix)
            + name
            + ".replies."
            + this.getIdGenerator().generateId();
    this.doRegisterProducer(name, requests, queue, replyQueueName, accessor);
    Queue replyQueue = new Queue(replyQueueName, false, false, true); // auto-delete
    declareQueueIfNotPresent(replyQueue);
    // register with context so it will be redeclared after a connection failure
    if (!this.autoDeclareContext.containsBean(replyQueueName)) {
      this.autoDeclareContext.getBeanFactory().registerSingleton(replyQueueName, replyQueue);
    }
    this.doRegisterConsumer(name, replies, replyQueue, accessor, false);
  }
 private Map<String, Object> queueArgs(RabbitPropertiesAccessor accessor, String queueName) {
   Map<String, Object> args = new HashMap<>();
   if (accessor.getAutoBindDLQ(this.defaultAutoBindDLQ)) {
     args.put(
         "x-dead-letter-exchange", applyPrefix(accessor.getPrefix(this.defaultPrefix), "DLX"));
     args.put("x-dead-letter-routing-key", queueName);
   }
   return args;
 }
 @Override
 public void bindPubSubProducer(
     String name, MessageChannel moduleOutputChannel, Properties properties) {
   validateProducerProperties(name, properties, SUPPORTED_PUBSUB_PRODUCER_PROPERTIES);
   RabbitPropertiesAccessor accessor = new RabbitPropertiesAccessor(properties);
   String exchangeName = applyPrefix(accessor.getPrefix(this.defaultPrefix), applyPubSub(name));
   declareExchangeIfNotPresent(new FanoutExchange(exchangeName));
   AmqpOutboundEndpoint fanout = new AmqpOutboundEndpoint(determineRabbitTemplate(accessor));
   fanout.setExchangeName(exchangeName);
   configureOutboundHandler(fanout, accessor);
   doRegisterProducer(name, moduleOutputChannel, fanout, accessor);
 }
 private MessageRecoverer determineRecoverer(String name, RabbitPropertiesAccessor properties) {
   if (properties.getRepublishToDLQ(this.defaultRepublishToDLQ)) {
     RabbitTemplate errorTemplate = new RabbitTemplate(this.connectionFactory);
     String prefix = properties.getPrefix(this.defaultPrefix);
     RepublishMessageRecoverer republishMessageRecoverer =
         new RepublishMessageRecoverer(
             errorTemplate, deadLetterExchangeName(prefix), applyPrefix(prefix, name));
     // TODO: Add container id to republished message headers? (Needs AMQP-489).
     return republishMessageRecoverer;
   } else {
     return new RejectAndDontRequeueRecoverer();
   }
 }
 /**
  * If so requested, declare the DLX/DLQ and bind it. The DLQ is bound to the DLX with a routing
  * key of the original queue name because we use default exchange routing by queue name for the
  * original message.
  *
  * @param name The name.
  * @param properties The properties accessor.
  */
 private void autoBindDLQ(final String name, RabbitPropertiesAccessor properties) {
   if (logger.isDebugEnabled()) {
     logger.debug(
         "autoBindDLQ=" + properties.getAutoBindDLQ(this.defaultAutoBindDLQ) + " for: " + name);
   }
   if (properties.getAutoBindDLQ(this.defaultAutoBindDLQ)) {
     String prefix = properties.getPrefix(this.defaultPrefix);
     String queueName = applyPrefix(prefix, name);
     String dlqName = constructDLQName(queueName);
     Queue dlq = new Queue(dlqName);
     declareQueueIfNotPresent(dlq);
     final String dlxName = deadLetterExchangeName(prefix);
     final DirectExchange dlx = new DirectExchange(dlxName);
     declareExchangeIfNotPresent(dlx);
     this.rabbitAdmin.declareBinding(BindingBuilder.bind(dlq).to(dlx).with(queueName));
   }
 }
  @Override
  public void bindReplier(
      String name, MessageChannel requests, MessageChannel replies, Properties properties) {
    if (logger.isInfoEnabled()) {
      logger.info("binding replier: " + name);
    }
    validateConsumerProperties(name, properties, SUPPORTED_REPLYING_CONSUMER_PROPERTIES);
    RabbitPropertiesAccessor accessor = new RabbitPropertiesAccessor(properties);
    Queue requestQueue =
        new Queue(applyPrefix(accessor.getPrefix(this.defaultPrefix), applyRequests(name)));
    declareQueueIfNotPresent(requestQueue);
    this.doRegisterConsumer(name, requests, requestQueue, accessor, false);

    AmqpOutboundEndpoint replyQueue = new AmqpOutboundEndpoint(rabbitTemplate);
    replyQueue.setExpressionRoutingKey(
        EXPRESSION_PARSER.parseExpression("headers['" + AmqpHeaders.REPLY_TO + "']"));
    configureOutboundHandler(replyQueue, accessor);
    doRegisterProducer(name, replies, replyQueue, accessor);
  }
 private AmqpOutboundEndpoint buildOutboundEndpoint(
     final String name, RabbitPropertiesAccessor properties, RabbitTemplate rabbitTemplate) {
   String queueName = applyPrefix(properties.getPrefix(this.defaultPrefix), name);
   String partitionKeyExtractorClass = properties.getPartitionKeyExtractorClass();
   Expression partitionKeyExpression = properties.getPartitionKeyExpression();
   AmqpOutboundEndpoint queue = new AmqpOutboundEndpoint(rabbitTemplate);
   if (partitionKeyExpression == null && !StringUtils.hasText(partitionKeyExtractorClass)) {
     declareQueueIfNotPresent(new Queue(queueName));
     queue.setRoutingKey(queueName); // uses default exchange
   } else {
     queue.setExpressionRoutingKey(
         EXPRESSION_PARSER.parseExpression(buildPartitionRoutingExpression(queueName)));
     // if the stream is partitioned, create one queue for each target partition
     for (int i = 0; i < properties.getNextModuleCount(); i++) {
       this.rabbitAdmin.declareQueue(new Queue(queueName + "-" + i));
     }
   }
   configureOutboundHandler(queue, properties);
   return queue;
 }
 @Override
 public void bindPubSubConsumer(
     String name, MessageChannel moduleInputChannel, Properties properties) {
   String exchangeName = BinderUtils.removeGroupFromPubSub(name);
   if (logger.isInfoEnabled()) {
     logger.info("declaring pubsub for inbound: " + name + ", bound to: " + exchangeName);
   }
   RabbitPropertiesAccessor accessor = new RabbitPropertiesAccessor(properties);
   validateConsumerProperties(name, properties, SUPPORTED_PUBSUB_CONSUMER_PROPERTIES);
   String prefix = accessor.getPrefix(this.defaultPrefix);
   FanoutExchange exchange = new FanoutExchange(applyPrefix(prefix, applyPubSub(exchangeName)));
   declareExchangeIfNotPresent(exchange);
   Queue queue;
   boolean durable = accessor.isDurable(this.defaultDurableSubscription);
   String queueName = applyPrefix(prefix, name);
   if (durable) {
     Map<String, Object> args = queueArgs(accessor, queueName);
     queue = new Queue(queueName, true, false, false, args);
   } else {
     queue = new Queue(queueName, false, false, true);
   }
   declareQueueIfNotPresent(queue);
   org.springframework.amqp.core.Binding binding = BindingBuilder.bind(queue).to(exchange);
   this.rabbitAdmin.declareBinding(binding);
   // register with context so they will be redeclared after a connection failure
   if (!this.autoDeclareContext.containsBean(applyPubSub(name))) {
     this.autoDeclareContext.getBeanFactory().registerSingleton(applyPubSub(name), queue);
   }
   String bindingBeanName = exchange.getName() + "." + queue.getName() + ".binding";
   if (!this.autoDeclareContext.containsBean(bindingBeanName)) {
     this.autoDeclareContext.getBeanFactory().registerSingleton(bindingBeanName, binding);
   }
   doRegisterConsumer(name, moduleInputChannel, queue, accessor, true);
   if (durable) {
     autoBindDLQ(name, accessor);
   }
 }
 @Override
 public void bindConsumer(
     final String name, MessageChannel moduleInputChannel, Properties properties) {
   if (logger.isInfoEnabled()) {
     logger.info("declaring queue for inbound: " + name);
   }
   if (name.startsWith(P2P_NAMED_CHANNEL_TYPE_PREFIX)) {
     validateConsumerProperties(name, properties, SUPPORTED_NAMED_CONSUMER_PROPERTIES);
   } else {
     validateConsumerProperties(name, properties, SUPPORTED_CONSUMER_PROPERTIES);
   }
   RabbitPropertiesAccessor accessor = new RabbitPropertiesAccessor(properties);
   String queueName = applyPrefix(accessor.getPrefix(this.defaultPrefix), name);
   int partitionIndex = accessor.getPartitionIndex();
   if (partitionIndex >= 0) {
     queueName += "-" + partitionIndex;
   }
   Map<String, Object> args = queueArgs(accessor, queueName);
   Queue queue = new Queue(queueName, true, false, false, args);
   declareQueueIfNotPresent(queue);
   autoBindDLQ(name, accessor);
   doRegisterConsumer(name, moduleInputChannel, queue, accessor, false);
   bindExistingProducerDirectlyIfPossible(name, moduleInputChannel);
 }