@Override public Binding<MessageChannel> bindProducer( final String name, MessageChannel moduleOutputChannel, Properties properties) { Assert.isInstanceOf(SubscribableChannel.class, moduleOutputChannel); KafkaPropertiesAccessor producerPropertiesAccessor = new KafkaPropertiesAccessor(properties); validateProducerProperties(name, properties, SUPPORTED_PRODUCER_PROPERTIES); if (logger.isInfoEnabled()) { logger.info("Using kafka topic for outbound: " + name); } final String topicName = escapeTopicName(name); int numPartitions = producerPropertiesAccessor.getNumberOfKafkaPartitionsForProducer(); Collection<Partition> partitions = ensureTopicCreated(topicName, numPartitions, defaultReplicationFactor); ProducerMetadata<byte[], byte[]> producerMetadata = new ProducerMetadata<>( topicName, byte[].class, byte[].class, BYTE_ARRAY_SERIALIZER, BYTE_ARRAY_SERIALIZER); producerMetadata.setCompressionType( ProducerMetadata.CompressionType.valueOf( producerPropertiesAccessor.getCompressionCodec(this.defaultCompressionCodec))); producerMetadata.setBatchBytes(producerPropertiesAccessor.getBatchSize(this.defaultBatchSize)); Properties additionalProps = new Properties(); additionalProps.put( ProducerConfig.ACKS_CONFIG, String.valueOf(producerPropertiesAccessor.getRequiredAcks(this.defaultRequiredAcks))); additionalProps.put( ProducerConfig.LINGER_MS_CONFIG, String.valueOf(producerPropertiesAccessor.getBatchTimeout(this.defaultBatchTimeout))); ProducerFactoryBean<byte[], byte[]> producerFB = new ProducerFactoryBean<>(producerMetadata, brokers, additionalProps); try { final ProducerConfiguration<byte[], byte[]> producerConfiguration = new ProducerConfiguration<>(producerMetadata, producerFB.getObject()); MessageHandler handler = new SendingHandler( topicName, producerPropertiesAccessor, partitions.size(), producerConfiguration); EventDrivenConsumer consumer = new EventDrivenConsumer((SubscribableChannel) moduleOutputChannel, handler); consumer.setBeanFactory(this.getBeanFactory()); consumer.setBeanName("outbound." + name); consumer.afterPropertiesSet(); Binding<MessageChannel> producerBinding = Binding.forProducer(name, moduleOutputChannel, consumer, producerPropertiesAccessor); addBinding(producerBinding); producerBinding.start(); return producerBinding; } catch (Exception e) { throw new RuntimeException(e); } }
@Test public void correlationIdCopiedFromMessageId() { Message<String> message = MessageBuilder.withPayload("test").build(); DirectChannel inputChannel = new DirectChannel(); QueueChannel outputChannel = new QueueChannel(1); DefaultMessageSplitter splitter = new DefaultMessageSplitter(); splitter.setOutputChannel(outputChannel); EventDrivenConsumer endpoint = new EventDrivenConsumer(inputChannel, splitter); endpoint.start(); assertTrue(inputChannel.send(message)); Message<?> reply = outputChannel.receive(0); assertEquals(message.getHeaders().getId(), reply.getHeaders().getCorrelationId()); }
@Test public void targetOnly() { String beanName = "outboundWithImplicitChannel"; Object channel = this.applicationContext.getBean(beanName); assertTrue(channel instanceof DirectChannel); BeanFactoryChannelResolver channelResolver = new BeanFactoryChannelResolver(this.applicationContext); assertNotNull(channelResolver.resolveDestination(beanName)); Object adapter = this.applicationContext.getBean(beanName + ".adapter"); assertNotNull(adapter); assertTrue(adapter instanceof EventDrivenConsumer); assertFalse(((EventDrivenConsumer) adapter).isAutoStartup()); assertEquals(-1, ((EventDrivenConsumer) adapter).getPhase()); TestConsumer consumer = (TestConsumer) this.applicationContext.getBean("consumer"); assertNull(consumer.getLastMessage()); Message<?> message = new GenericMessage<String>("test"); try { ((MessageChannel) channel).send(message); fail("MessageDispatchingException is expected."); } catch (Exception e) { assertThat(e, Matchers.instanceOf(MessageDeliveryException.class)); assertThat(e.getCause(), Matchers.instanceOf(MessageDispatchingException.class)); } ((EventDrivenConsumer) adapter).start(); ((MessageChannel) channel).send(message); assertNotNull(consumer.getLastMessage()); assertEquals(message, consumer.getLastMessage()); }
private void doRegisterProducer( final String name, MessageChannel moduleOutputChannel, AmqpOutboundEndpoint delegate, String replyTo, RabbitPropertiesAccessor properties) { Assert.isInstanceOf(SubscribableChannel.class, moduleOutputChannel); MessageHandler handler = new SendingHandler(delegate, replyTo, properties); EventDrivenConsumer consumer = new EventDrivenConsumer((SubscribableChannel) moduleOutputChannel, handler); consumer.setBeanFactory(getBeanFactory()); consumer.setBeanName("outbound." + name); consumer.afterPropertiesSet(); Binding producerBinding = Binding.forProducer(name, moduleOutputChannel, consumer, properties); addBinding(producerBinding); producerBinding.start(); }
private Binding<MessageChannel> createKafkaConsumer( String name, final MessageChannel moduleInputChannel, Properties properties, String group, long referencePoint) { validateConsumerProperties(groupedName(name, group), properties, SUPPORTED_CONSUMER_PROPERTIES); KafkaPropertiesAccessor accessor = new KafkaPropertiesAccessor(properties); int maxConcurrency = accessor.getConcurrency(defaultConcurrency); String topic = escapeTopicName(name); int numPartitions = accessor.getNumberOfKafkaPartitionsForConsumer(); Collection<Partition> allPartitions = ensureTopicCreated(topic, numPartitions, defaultReplicationFactor); Decoder<byte[]> valueDecoder = new DefaultDecoder(null); Decoder<byte[]> keyDecoder = new DefaultDecoder(null); Collection<Partition> listenedPartitions; int moduleCount = accessor.getCount(); if (moduleCount == 1) { listenedPartitions = allPartitions; } else { listenedPartitions = new ArrayList<Partition>(); for (Partition partition : allPartitions) { // divide partitions across modules if (accessor.getPartitionIndex() != -1) { if ((partition.getId() % moduleCount) == accessor.getPartitionIndex()) { listenedPartitions.add(partition); } } else { int moduleSequence = accessor.getSequence(); if (moduleCount == 0) { throw new IllegalArgumentException( "The Kafka transport does not support 0-count modules"); } else { // sequence numbers are zero-based if ((partition.getId() % moduleCount) == (moduleSequence - 1)) { listenedPartitions.add(partition); } } } } } ReceivingHandler rh = new ReceivingHandler(); rh.setOutputChannel(moduleInputChannel); final FixedSubscriberChannel bridge = new FixedSubscriberChannel(rh); bridge.setBeanName("bridge." + name); final KafkaMessageListenerContainer messageListenerContainer = createMessageListenerContainer( accessor, group, maxConcurrency, listenedPartitions, referencePoint); final KafkaMessageDrivenChannelAdapter kafkaMessageDrivenChannelAdapter = new KafkaMessageDrivenChannelAdapter(messageListenerContainer); kafkaMessageDrivenChannelAdapter.setBeanFactory(this.getBeanFactory()); kafkaMessageDrivenChannelAdapter.setKeyDecoder(keyDecoder); kafkaMessageDrivenChannelAdapter.setPayloadDecoder(valueDecoder); kafkaMessageDrivenChannelAdapter.setOutputChannel(bridge); kafkaMessageDrivenChannelAdapter.setAutoCommitOffset( accessor.getDefaultAutoCommitEnabled(this.defaultAutoCommitEnabled)); kafkaMessageDrivenChannelAdapter.afterPropertiesSet(); kafkaMessageDrivenChannelAdapter.start(); EventDrivenConsumer edc = new EventDrivenConsumer(bridge, rh) { @Override protected void doStop() { // stop the offset manager and the channel adapter before unbinding // this means that the upstream channel adapter has a chance to stop kafkaMessageDrivenChannelAdapter.stop(); if (messageListenerContainer.getOffsetManager() instanceof DisposableBean) { try { ((DisposableBean) messageListenerContainer.getOffsetManager()).destroy(); } catch (Exception e) { logger.error("Error while closing the offset manager", e); } } super.doStop(); } }; String groupedName = groupedName(name, group); edc.setBeanName("inbound." + groupedName); Binding<MessageChannel> consumerBinding = Binding.forConsumer(name, group, edc, moduleInputChannel, accessor); addBinding(consumerBinding); consumerBinding.start(); return consumerBinding; }