/* * Copyright 2016-2017 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.data.cassandra.repository; import static org.assertj.core.api.Assertions.*; import io.reactivex.Flowable; import io.reactivex.Maybe; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import rx.Observable; import rx.Single; import java.util.Arrays; import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.core.ReactiveCassandraTemplate; import org.springframework.data.cassandra.domain.Person; import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories; import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig; import org.springframework.data.repository.reactive.ReactiveCrudRepository; import org.springframework.data.repository.reactive.RxJava1CrudRepository; import org.springframework.data.repository.reactive.RxJava2CrudRepository; import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.datastax.driver.core.KeyspaceMetadata; import com.datastax.driver.core.Session; import com.datastax.driver.core.TableMetadata; /** * Test for {@link ReactiveCassandraRepository} using reactive wrapper type conversion. * * @author Mark Paluch * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ConvertingReactiveCassandraRepositoryTests.Config.class) public class ConvertingReactiveCassandraRepositoryTests extends AbstractKeyspaceCreatingIntegrationTest { @EnableReactiveCassandraRepositories(includeFilters = @Filter(value = Repository.class), considerNestedRepositories = true) @Configuration public static class Config extends IntegrationTestConfig { @Override public String[] getEntityBasePackages() { return new String[] { Person.class.getPackage().getName() }; } } @Autowired Session session; @Autowired ReactiveCassandraTemplate template; @Autowired MixedPersonRepository reactiveRepository; @Autowired PersonRepostitory reactivePersonRepostitory; @Autowired RxJava1PersonRepostitory rxJava1PersonRepostitory; @Autowired RxJava2PersonRepostitory rxJava2PersonRepostitory; Person dave, oliver, carter, boyd; @Before public void setUp() throws Exception { KeyspaceMetadata keyspace = session.getCluster().getMetadata().getKeyspace(session.getLoggedKeyspace()); TableMetadata person = keyspace.getTable("person"); if (person.getIndex("IX_person_lastname") == null) { session.execute("CREATE INDEX IX_person_lastname ON person (lastname);"); Thread.sleep(500); } StepVerifier.create(reactiveRepository.deleteAll()).verifyComplete(); dave = new Person("42", "Dave", "Matthews"); oliver = new Person("4", "Oliver August", "Matthews"); carter = new Person("49", "Carter", "Beauford"); boyd = new Person("45", "Boyd", "Tinsley"); StepVerifier.create(reactiveRepository.saveAll(Arrays.asList(oliver, dave, carter, boyd))).expectNextCount(4) .verifyComplete(); } @Test // DATACASS-335 public void reactiveStreamsMethodsShouldWork() { StepVerifier.create(reactivePersonRepostitory.existsById(dave.getId())).expectNext(true).verifyComplete(); } @Test // DATACASS-335 public void reactiveStreamsQueryMethodsShouldWork() { StepVerifier.create(reactivePersonRepostitory.findByLastname(boyd.getLastname())).expectNext(boyd).verifyComplete(); } @Test // DATACASS-360 public void dtoProjectionShouldWork() { StepVerifier.create(reactivePersonRepostitory.findProjectedByLastname(boyd.getLastname())) .consumeNextWith(actual -> { assertThat(actual.firstname).isEqualTo(boyd.getFirstname()); assertThat(actual.lastname).isEqualTo(boyd.getLastname()); }).verifyComplete(); } @Test // DATACASS-335 public void simpleRxJava1MethodsShouldWork() { rxJava1PersonRepostitory.existsById(dave.getId()) // .test() // .awaitTerminalEvent() // .assertResult(true) // .assertCompleted() // .assertNoErrors(); } @Test // DATACASS-335 public void existsWithSingleRxJava1IdMethodsShouldWork() { rxJava1PersonRepostitory.existsById(Single.just(dave.getId())) // .test() // .awaitTerminalEvent() // .assertResult(true) // .assertCompleted() // .assertNoErrors(); } @Test // DATACASS-335 public void singleRxJava1QueryMethodShouldWork() { rxJava1PersonRepostitory.findManyByLastname(dave.getLastname()) // .test() // .awaitTerminalEvent() // .assertValueCount(2) // .assertNoErrors() // .assertCompleted(); } @Test // DATACASS-335 public void singleProjectedRxJava1QueryMethodShouldWork() { List<ProjectedPerson> values = rxJava1PersonRepostitory.findProjectedByLastname(carter.getLastname()) // .test() // .awaitTerminalEvent() // .assertValueCount(1) // .assertCompleted() // .assertNoErrors() // .getOnNextEvents(); ProjectedPerson projectedPerson = values.get(0); assertThat(projectedPerson.getFirstname()).isEqualTo(carter.getFirstname()); } @Test // DATACASS-335 public void observableRxJava1QueryMethodShouldWork() { rxJava1PersonRepostitory.findByLastname(boyd.getLastname()) // .test() // .awaitTerminalEvent() // .assertValue(boyd) // .assertNoErrors() // .assertCompleted(); } @Test // DATACASS-398 public void simpleRxJava2MethodsShouldWork() { rxJava2PersonRepostitory.existsById(dave.getId()) // .test()// .assertValue(true) // .assertNoErrors() // .assertComplete() // .awaitTerminalEvent(); } @Test // DATACASS-398 public void existsWithSingleRxJava2IdMethodsShouldWork() { rxJava2PersonRepostitory.existsById(io.reactivex.Single.just(dave.getId())).test() // .assertValue(true) // .assertNoErrors() // .assertComplete() // .awaitTerminalEvent(); } @Test // DATACASS-398 public void flowableRxJava2QueryMethodShouldWork() { rxJava2PersonRepostitory.findManyByLastname(dave.getLastname()) // .test() // .assertValueCount(2) // .assertNoErrors() // .assertComplete() // .awaitTerminalEvent(); } @Test // DATACASS-398 public void singleProjectedRxJava2QueryMethodShouldWork() { rxJava2PersonRepostitory.findProjectedByLastname(Maybe.just(carter.getLastname())) // .test() // .assertValue(actual -> { assertThat(actual.getFirstname()).isEqualTo(carter.getFirstname()); return true; }) // .assertComplete() // .assertNoErrors() // .awaitTerminalEvent(); } @Test // DATACASS-398 public void observableProjectedRxJava2QueryMethodShouldWork() { rxJava2PersonRepostitory.findProjectedByLastname(Single.just(carter.getLastname())) // .test() // .assertValue(actual -> { assertThat(actual.getFirstname()).isEqualTo(carter.getFirstname()); return true; }) // .assertComplete() // .assertNoErrors() // .awaitTerminalEvent(); } @Test // DATACASS-398 public void maybeRxJava2QueryMethodShouldWork() { rxJava2PersonRepostitory.findByLastname(boyd.getLastname()) // .test() // .assertValue(boyd) // .assertNoErrors() // .assertComplete() // .awaitTerminalEvent(); } @Test // DATACASS-335 public void mixedRepositoryShouldWork() { reactiveRepository.findByLastname(boyd.getLastname()) // .test() // .awaitTerminalEvent() // .assertValue(boyd) // .assertCompleted() // .assertNoErrors(); } @Test // DATACASS-335 public void shouldFindByIdByPublisherOfLastName() { StepVerifier.create(reactiveRepository.findByLastname(Single.just(this.carter.getLastname()))) // .expectNext(carter) // .verifyComplete(); } @Repository interface PersonRepostitory extends ReactiveCrudRepository<Person, String> { Publisher<Person> findByLastname(String lastname); Flux<PersonDto> findProjectedByLastname(String lastname); } @Repository interface RxJava1PersonRepostitory extends RxJava1CrudRepository<Person, String> { Observable<Person> findManyByLastname(String lastname); Single<Person> findByLastname(String lastname); Single<ProjectedPerson> findProjectedByLastname(String lastname); } @Repository interface RxJava2PersonRepostitory extends RxJava2CrudRepository<Person, String> { Flowable<Person> findManyByLastname(String lastname); Maybe<Person> findByLastname(String lastname); io.reactivex.Single<ProjectedPerson> findProjectedByLastname(Maybe<String> lastname); io.reactivex.Observable<ProjectedPerson> findProjectedByLastname(Single<String> lastname); } @Repository interface MixedPersonRepository extends ReactiveCassandraRepository<Person, String> { Single<Person> findByLastname(String lastname); Mono<Person> findByLastname(Single<String> lastname); } interface ProjectedPerson { String getId(); String getFirstname(); } static class PersonDto { public String firstname, lastname; public PersonDto(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } } }