/* * 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.cassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Select; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.thrift.transport.TTransportException; import org.cassandraunit.utils.EmbeddedCassandraServerHelper; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.data.cassandra.core.CassandraTemplate; import org.springframework.integration.support.json.Jackson2JsonObjectMapper; import org.springframework.xd.dirt.server.singlenode.SingleNodeApplication; import org.springframework.xd.dirt.test.SingleNodeIntegrationTestSupport; import org.springframework.xd.dirt.test.SingletonModuleRegistry; import org.springframework.xd.dirt.test.process.SingleNodeProcessingChainProducer; import org.springframework.xd.dirt.test.process.SingleNodeProcessingChainSupport; import org.springframework.xd.module.ModuleType; import org.springframework.xd.test.RandomConfigurationSupport; import org.springframework.xd.test.domain.Book; import reactor.fn.Supplier; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.UUID; import static org.junit.Assert.assertTrue; /** * @author Artem Bilan */ public class CassandraSinkTests { private static final String STREAM_NAME = "cassandraTest"; private static final String MODULE_NAME = "cassandra"; private static final String CASSANDRA_CONFIG = "spring-cassandra.yaml"; private static final int PORT = 9043; // See spring-cassandra.yaml - native_transport_port private static Cluster cluster; private static CassandraOperations cassandraTemplate; private static SingleNodeApplication application; @BeforeClass public static void setUp() throws ConfigurationException, IOException, TTransportException { EmbeddedCassandraServerHelper.startEmbeddedCassandra(CASSANDRA_CONFIG, "build/embeddedCassandra"); cluster = Cluster.builder() .addContactPoint("localhost") .withPort(PORT) .build(); cluster.connect().execute(String.format("CREATE KEYSPACE IF NOT EXISTS %s" + " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };", STREAM_NAME)); cassandraTemplate = new CassandraTemplate(cluster.connect(STREAM_NAME)); new RandomConfigurationSupport(); application = new SingleNodeApplication().run(); SingleNodeIntegrationTestSupport integrationTest = new SingleNodeIntegrationTestSupport(application); integrationTest.addModuleRegistry(new SingletonModuleRegistry(ModuleType.sink, MODULE_NAME)); } @AfterClass public static void cleanup() { if (cluster != null) { cluster.close(); } EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); } @Test public void testIngestQuery() throws Exception { String stream = String.format("%s --port=%s --initScript=%s --ingestQuery=\"%s\"", MODULE_NAME, PORT, "int-db.cql", "insert into book (isbn, title, author, pages, saleDate, inStock) values (?, ?, ?, ?, ?, ?)"); SingleNodeProcessingChainProducer chain = SingleNodeProcessingChainSupport.chainProducer(application, STREAM_NAME, stream); List<Book> books = getBookList(5); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); Jackson2JsonObjectMapper mapper = new Jackson2JsonObjectMapper(objectMapper); chain.sendPayload(mapper.toJson(books)); final Select select = QueryBuilder.select().all().from("book"); assertEqualsEventually(5, new Supplier<Integer>() { @Override public Integer get() { return cassandraTemplate.select(select, Book.class).size(); } }); cassandraTemplate.truncate("book"); chain.destroy(); } private List<Book> getBookList(int numBooks) { List<Book> books = new ArrayList<>(); Book b; for (int i = 0; i < numBooks; i++) { b = new Book(); b.setIsbn(UUID.randomUUID()); b.setTitle("Spring XD Guide"); b.setAuthor("XD Guru"); b.setPages(i * 10 + 5); b.setInStock(true); b.setSaleDate(new Date()); books.add(b); } return books; } private static <T> void assertEqualsEventually(T expected, Supplier<T> actualSupplier) throws InterruptedException { int n = 0; while (!actualSupplier.get().equals(expected) && n++ < 100) { Thread.sleep(100); } assertTrue(n < 10); } }