From 97be7d6fc34c82672d0fe97496f46399f2e7a4b4 Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 14 Jun 2016 15:52:43 -0700 Subject: [PATCH] DATACASS-297 - Polish. Original pull request: #65. --- .../cassandra/core/CqlTemplate.java | 59 ++++++------ .../cassandra/core/CassandraOperations.java | 12 +-- .../cassandra/core/CassandraTemplate.java | 25 ++++-- .../query/AbstractCassandraQuery.java | 9 +- .../CassandraOperationsIntegrationTests.java | 90 +++++++++++-------- .../declared/QueryIntegrationTests.java | 30 ++++--- 6 files changed, 126 insertions(+), 99 deletions(-) diff --git a/spring-cql/src/main/java/org/springframework/cassandra/core/CqlTemplate.java b/spring-cql/src/main/java/org/springframework/cassandra/core/CqlTemplate.java index c3b275fdc..342a6e8e2 100644 --- a/spring-cql/src/main/java/org/springframework/cassandra/core/CqlTemplate.java +++ b/spring-cql/src/main/java/org/springframework/cassandra/core/CqlTemplate.java @@ -99,6 +99,7 @@ import com.datastax.driver.core.querybuilder.Update; public class CqlTemplate extends CassandraAccessor implements CqlOperations { protected static final Executor RUN_RUNNABLE_EXECUTOR = new Executor() { + @Override @SuppressWarnings("all") public void execute(Runnable command) { @@ -856,48 +857,50 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations { /** * Attempts to translate the {@link Exception} into a Spring Data {@link Exception}. - * @param ex the Exception - * @return the translated {@link RuntimeException} + * + * @param e the {@link Exception} to translate. + * @return the translated {@link RuntimeException}. + * @see Consistent exception hierarchy */ @SuppressWarnings("all") - protected RuntimeException translateExceptionIfPossible(Exception ex) { - return translateExceptionIfPossible(ex, getExceptionTranslator()); + protected RuntimeException translateExceptionIfPossible(Exception e) { + return translateExceptionIfPossible(e, getExceptionTranslator()); } /** * Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original * exception if the conversation failed. Thus allows safe re-throwing of the return value. * - * @param ex the exception to translate + * @param e the exception to translate * @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation * @return */ @SuppressWarnings("all") - protected static RuntimeException translateExceptionIfPossible(Exception ex, PersistenceExceptionTranslator exceptionTranslator) { - - Assert.notNull(ex, "Exception must not be null"); - Assert.notNull(exceptionTranslator, "PersistenceExceptionTranslator must not be null"); - - if (ex instanceof RuntimeException) { - return potentiallyConvertRuntimeException((RuntimeException) ex, exceptionTranslator); - } - - return new CassandraUncategorizedDataAccessException("Caught Uncategorized Exception", ex); - } - - /** - * Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original - * exception if the conversation failed. Thus allows safe re-throwing of the return value. - * - * @param ex the exception to translate - * @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation - * @return - */ - private static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex, + protected static RuntimeException translateExceptionIfPossible(Exception e, PersistenceExceptionTranslator exceptionTranslator) { - RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex); - return resolved == null ? ex : resolved; + Assert.notNull(e, "Exception must not be null"); + Assert.notNull(exceptionTranslator, "PersistenceExceptionTranslator must not be null"); + + return (e instanceof RuntimeException) ? potentiallyConvertRuntimeException((RuntimeException) e, exceptionTranslator) + : new CassandraUncategorizedDataAccessException("Caught Uncategorized Exception", e); + } + + /** + * Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original + * exception if the conversation failed. Thus allows safe re-throwing of the return value. + * + * @param e the exception to translate + * @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation + * @return + */ + @SuppressWarnings("all") + private static RuntimeException potentiallyConvertRuntimeException(RuntimeException e, + PersistenceExceptionTranslator exceptionTranslator) { + + RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(e); + + return (resolved != null ? resolved : e); } @Override diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java index ea43ca596..7211b2d51 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java @@ -56,12 +56,12 @@ public interface CassandraOperations extends CqlOperations { * Executes the given select {@code query} on the entity table of the specified {@code type} backed by a Cassandra * {@link com.datastax.driver.core.ResultSet}. *

