#265 - Polishing.

Add license headers. Replace CouchbaseConfiguration with Spring Boot properties. Post-process example data to make it accessible for repository use. Fix Id type. Add examples for N1ql and view access.

Enable couchbase examples in parent pom.

Add test rule to skip tests if Couchbase is not available.

Original pull request: #275.
This commit is contained in:
Mark Paluch
2017-11-21 13:03:04 +01:00
parent 5ba65308a7
commit b61875f97c
13 changed files with 371 additions and 155 deletions

View File

@@ -1,35 +0,0 @@
package example.springdata.couchbase;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
import java.util.Collections;
import java.util.List;
/**
* Couchbase Configuration to connect to Couchbase data store
*
* @author Chandana Kithalagama
*/
@SpringBootApplication
@Configuration
@EnableCouchbaseRepositories
public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
@Override
protected List<String> getBootstrapHosts() {
return Collections.singletonList("192.168.99.100");
}
@Override
protected String getBucketName() {
return "travel-sample";
}
@Override
protected String getBucketPassword() {
return "";
}
}

View File

@@ -1,9 +1,26 @@
/*
* Copyright 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 example.springdata.couchbase.model;
import lombok.Data;
import org.springframework.data.couchbase.core.mapping.Document;
import com.couchbase.client.java.repository.annotation.Field;
import com.couchbase.client.java.repository.annotation.Id;
import lombok.*;
import org.springframework.data.couchbase.core.mapping.Document;
/**
* A domain object representing an Airline
@@ -11,13 +28,11 @@ import org.springframework.data.couchbase.core.mapping.Document;
* @author Chandana Kithalagama
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document
public class Airline {
@Id
private int id;
private String id;
@Field
private String type;
@@ -36,5 +51,4 @@ public class Airline {
@Field
private String country;
}

View File

@@ -1,18 +1,52 @@
/*
* Copyright 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 example.springdata.couchbase.repository;
import example.springdata.couchbase.model.Airline;
import org.springframework.data.couchbase.core.query.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
import org.springframework.data.couchbase.core.query.N1qlPrimaryIndexed;
import org.springframework.data.couchbase.core.query.View;
import org.springframework.data.couchbase.core.query.ViewIndexed;
import org.springframework.data.repository.CrudRepository;
/**
* Repository interface to manage {@link Airline} instances.
*
* @author Chandana Kithalagama
* @author Mark Paluch
*/
public interface AirlineRepository extends CrudRepository<Airline, Integer>{
@N1qlPrimaryIndexed
@ViewIndexed(designDoc = "airlines")
public interface AirlineRepository extends CrudRepository<Airline, String> {
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND name = $1")
List<Airline> findAirlineByName(String name);
/**
* Derived query selecting by {@code iataCode}.
*
* @param code
* @return
*/
Airline findAirlineByIataCode(String code);
/**
* Query method using {@code airlines/all} view.
*
* @return
*/
@View(designDocument = "airlines", viewName = "all")
List<Airline> findAllBy();
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 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 example.springdata.couchbase.repository;
import example.springdata.couchbase.model.Airline;
import lombok.RequiredArgsConstructor;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.data.couchbase.repository.support.IndexManager;
import com.couchbase.client.java.query.N1qlQuery;
/**
* Simple configuration class.
*
* @author Chandana Kithalagama
* @author Mark Paluch
*/
@SpringBootApplication
@RequiredArgsConstructor
public class CouchbaseConfiguration {
private final CouchbaseOperations couchbaseOperations;
/**
* Create an {@link IndexManager} that allows index creation.
*
* @return
*/
@Bean(name = BeanNames.COUCHBASE_INDEX_MANAGER)
public IndexManager indexManager() {
return new IndexManager(true, true, false);
}
@PostConstruct
private void postConstruct() {
// Need to post-process travel data to add _class attribute
List<Airline> airlinesWithoutClassAttribute = couchbaseOperations.findByN1QL(N1qlQuery.simple( //
"SELECT META(`travel-sample`).id AS _ID, META(`travel-sample`).cas AS _CAS, `travel-sample`.* " + //
"FROM `travel-sample` " + //
"WHERE type = \"airline\" AND _class IS MISSING;"),
Airline.class);
airlinesWithoutClassAttribute.forEach(couchbaseOperations::save);
}
}

View File

@@ -0,0 +1,9 @@
spring.couchbase.bucket.name=travel-sample
spring.couchbase.bootstrap-hosts=localhost
# Required for Couchbase 5
spring.couchbase.bucket.password=password
# Increased timeout to fit slower environments like TravisCI
spring.couchbase.env.timeouts.view=15000
spring.couchbase.env.timeouts.query=15000

View File

@@ -1,84 +0,0 @@
package example.springdata.couchbase.repository;
import example.springdata.couchbase.CouchbaseConfiguration;
import example.springdata.couchbase.model.Airline;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for basic CRUD operations
*
* @author Chandana Kithalagama
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CouchbaseConfiguration.class)
public class AirlineRepositoryIntegrationTest {
@Autowired
AirlineRepository airlineRepository;
Airline a, b, c;
List<Airline> airlineList;
@Before
public void setup() {
a = new Airline(20000,"airline", "CK 1", "LK", "CMB", "CLK","Sri Lanka");
b = new Airline(20001,"airline", "CK 2", "LK", "CMB", "CLK","Sri Lanka");
c = new Airline(20002,"airline", "CK 3", "LK", "CMB", "CLK","Sri Lanka");
airlineList = Arrays.asList(a, b, b);
}
@Test
public void testSaveAirline() {
Iterable<Airline> itr = airlineRepository.save(Arrays.asList(a));
assertThat(itr).isNotNull();
Airline airline = airlineRepository.findOne(a.getId());
assertThat(airline).isNotNull();
assertThat(airline).isEqualTo(a);
assertThat(airline).isNotEqualTo(b);
airlineRepository.delete(a.getId());
}
@Test
public void testGetAllAirlines() {
Iterable<Airline> itr = airlineRepository.save(airlineList);
assertThat(itr).isNotNull();
Iterable<Airline> itr2 = airlineRepository.findAll(Arrays.asList(a.getId(), b.getId(), c.getId()));
assertThat(itr2).isNotNull();
airlineRepository.delete(airlineList);
}
@Test
public void testDeleteAirlines() {
Iterable<Airline> itr = airlineRepository.save(Arrays.asList(a));
assertThat(itr).isNotNull();
airlineRepository.delete(a.getId());
Airline airline = airlineRepository.findOne(a.getId());
assertThat(airline).isNull();
}
@Test
public void testGetByName() {
Iterable<Airline> itr = airlineRepository.save(Arrays.asList(a));
assertThat(itr).isNotNull();
List<Airline> airlines = airlineRepository.findAirlineByName(a.getName());
assertThat(airlines.size()).isGreaterThanOrEqualTo(1);
assertThat(airlines.get(0)).isEqualTo(a);
airlineRepository.delete(a.getId());
}
@After
public void tearDown() {
airlineRepository.delete(airlineList);
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 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 example.springdata.couchbase.repository;
import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration tests showing basic CRUD operations through {@link AirlineRepository}.
*
* @author Chandana Kithalagama
* @author Mark Paluch
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class AirlineRepositoryIntegrationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Autowired
AirlineRepository airlineRepository;
@Autowired CouchbaseOperations couchbaseOperations;
@Before
public void before() {
airlineRepository.findById("LH").ifPresent(couchbaseOperations::remove);
}
/**
* The derived query executes a N1QL query emitting a single element.
*/
@Test
public void shouldFindAirlineN1ql() {
Airline airline = airlineRepository.findAirlineByIataCode("TQ");
assertThat(airline.getCallsign()).isEqualTo("TXW");
}
/**
* The derived query executes a N1QL query and the emitted element is used to invoke
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based
* lookup. Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
Airline airline = airlineRepository.findAirlineByIataCode("TQ");
assertThat(airlineRepository.findById(airline.getId())).contains(airline);
assertThat(airlineRepository.findById("unknown")).isEmpty();
}
/**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindByView() {
List<Airline> airlines = airlineRepository.findAllBy();
assertThat(airlines).hasSize(187);
}
/**
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline();
airline.setId("LH");
airline.setIataCode("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airlineRepository.save(airline);
assertThat(airlineRepository.findById("LH")).contains(airline);
}
}