diff --git a/src/main/java/org/couchbase/quickstart/springdata/Application.java b/src/main/java/org/couchbase/quickstart/springdata/Application.java index 103adf5..ee7a4f1 100644 --- a/src/main/java/org/couchbase/quickstart/springdata/Application.java +++ b/src/main/java/org/couchbase/quickstart/springdata/Application.java @@ -2,9 +2,12 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; import org.springframework.web.filter.ForwardedHeaderFilter; import io.swagger.v3.oas.annotations.OpenAPIDefinition; @@ -19,6 +22,7 @@ @Slf4j @SpringBootApplication(exclude = SecurityAutoConfiguration.class, proxyBeanMethods = false) @OpenAPIDefinition(info = @Info(title = "Quickstart in Couchbase with Spring Data", version = "2.0", description = "

A quickstart API using Java and Spring Data with Couchbase and travel-sample data

We have a visual representation of the API documentation using Swagger which allows you to interact with the API's endpoints directly through the browser. It provides a clear view of the API including endpoints, HTTP methods, request parameters, and response objects.

Click on an individual endpoint to expand it and see detailed information. This includes the endpoint's description, possible response status codes, and the request parameters it accepts.

Trying Out the API

You can try out an API by clicking on the \"Try it out\" button next to the endpoints.

Models

Swagger documents the structure of request and response bodies using models. These models define the expected data structure using JSON schema and are extremely helpful in understanding what data to send and expect.

For details on the API, please check the tutorial on the Couchbase Developer Portal: https://developer.couchbase.com/tutorial-quickstart-java-spring-boot

")) +@EnableCouchbaseRepositories(basePackages = "org.couchbase.quickstart.springdata.repository") public class Application implements CommandLineRunner { @Override diff --git a/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfig.java b/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfig.java new file mode 100644 index 0000000..9092220 --- /dev/null +++ b/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfig.java @@ -0,0 +1,90 @@ +package org.couchbase.quickstart.springdata.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.couchbase.client.core.error.CouchbaseException; +import com.couchbase.client.core.msg.kv.DurabilityLevel; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.manager.bucket.BucketSettings; +import com.couchbase.client.java.manager.bucket.BucketType; + +import lombok.extern.slf4j.Slf4j; + +@Configuration +@Slf4j +public class CouchbaseConfig { + + private final DBProperties dbProp; + + public CouchbaseConfig(DBProperties dbProp) { + this.dbProp = dbProp; + } + + + /** + * NOTE: If connecting to Couchbase Capella, you must enable TLS. + *

+ * The simplest way to enable TLS is to edit {@code application.properties} + * and make sure the {@code spring.couchbase.bootstrap-hosts} config property + * starts with "couchbases://" (note the final 's'), like this: + *

+     * spring.couchbase.bootstrap-hosts=couchbases://my-cluster.cloud.couchbase.com
+     * 
+ * Alternatively, you can enable TLS by writing code to configure the cluster environment; + * see the commented-out code in this method for an example. + */ + @Bean(destroyMethod = "disconnect") + public Cluster getCouchbaseCluster() { + try { + log.debug("Connecting to Couchbase cluster at " + dbProp.getHostName()); + return Cluster.connect(dbProp.getHostName(), dbProp.getUsername(), dbProp.getPassword()); + + // Here is an alternative version that enables TLS by configuring the cluster environment. +/* return Cluster.connect( + dbProp.getHostName(), + ClusterOptions.clusterOptions(dbProp.getUsername(), dbProp.getPassword()) + .environment(env -> { // Configure cluster environment properties here + env.securityConfig().enableTls(true); + + // If you're connecting to Capella, the SDK already knows which certificates to trust. + // When using TLS with non-Capella clusters, you must tell the SDK which certificates to trust. + env.securityConfig().trustCertificate( + Paths.get("/path/to/trusted-root-certificate.pem") + ); + }) + ); + + */ + + } catch (CouchbaseException e) { + log.error("Could not connect to Couchbase cluster at " + dbProp.getHostName()); + log.error("Please check the username (" + dbProp.getUsername() + ") and password (" + dbProp.getPassword() + ")"); + throw e; + } catch (Exception e) { + log.error("Could not connect to Couchbase cluster at " + dbProp.getHostName()); + throw e; + } + + } + + @Bean + public Bucket getCouchbaseBucket(Cluster cluster) { + + try { + // Creates the cluster if it does not exist yet + if (!cluster.buckets().getAllBuckets().containsKey(dbProp.getBucketName())) { + cluster.buckets().createBucket( + BucketSettings.create(dbProp.getBucketName()) + .bucketType(BucketType.COUCHBASE) + .minimumDurabilityLevel(DurabilityLevel.NONE) + .ramQuotaMB(128)); + } + return cluster.bucket(dbProp.getBucketName()); + } catch (Exception e) { + log.error("Could not connect to Couchbase bucket " + dbProp.getBucketName()); + throw e; + } + } +} diff --git a/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfiguration.java b/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfiguration.java index 31fcd30..75b6e47 100644 --- a/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfiguration.java +++ b/src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfiguration.java @@ -1,84 +1,84 @@ -package org.couchbase.quickstart.springdata.config; +// package org.couchbase.quickstart.springdata.config; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; -import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; +// import org.springframework.beans.factory.annotation.Value; +// import org.springframework.context.annotation.Bean; +// import org.springframework.context.annotation.Configuration; +// import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; +// import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; -import com.couchbase.client.core.msg.kv.DurabilityLevel; -import com.couchbase.client.java.Bucket; -import com.couchbase.client.java.Cluster; -import com.couchbase.client.java.manager.bucket.BucketSettings; -import com.couchbase.client.java.manager.bucket.BucketType; +// import com.couchbase.client.core.msg.kv.DurabilityLevel; +// import com.couchbase.client.java.Bucket; +// import com.couchbase.client.java.Cluster; +// import com.couchbase.client.java.manager.bucket.BucketSettings; +// import com.couchbase.client.java.manager.bucket.BucketType; -@Configuration -@EnableCouchbaseRepositories -public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration { +// @Configuration +// @EnableCouchbaseRepositories +// public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration { - @Value("${spring.couchbase.bootstrap-hosts}") - private String host; +// @Value("${spring.couchbase.bootstrap-hosts}") +// private String host; - @Value("${spring.couchbase.bucket.user}") - private String username; +// @Value("${spring.couchbase.bucket.user}") +// private String username; - @Value("${spring.couchbase.bucket.password}") - private String password; +// @Value("${spring.couchbase.bucket.password}") +// private String password; - @Value("${spring.couchbase.bucket.name}") - private String bucket; +// @Value("${spring.couchbase.bucket.name}") +// private String bucket; - @Override - public String getConnectionString() { - // To connect to capella: - // - with ssl certificate validation: - // return "couchbases://cb.jnym5s9gv4ealbe.cloud.couchbase.com" - // - without ssl validation: - // return "couchbases://cb.jnym5s9gv4ealbe.cloud.couchbase.com?tls=no_verify" - // (replace cb.jnym5s9gv4ealbe.cloud.couchbase.com with your Capella cluster - // address) +// @Override +// public String getConnectionString() { +// // To connect to capella: +// // - with ssl certificate validation: +// // return "couchbases://cb.jnym5s9gv4ealbe.cloud.couchbase.com" +// // - without ssl validation: +// // return "couchbases://cb.jnym5s9gv4ealbe.cloud.couchbase.com?tls=no_verify" +// // (replace cb.jnym5s9gv4ealbe.cloud.couchbase.com with your Capella cluster +// // address) - return host; - } +// return host; +// } - @Override - public String getUserName() { - return username; - } +// @Override +// public String getUserName() { +// return username; +// } - @Override - public String getPassword() { - return password; - } +// @Override +// public String getPassword() { +// return password; +// } - @Override - public String getBucketName() { - return bucket; - } +// @Override +// public String getBucketName() { +// return bucket; +// } - @Override - public String typeKey() { - return "type"; - } +// @Override +// public String typeKey() { +// return "type"; +// } - @Bean - public Bucket getCouchbaseBucket(Cluster cluster){ - // verify that bucket exists - if (!cluster.buckets().getAllBuckets().containsKey(getBucketName())) { - // create the bucket if it doesn't - cluster.buckets().createBucket( - BucketSettings.create(getBucketName()) - .bucketType(BucketType.COUCHBASE) - .minimumDurabilityLevel(DurabilityLevel.NONE) - .ramQuotaMB(128)); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - e.printStackTrace(); - } - } - return cluster.bucket(getBucketName()); - } -} \ No newline at end of file +// // @Bean +// // public Bucket getCouchbaseBucket(Cluster cluster){ +// // // verify that bucket exists +// // if (!cluster.buckets().getAllBuckets().containsKey(getBucketName())) { +// // // create the bucket if it doesn't +// // cluster.buckets().createBucket( +// // BucketSettings.create(getBucketName()) +// // .bucketType(BucketType.COUCHBASE) +// // .minimumDurabilityLevel(DurabilityLevel.NONE) +// // .ramQuotaMB(128)); +// // try { +// // Thread.sleep(1000); +// // } catch (InterruptedException e) { +// // Thread.currentThread().interrupt(); +// // e.printStackTrace(); +// // } +// // } +// // return cluster.bucket(getBucketName()); +// // } +// } \ No newline at end of file diff --git a/src/main/java/org/couchbase/quickstart/springdata/config/DBProperties.java b/src/main/java/org/couchbase/quickstart/springdata/config/DBProperties.java new file mode 100644 index 0000000..758a8e6 --- /dev/null +++ b/src/main/java/org/couchbase/quickstart/springdata/config/DBProperties.java @@ -0,0 +1,21 @@ +package org.couchbase.quickstart.springdata.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +import lombok.Getter; + +@Configuration +@Getter +public class DBProperties { + + @Value("${spring.couchbase.bootstrap-hosts}") + private String hostName; + @Value("${spring.couchbase.bucket.user}") + private String username; + @Value("${spring.couchbase.bucket.password}") + private String password; + @Value("${spring.couchbase.bucket.name}") + private String bucketName; + +} diff --git a/src/main/java/org/couchbase/quickstart/springdata/services/AirlineService.java b/src/main/java/org/couchbase/quickstart/springdata/services/AirlineService.java index 3607ff5..b01179b 100644 --- a/src/main/java/org/couchbase/quickstart/springdata/services/AirlineService.java +++ b/src/main/java/org/couchbase/quickstart/springdata/services/AirlineService.java @@ -1,54 +1,26 @@ package org.couchbase.quickstart.springdata.services; - import java.util.Optional; import org.couchbase.quickstart.springdata.models.Airline; -import org.couchbase.quickstart.springdata.repository.AirlineRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -@Service -public class AirlineService { - - private final AirlineRepository airlineRepository; - - public AirlineService(AirlineRepository airlineRepository) { - this.airlineRepository = airlineRepository; - } - public Page getAllAirlines(Pageable pageable) { - return airlineRepository.findAll(pageable); - } +public interface AirlineService { - public Optional getAirlineById(String id) { - return airlineRepository.findById(id); - } + Page getAllAirlines(Pageable pageable); - public Airline saveAirline(Airline airline) { - return airlineRepository.save(airline); - } + Optional getAirlineById(String id); - public void deleteAirline(String id) { - airlineRepository.deleteById(id); - } + Airline saveAirline(Airline airline); - public Airline createAirline(Airline airline) { - return airlineRepository.save(airline); - } + void deleteAirline(String id); - public Airline updateAirline(String id, Airline airline) { - airline.setId(id); - return airlineRepository.save(airline); - } + Airline createAirline(Airline airline); - public Page findByCountry(String country, Pageable pageable) { - return airlineRepository.findByCountry(country,pageable); - } + Airline updateAirline(String id, Airline airline); - public Page findByDestinationAirport(String destinationAirport, Pageable pageable) { - return airlineRepository.findByDestinationAirport(destinationAirport, pageable); - } + Page findByCountry(String country, Pageable pageable); + Page findByDestinationAirport(String destinationAirport, Pageable pageable); } diff --git a/src/main/java/org/couchbase/quickstart/springdata/services/AirlineServiceImpl.java b/src/main/java/org/couchbase/quickstart/springdata/services/AirlineServiceImpl.java new file mode 100644 index 0000000..910a67a --- /dev/null +++ b/src/main/java/org/couchbase/quickstart/springdata/services/AirlineServiceImpl.java @@ -0,0 +1,60 @@ +package org.couchbase.quickstart.springdata.services; + +import java.util.Optional; + +import org.couchbase.quickstart.springdata.models.Airline; +import org.couchbase.quickstart.springdata.repository.AirlineRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class AirlineServiceImpl implements AirlineService { + + private final AirlineRepository airlineRepository; + + public AirlineServiceImpl(AirlineRepository airlineRepository) { + this.airlineRepository = airlineRepository; + } + + @Override + public Page getAllAirlines(Pageable pageable) { + return airlineRepository.findAll(pageable); + } + + @Override + public Optional getAirlineById(String id) { + return airlineRepository.findById(id); + } + + @Override + public Airline saveAirline(Airline airline) { + return airlineRepository.save(airline); + } + + @Override + public void deleteAirline(String id) { + airlineRepository.deleteById(id); + } + + @Override + public Airline createAirline(Airline airline) { + return airlineRepository.save(airline); + } + + @Override + public Airline updateAirline(String id, Airline airline) { + airline.setId(id); + return airlineRepository.save(airline); + } + + @Override + public Page findByCountry(String country, Pageable pageable) { + return airlineRepository.findByCountry(country, pageable); + } + + @Override + public Page findByDestinationAirport(String destinationAirport, Pageable pageable) { + return airlineRepository.findByDestinationAirport(destinationAirport, pageable); + } +}