/* * Copyright 2015 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.xd.dirt.stream; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.springframework.xd.dirt.integration.kafka.KafkaMessageBus.escapeTopicName; import java.util.Collections; import java.util.HashMap; import java.util.Map; import kafka.api.OffsetRequest; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; import org.junit.rules.ExternalResource; import org.springframework.integration.kafka.core.BrokerAddress; import org.springframework.integration.kafka.core.DefaultConnectionFactory; import org.springframework.integration.kafka.core.FetchRequest; import org.springframework.integration.kafka.core.KafkaMessageBatch; import org.springframework.integration.kafka.core.KafkaTemplate; import org.springframework.integration.kafka.core.Partition; import org.springframework.integration.kafka.core.PartitionNotFoundException; import org.springframework.integration.kafka.core.Result; import org.springframework.integration.kafka.core.ZookeeperConfiguration; import org.springframework.integration.kafka.serializer.common.StringDecoder; import org.springframework.integration.kafka.support.ZookeeperConnect; import org.springframework.integration.kafka.util.MessageUtils; import org.springframework.messaging.MessageChannel; import org.springframework.xd.dirt.integration.bus.kafka.KafkaTestMessageBus; import org.springframework.xd.test.kafka.KafkaTestSupport; /** * @author Marius Bogoevici */ public class KafkaSingleNodeStreamDeploymentIntegrationTests extends AbstractSingleNodeStreamDeploymentIntegrationTests { @ClassRule public static KafkaTestSupport kafkaTestSupport = new KafkaTestSupport(); @ClassRule public static ExternalResource initializeKafkaMessageBus = new ExternalResource() { @Override protected void before() { if (testMessageBus == null || !(testMessageBus instanceof KafkaTestMessageBus)) { testMessageBus = new KafkaTestMessageBus(kafkaTestSupport); } } }; @BeforeClass public static void setUpAll() { System.setProperty("xd.messagebus.kafka.zkAddress", kafkaTestSupport.getZkConnectString()); System.setProperty("xd.messagebus.kafka.brokers", kafkaTestSupport.getBrokerAddress()); setUp("kafka"); } @AfterClass public static void clearAll() { System.clearProperty("xd.messagebus.kafka.zkAddress"); System.clearProperty("xd.messagebus.kafka.brokers"); } @Test @Ignore("Disabled pending on resolution of https://jira.spring.io/browse/XD-3055") @Override public void testTappingWithRepeatedModulesDoesNotDuplicateMessages() { // do nothing } @Test @Ignore("Disabled pending on resolution of https://jira.spring.io/browse/XD-3055") @Override public void verifyQueueChannelsRegisteredOnDemand() throws InterruptedException { // do nothing } @Override protected void verifyOnDemandQueues(MessageChannel y3, MessageChannel z3, Map<String, Object> initialTransportState) { DefaultConnectionFactory defaultConnectionFactory = getDefaultConnectionFactory(); KafkaTemplate template = new KafkaTemplate(defaultConnectionFactory); String y = receiveFromTopicForQueue(template, escapeTopicName("queue:y"), initialTransportState); assertTrue(y.endsWith("y")); // bus headers String z = receiveFromTopicForQueue(template, escapeTopicName("queue:z"), initialTransportState); assertNotNull(z); assertTrue(z.endsWith("z")); // bus headers try { defaultConnectionFactory.destroy(); } catch (Exception e) { throw new RuntimeException(e); } } private DefaultConnectionFactory getDefaultConnectionFactory() { ZookeeperConnect zookeeperConnect = new ZookeeperConnect(); zookeeperConnect.setZkConnect(kafkaTestSupport.getZkConnectString()); ZookeeperConfiguration configuration = new ZookeeperConfiguration(zookeeperConnect); DefaultConnectionFactory connectionFactory = new DefaultConnectionFactory(configuration); try { connectionFactory.afterPropertiesSet(); } catch (Exception e) { throw new RuntimeException(e); } return connectionFactory; } @Override protected Map<String, Object> readInitialQueueState(String... queueNames) { DefaultConnectionFactory defaultConnectionFactory = getDefaultConnectionFactory(); KafkaTemplate template = new KafkaTemplate(getDefaultConnectionFactory()); Map<String, Object> initialOffsets = new HashMap<String, Object>(); for (String queueName : queueNames) { String escapedTopicName = escapeTopicName(queueName); initialOffsets.put(escapedTopicName, getInitialOffset(template, escapedTopicName)); } try { defaultConnectionFactory.destroy(); } catch (Exception e) { throw new RuntimeException(e); } return initialOffsets; } private String receiveFromTopicForQueue(KafkaTemplate template, String topicName, Map<String, Object> initialTransportState) { Partition partition = new Partition(topicName, 0); Result<KafkaMessageBatch> receive = template.receive(Collections.singleton(new FetchRequest(partition, (Long) initialTransportState.get(topicName), 1000))); return MessageUtils.decodePayload(receive.getResult(partition).getMessages().get(0), new StringDecoder()); } private long getInitialOffset(KafkaTemplate template, String topicName) { try { Partition partition = new Partition(topicName, 0); BrokerAddress leader = template.getConnectionFactory().getLeader(partition); return template.getConnectionFactory().connect(leader) .fetchInitialOffset(OffsetRequest.LatestTime(), partition).getResult(partition); } catch (PartitionNotFoundException e) { return 0; } } }