Skip to content

Commit bd6f667

Browse files
authored
(feat) update project config (#59)
* Update project configuration and dependencies - Added .env and .DS_Store to .gitignore. - Updated Gradle wrapper to version 9.0. - Changed base.archivesName in build.gradle for consistency. - Added dotenv-java dependency for environment variable loading. - Refactored Couchbase configuration to use updated property names. - Modified AirportController and AirportRepository to use Slice instead of Page for direct connections. - Updated integration tests to reflect changes in response types and improved error logging. These changes enhance the project's configuration and improve the handling of Couchbase connections. * Update Gradle wrapper and enhance logging in DotEnvConfiguration - Updated Gradle wrapper distribution URL to version 9.0.0. - Replaced System.out logging with SLF4J logging in DotEnvConfiguration for better logging practices. - Added @JsonIgnoreProperties annotation to RestResponseSlice to ignore unknown properties during JSON deserialization. These changes improve project configuration and logging consistency. * Refactor logging in integration tests and remove unused dependency - Removed the unused 'jakarta.persistence:jakarta.persistence-api' dependency from build.gradle. - Updated error logging in AirlineIntegrationTest, AirportIntegrationTest, and RouteIntegrationTest to use debug level for expected cleanup failures. These changes streamline the project by eliminating unnecessary dependencies and improving logging clarity during test cleanup.
1 parent c8ef268 commit bd6f667

File tree

17 files changed

+200
-31
lines changed

17 files changed

+200
-31
lines changed

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copy this file to .env and update with your actual values
2+
# DO NOT commit .env file to git - it's already in .gitignore
3+
#
4+
# These environment variables are used for database connection
5+
# and correspond to the Spring Boot 3.5+ Couchbase properties:
6+
# - spring.couchbase.connection-string
7+
# - spring.couchbase.username
8+
# - spring.couchbase.password
9+
10+
DB_CONN_STR=couchbases://your-cluster-url.cloud.couchbase.com
11+
DB_USERNAME=your-username
12+
DB_PASSWORD=your-password

.github/workflows/tests.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ jobs:
3131
uses: actions/setup-java@v4
3232
with:
3333
java-version: ${{ matrix.java-version }}
34-
distribution: "adopt"
34+
distribution: "temurin"
3535
cache: "gradle"
3636

37+
- name: Setup Gradle
38+
uses: gradle/actions/setup-gradle@v4
39+
with:
40+
gradle-home-cache-cleanup: true
41+
3742
- name: Run Gradle Tests
3843
id: run
3944
run: |
4045
chmod +x gradlew
41-
./gradlew clean test --info --stacktrace
46+
./gradlew clean test --info --stacktrace --configuration-cache
4247
4348
- name: Report Status
4449
if: always()

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
.env
2+
3+
.DS_Store
14
*.iml
5+
logs/
26

37
.gradle
48
build/

build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66

77
group = 'org.couchbase.quickstart.springdata'
88
version = '0.0.1-SNAPSHOT'
9-
archivesBaseName = 'java-springdata-quickstart'
9+
base.archivesName = 'java-springdata-quickstart'
1010

1111
repositories {
1212
mavenCentral()
@@ -24,8 +24,10 @@ dependencies {
2424
implementation 'org.springframework.data:spring-data-couchbase'
2525
implementation 'org.springframework.boot:spring-boot-devtools'
2626

27-
implementation 'jakarta.persistence:jakarta.persistence-api'
2827
implementation 'jakarta.servlet:jakarta.servlet-api'
28+
29+
// Environment variable loading from .env file
30+
implementation 'io.github.cdimascio:dotenv-java:3.0.2'
2931

3032
// lombok
3133
compileOnly 'org.projectlombok:lombok'

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

src/main/java/org/couchbase/quickstart/springdata/config/CouchbaseConfiguration.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@
1818
@EnableCouchbaseRepositories
1919
public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
2020

21-
@Value("#{systemEnvironment['DB_CONN_STR'] ?: '${spring.couchbase.bootstrap-hosts:localhost}'}")
21+
@Value("#{systemEnvironment['DB_CONN_STR'] ?: '${spring.couchbase.connection-string:localhost}'}")
2222
private String host;
2323

24-
@Value("#{systemEnvironment['DB_USERNAME'] ?: '${spring.couchbase.bucket.user:Administrator}'}")
24+
@Value("#{systemEnvironment['DB_USERNAME'] ?: '${spring.couchbase.username:Administrator}'}")
2525
private String username;
2626

27-
@Value("#{systemEnvironment['DB_PASSWORD'] ?: '${spring.couchbase.bucket.password:password}'}")
27+
@Value("#{systemEnvironment['DB_PASSWORD'] ?: '${spring.couchbase.password:password}'}")
2828
private String password;
2929

30-
@Value("${spring.couchbase.bucket.name:travel-sample}")
31-
private String bucketName;
30+
// Since bucket auto-configuration is removed, we'll hardcode the travel-sample bucket name
31+
private String bucketName = "travel-sample";
3232

3333
@Override
3434
public String getConnectionString() {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.couchbase.quickstart.springdata.config;
2+
3+
import io.github.cdimascio.dotenv.Dotenv;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.context.ApplicationContextInitializer;
7+
import org.springframework.context.ConfigurableApplicationContext;
8+
import org.springframework.core.env.ConfigurableEnvironment;
9+
import org.springframework.core.env.MapPropertySource;
10+
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
public class DotEnvConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> {
15+
16+
private static final Logger log = LoggerFactory.getLogger(DotEnvConfiguration.class);
17+
18+
@Override
19+
public void initialize(ConfigurableApplicationContext applicationContext) {
20+
ConfigurableEnvironment environment = applicationContext.getEnvironment();
21+
22+
try {
23+
// Load .env file if it exists
24+
Dotenv dotenv = Dotenv.configure()
25+
.directory(".")
26+
.ignoreIfMalformed()
27+
.ignoreIfMissing()
28+
.load();
29+
30+
// Create a property source from .env entries
31+
Map<String, Object> envMap = new HashMap<>();
32+
dotenv.entries().forEach(entry -> {
33+
String key = entry.getKey();
34+
String value = entry.getValue();
35+
36+
// Only add if not already set by system environment
37+
if (System.getenv(key) == null) {
38+
envMap.put(key, value);
39+
log.debug("Loaded from .env: {}", key);
40+
}
41+
});
42+
43+
if (!envMap.isEmpty()) {
44+
environment.getPropertySources().addFirst(new MapPropertySource("dotenv", envMap));
45+
log.info("Environment variables loaded from .env file: {}", envMap.keySet());
46+
}
47+
48+
} catch (Exception e) {
49+
log.error("Could not load .env file", e);
50+
}
51+
}
52+
}

src/main/java/org/couchbase/quickstart/springdata/controller/AirportController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.springframework.dao.DataRetrievalFailureException;
99
import org.springframework.data.domain.Page;
1010
import org.springframework.data.domain.PageRequest;
11+
import org.springframework.data.domain.Slice;
1112
import org.springframework.http.HttpStatus;
1213
import org.springframework.http.ResponseEntity;
1314
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -162,13 +163,13 @@ public ResponseEntity<Page<Airport>> listAirports(@RequestParam(defaultValue = "
162163
@ApiResponse(responseCode = "500", description = "Internal server error")
163164
})
164165
@Parameter(name = "airportCode", description = "The airport code to list direct connections", required = true, example = "SFO")
165-
public ResponseEntity<Page<String>> listDirectConnections(
166+
public ResponseEntity<Slice<String>> listDirectConnections(
166167
@RequestParam(required = true) String airportCode,
167168
@RequestParam(defaultValue = "0") int page,
168169
@RequestParam(defaultValue = "10") int size) {
169170
try {
170-
Page<Route> airports = airportService.getDirectConnections(airportCode, PageRequest.of(page, size));
171-
Page<String> directConnections = airports.map(Route::getDestinationAirport);
171+
Slice<Route> airports = airportService.getDirectConnections(airportCode, PageRequest.of(page, size));
172+
Slice<String> directConnections = airports.map(Route::getDestinationAirport);
172173
return new ResponseEntity<>(directConnections, HttpStatus.OK);
173174

174175
} catch (Exception e) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.couchbase.quickstart.springdata.models;
2+
3+
import java.util.List;
4+
5+
import org.springframework.data.domain.PageRequest;
6+
import org.springframework.data.domain.SliceImpl;
7+
8+
import com.fasterxml.jackson.annotation.JsonCreator;
9+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
import com.fasterxml.jackson.databind.JsonNode;
12+
13+
@JsonIgnoreProperties(ignoreUnknown = true)
14+
public class RestResponseSlice<T> extends SliceImpl<T> {
15+
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
16+
public RestResponseSlice(@JsonProperty("content") List<T> content,
17+
@JsonProperty("number") int number,
18+
@JsonProperty("size") int size,
19+
@JsonProperty("pageable") JsonNode pageable,
20+
@JsonProperty("last") boolean last,
21+
@JsonProperty("sort") JsonNode sort,
22+
@JsonProperty("first") boolean first,
23+
@JsonProperty("numberOfElements") int numberOfElements,
24+
@JsonProperty("hasNext") boolean hasNext) {
25+
26+
// Calculate hasNext from the available information
27+
// For Slice, hasNext is typically determined by whether we have more content
28+
super(content, PageRequest.of(number, size), hasNext);
29+
}
30+
31+
}

src/main/java/org/couchbase/quickstart/springdata/repository/AirportRepository.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.springframework.data.couchbase.repository.Scope;
1010
import org.springframework.data.domain.Page;
1111
import org.springframework.data.domain.Pageable;
12+
import org.springframework.data.domain.Slice;
1213
import org.springframework.stereotype.Repository;
1314

1415
import com.couchbase.client.java.query.QueryScanConsistency;
@@ -22,10 +23,10 @@ public interface AirportRepository extends CouchbaseRepository<Airport, String>
2223
@Query("SELECT META(airport).id as __id,airport.* FROM airport")
2324
Page<Airport> findAll(Pageable pageable);
2425

25-
@Query("SELECT DISTINCT META(route).id as __id,route.* " +
26+
@Query("SELECT META(route).id as __id,route.* " +
2627
"FROM airport as airport " +
2728
"JOIN route as route ON airport.faa = route.sourceairport " +
2829
"WHERE airport.faa = $1 AND route.stops = 0")
29-
Page<Route> getDirectConnections(String targetAirportCode, Pageable pageable);
30+
Slice<Route> getDirectConnections(String targetAirportCode, Pageable pageable);
3031

3132
}

0 commit comments

Comments
 (0)