- * Returns a {@link java.util.Iterator} that wraps the a Cassandra {@link com.datastax.driver.core.ResultSet}. - * - * @param element return type - * @param query must not be empty and not {@literal null}. - * @param type must not be {@literal null}. - * @return + * Returns a {@link java.util.Iterator} that wraps the Cassandra {@link com.datastax.driver.core.ResultSet}. + * + * @param element return type. + * @param query query to execute. Must not be empty or {@literal null}. + * @param type Class type of the elements in the {@link Iterator} stream. Must not be {@literal null}. + * @return an {@link Iterator} (stream) over the elements in the query result set. * @since 1.5 */ Iterator stream(String query, Class type); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java index 7440a4d88..06a58959a 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java @@ -602,15 +602,22 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation @Override public ResultSet doInSession(Session s) throws DataAccessException { - return s.execute(query); + return s.execute(logCql(query)); } }); - if (resultSet == null) { - return Collections.emptyList().iterator(); - } + return (resultSet != null ? toIterator(resultSet, type) : Collections.emptyIterator()); + } - return new ResultSetIteratorAdapter(resultSet.iterator(), getExceptionTranslator(), new CassandraConverterRowCallback(cassandraConverter, type)); + /* + * (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraTemplate.ResultSetIteratorAdapter + */ + @SuppressWarnings("unchecked") + private Iterator toIterator(ResultSet resultSet, Class type) { + + return new ResultSetIteratorAdapter(resultSet.iterator(), getExceptionTranslator(), + new CassandraConverterRowCallback(cassandraConverter, type)); } protected List select(final Select query, CassandraConverterRowCallback readRowCallback) { @@ -1109,7 +1116,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation throw new IllegalArgumentException( String.format("Expected type String or Select; got type [%s] with value [%s]", query.getClass(), query)); } - + private static class ResultSetIteratorAdapter implements Iterator{ private final Iterator iterator; @@ -1117,7 +1124,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation private final CassandraConverterRowCallback rowCallback; public ResultSetIteratorAdapter(Iterator iterator, PersistenceExceptionTranslator exceptionTranslator, CassandraConverterRowCallback rowCallback) { - + this.iterator = iterator; this.exceptionTranslator = exceptionTranslator; this.rowCallback = rowCallback; @@ -1125,7 +1132,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation @Override public boolean hasNext() { - + try { return iterator.hasNext(); } catch (Exception e) { @@ -1135,7 +1142,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation @Override public T next() { - + try { return rowCallback.doWith(iterator.next()); } catch (Exception e) { diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/AbstractCassandraQuery.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/AbstractCassandraQuery.java index ccb89c6e6..57d769eb2 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/AbstractCassandraQuery.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/AbstractCassandraQuery.java @@ -104,14 +104,15 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery { return new ResultProcessingExecution(getExecutionToWrap(accessor, resultProcessing), resultProcessing); } - private CassandraQueryExecution getExecutionToWrap(CassandraParameterAccessor accessor, Converter resultProcessing) { + private CassandraQueryExecution getExecutionToWrap(CassandraParameterAccessor accessor, + Converter resultProcessing) { - if (method.isResultSetQuery()) { + if (method.isCollectionQuery()) { + return new CollectionExecution(template); + } else if (method.isResultSetQuery()) { return new ResultSetQuery(template); } else if (method.isStreamQuery()) { return new StreamExecution(template, resultProcessing); - } else if (method.isCollectionQuery()) { - return new CollectionExecution(template); } else { return new SingleEntityExecution(template); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/core/CassandraOperationsIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/core/CassandraOperationsIntegrationTests.java index 7443ca5d9..bb16e2353 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/core/CassandraOperationsIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/core/CassandraOperationsIntegrationTests.java @@ -24,7 +24,6 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -184,14 +183,16 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed @Test public void insertEmptyList() { List list = template.insert(new ArrayList()); - assertNotNull(list); - assertEquals(0, list.size()); + + assertThat(list, is(notNullValue(List.class))); + assertThat(list.isEmpty(), is(true)); } @Test public void insertNullList() { List list = template.insert((List) null); - assertNull(list); + + assertThat(list, is(nullValue(List.class))); } @Test @@ -253,21 +254,21 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed /** * @return */ - private List getBookList(int numBooks) { + private List getBookList(long numBooks) { List books = new ArrayList(); + Book book; - Book b = null; - for (int i = 0; i < numBooks; i++) { - b = new Book(); - b.setIsbn(UUID.randomUUID().toString()); - b.setTitle("Spring Data Cassandra Guide"); - b.setAuthor("Cassandra Guru"); - b.setPages(i * 10 + 5); - b.setInStock(true); - b.setSaleDate(new Date()); - b.setCondition(BookCondition.NEW); - books.add(b); + for (int index = 0; index < numBooks; index++) { + book = new Book(); + book.setIsbn(UUID.randomUUID().toString()); + book.setTitle("Spring Data Cassandra Guide"); + book.setAuthor("Cassandra Guru"); + book.setPages(index * 10 + 5); + book.setInStock(true); + book.setSaleDate(new Date()); + book.setCondition(BookCondition.NEW); + books.add(book); } return books; @@ -648,13 +649,13 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed Select select = QueryBuilder.select().all().from("book"); select.where(QueryBuilder.eq("isbn", "123456-1")); - Book b = template.selectOne(select, Book.class); + Book book = template.selectOne(select, Book.class); - log.debug("SingleSelect Book Title -> " + b.getTitle()); - log.debug("SingleSelect Book Author -> " + b.getAuthor()); + log.debug("SingleSelect Book Title -> " + book.getTitle()); + log.debug("SingleSelect Book Author -> " + book.getAuthor()); - assertEquals(b.getTitle(), "Spring Data Cassandra Guide"); - assertEquals(b.getAuthor(), "Cassandra Guru"); + assertThat(book.getTitle(), is(equalTo("Spring Data Cassandra Guide"))); + assertThat(book.getAuthor(), is(equalTo("Cassandra Guru"))); } @@ -667,39 +668,39 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed Select select = QueryBuilder.select().all().from("book"); - List bookz = template.select(select, Book.class); + List selectedBooks = template.select(select, Book.class); - log.debug("Book Count -> " + bookz.size()); + log.debug("Book Count -> " + selectedBooks.size()); - assertEquals(bookz.size(), 20); + assertThat(selectedBooks.size(), is(equalTo(20))); - for (Book b : bookz) { - Assert.assertTrue(b.isInStock()); - assertEquals(BookCondition.NEW, b.getCondition()); + for (Book book : selectedBooks) { + assertThat(book.isInStock(), is(true)); + assertThat(book.getCondition(), is(equalTo(BookCondition.NEW))); } } @Test public void selectCountTest() { - int count = 20; + long count = 20; List books = getBookList(count); template.insert(books); - assertEquals(count, template.count(Book.class)); + assertThat(template.count(Book.class), is(equalTo(count))); } @Test public void insertAndSelect() { - int count = 20; + long count = 20; List books = getBookList(count); template.insert(books); - assertEquals(count, template.count(Book.class)); + assertThat(template.count(Book.class), is(equalTo(count))); } /** @@ -708,16 +709,27 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed @Test public void stream() { - List books = getBookList(20); - template.insert(books); + template.insert(getBookList(20)); - Iterator iterator = template.stream("select * from book", Book.class); - List result = new ArrayList(); - while (iterator.hasNext()) { - result.add(iterator.next()); + Iterator iterator = template.stream("SELECT * FROM book", Book.class); + + assertThat(iterator, is(notNullValue(Iterator.class))); + + List selectedBooks = new ArrayList(); + + for (Book book : toIterable(iterator)) { + selectedBooks.add(book); } - assertThat(books.size(), is(20)); - assertThat(books.get(0), is(instanceOf(Book.class))); + assertThat(selectedBooks.size(), is(equalTo(20))); + assertThat(selectedBooks.get(0), is(instanceOf(Book.class))); + } + + Iterable toIterable(final Iterator iterator) { + return new Iterable() { + @Override public Iterator iterator() { + return iterator; + } + }; } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/querymethods/declared/QueryIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/querymethods/declared/QueryIntegrationTests.java index ec169e251..7c74cd436 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/querymethods/declared/QueryIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/querymethods/declared/QueryIntegrationTests.java @@ -278,17 +278,20 @@ public abstract class QueryIntegrationTests extends AbstractSpringDataEmbeddedCa @Test public void findOptionalShouldReturnTargetType() { - Person saved = new Person(); - saved.setFirstname(uuid()); - saved.setLastname(uuid()); - saved.setNumberOfChildren(1); + Person personToSave = new Person(); - saved = personRepository.save(saved); + personToSave.setFirstname(uuid()); + personToSave.setLastname(uuid()); + personToSave.setNumberOfChildren(1); - Optional optional = personRepository.findOptionalWithLastnameAndFirstname(saved.getLastname(), saved.getFirstname()); + personToSave = personRepository.save(personToSave); - assertTrue(optional.isPresent()); - assertTrue(optional.get() instanceof Person); + Optional savedPerson = personRepository.findOptionalWithLastnameAndFirstname( + personToSave.getLastname(), personToSave.getFirstname()); + + assertThat(savedPerson, is(notNullValue(Optional.class))); + assertThat(savedPerson.isPresent(), is(true)); + assertThat(savedPerson.get(), is(notNullValue(Person.class))); } @Test @@ -296,26 +299,27 @@ public abstract class QueryIntegrationTests extends AbstractSpringDataEmbeddedCa Optional optional = personRepository.findOptionalWithLastnameAndFirstname("not", "existent"); - assertFalse(optional.isPresent()); + assertThat(optional.isPresent(), is(false)); } /** - * @see DATACASS-297 + * @see https://jira.spring.io/browse/DATACASS-297 */ @Test public void streamShouldReturnEntities() { for (int i = 0; i < 100; i++) { - Person person = new Person(); + person.setFirstname(uuid()); person.setLastname(uuid()); person.setNumberOfChildren(i); - + personRepository.save(person); } Stream allPeople = personRepository.findAllPeople(); + long count = allPeople.peek(new Consumer() { @Override public void accept(Person person) { @@ -323,6 +327,6 @@ public abstract class QueryIntegrationTests extends AbstractSpringDataEmbeddedCa } }).count(); - assertThat(count, is(100L)); + assertThat(count, is(equalTo(100L))); } }