@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); }