diff --git a/build-all.sh b/build-all.sh index 2f3a745..57f35a5 100755 --- a/build-all.sh +++ b/build-all.sh @@ -86,11 +86,12 @@ if [[ "$MODULE" == "module6" ]] then # ADD NEW MODULES HERE # (add new modules above the rest so you get quicker feedback if it fails) + build_maven_module "spring-boot/zero-downtime" build_maven_module "resilience4j/springboot-resilience4j" build_maven_module "spring-boot/feature-flags" - build maven_module "aws/springcloudses" + build_maven_module "aws/springcloudses" build_gradle_module "aws/spring-cloud-caching-redis" - build maven_module "spring-boot/spring-boot-camel" + build_maven_module "spring-boot/spring-boot-camel" build_maven_module "logging/spring-boot" build_maven_module "logging/logback" build_maven_module "logging/log4j" @@ -103,7 +104,7 @@ fi if [[ "$MODULE" == "module5" ]] then - build maven_module "aws/aws-dynamodb" + build_maven_module "aws/aws-dynamodb" build_maven_module "spring-boot/spring-boot-testconfiguration" build_maven_module "aws/springcloudrds" build_maven_module "aws/springcloudsqs" diff --git a/spring-boot/zero-downtime/pom.xml b/spring-boot/zero-downtime/pom.xml index 55c678c..6c28e97 100644 --- a/spring-boot/zero-downtime/pom.xml +++ b/spring-boot/zero-downtime/pom.xml @@ -42,6 +42,13 @@ h2 + + + com.launchdarkly + launchdarkly-java-server-sdk + 5.3.0 + + diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerController.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerController.java index 8da8a2b..95ad61f 100644 --- a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerController.java +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerController.java @@ -1,31 +1,62 @@ package io.reflectoring.zerodowntime; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import java.util.Optional; + @RestController public class CustomerController { - private final CustomerRepository customerRepository; + private final CustomerRepository oldCustomerRepository; + private final NewCustomerRepository newCustomerRepository; + private final FeatureFlagService featureFlagService; - public CustomerController(CustomerRepository customerRepository) { - this.customerRepository = customerRepository; + public CustomerController(CustomerRepository oldCustomerRepository, NewCustomerRepository newCustomerRepository, FeatureFlagService featureFlagService) { + this.oldCustomerRepository = oldCustomerRepository; + this.newCustomerRepository = newCustomerRepository; + this.featureFlagService = featureFlagService; } @GetMapping("/customers/create") - String createUser() { - Customer customer = new Customer("Bob", "Builder", "21 Build Street"); - customerRepository.save(customer); + String createCustomer() { + if (featureFlagService.writeToNewCustomerSchema()) { + NewCustomer customer = new NewCustomer("Bob", "Builder", "Build Street", "21"); + newCustomerRepository.save(customer); + } else { + OldCustomer customer = new OldCustomer("Bob", "Builder", "21 Build Street"); + oldCustomerRepository.save(customer); + } return "customer created"; } + @GetMapping("/customers/{id}}") + String getCustomer(@PathVariable("id") Long id) { + if (featureFlagService.readFromNewCustomerSchema()) { + Optional customer = newCustomerRepository.findById(id); + return customer.get().toString(); + } else { + Optional customer = oldCustomerRepository.findById(id); + return customer.get().toString(); + } + } + @GetMapping("/customers/list") - String showUser() { - Iterable customers = customerRepository.findAll(); + String getCustomer() { StringBuffer buffer = new StringBuffer(); - for (Customer customer : customers) { - buffer.append("\n"); - buffer.append(customer.toString()); + if (featureFlagService.readFromNewCustomerSchema()) { + Iterable customers = newCustomerRepository.findAll(); + for (NewCustomer customer : customers) { + buffer.append("\n"); + buffer.append(customer.toString()); + } + } else { + Iterable customers = oldCustomerRepository.findAll(); + for (OldCustomer customer : customers) { + buffer.append("\n"); + buffer.append(customer.toString()); + } } return buffer.toString(); } diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerRepository.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerRepository.java index 81c9f15..8302e94 100644 --- a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerRepository.java +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/CustomerRepository.java @@ -2,5 +2,5 @@ package io.reflectoring.zerodowntime; import org.springframework.data.repository.CrudRepository; -public interface CustomerRepository extends CrudRepository { +public interface CustomerRepository extends CrudRepository { } diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/FeatureFlagService.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/FeatureFlagService.java new file mode 100644 index 0000000..35837dc --- /dev/null +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/FeatureFlagService.java @@ -0,0 +1,24 @@ +package io.reflectoring.zerodowntime; + +import com.launchdarkly.sdk.LDUser; +import com.launchdarkly.sdk.server.LDClient; +import org.springframework.stereotype.Component; + +@Component +public class FeatureFlagService { + + private final LDClient launchdarklyClient; + + public FeatureFlagService(LDClient launchdarklyClient) { + this.launchdarklyClient = launchdarklyClient; + } + + public Boolean writeToNewCustomerSchema() { + return true; + } + + public Boolean readFromNewCustomerSchema() { + return false; + } + +} \ No newline at end of file diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/LaunchDarklyConfiguration.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/LaunchDarklyConfiguration.java new file mode 100644 index 0000000..7f7b82a --- /dev/null +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/LaunchDarklyConfiguration.java @@ -0,0 +1,27 @@ +package io.reflectoring.zerodowntime; + +import com.launchdarkly.sdk.server.LDClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PreDestroy; +import java.io.IOException; + +@Configuration +public class LaunchDarklyConfiguration { + + private LDClient launchdarklyClient; + + @Bean + public LDClient launchdarklyClient(@Value("${launchdarkly.sdkKey}") String sdkKey) { + this.launchdarklyClient = new LDClient(sdkKey); + return this.launchdarklyClient; + } + + @PreDestroy + public void destroy() throws IOException { + this.launchdarklyClient.close(); + } + +} \ No newline at end of file diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomer.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomer.java new file mode 100644 index 0000000..b8a5f0c --- /dev/null +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomer.java @@ -0,0 +1,34 @@ +package io.reflectoring.zerodowntime; + + +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Table; + +@Table("CUSTOMER") +public class NewCustomer { + + @Id + private long id; + private String firstName; + private String lastName; + private String addressStreet; + private String addressStreetNumber; + + public NewCustomer(String firstName, String lastName, String addressStreet, String addressStreetNumber) { + this.firstName = firstName; + this.lastName = lastName; + this.addressStreet = addressStreet; + this.addressStreetNumber = addressStreetNumber; + } + + @Override + public String toString() { + return "NewCustomer{" + + "id=" + id + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", addressStreet='" + addressStreet + '\'' + + ", addressStreetNumber='" + addressStreetNumber + '\'' + + '}'; + } +} diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomerRepository.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomerRepository.java new file mode 100644 index 0000000..70ad017 --- /dev/null +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/NewCustomerRepository.java @@ -0,0 +1,6 @@ +package io.reflectoring.zerodowntime; + +import org.springframework.data.repository.CrudRepository; + +public interface NewCustomerRepository extends CrudRepository { +} diff --git a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/Customer.java b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/OldCustomer.java similarity index 82% rename from spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/Customer.java rename to spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/OldCustomer.java index 1a40d61..f9f5008 100644 --- a/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/Customer.java +++ b/spring-boot/zero-downtime/src/main/java/io/reflectoring/zerodowntime/OldCustomer.java @@ -5,7 +5,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.relational.core.mapping.Table; @Table("CUSTOMER") -public class Customer { +public class OldCustomer { @Id private long id; @@ -13,7 +13,7 @@ public class Customer { private String lastName; private String address; - public Customer(String firstName, String lastName, String address) { + public OldCustomer(String firstName, String lastName, String address) { this.firstName = firstName; this.lastName = lastName; this.address = address; @@ -21,7 +21,7 @@ public class Customer { @Override public String toString() { - return "Customer{" + + return "OldCustomer{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + diff --git a/spring-boot/zero-downtime/src/main/resources/application.yml b/spring-boot/zero-downtime/src/main/resources/application.yml index 1201da5..f31ca52 100644 --- a/spring-boot/zero-downtime/src/main/resources/application.yml +++ b/spring-boot/zero-downtime/src/main/resources/application.yml @@ -6,4 +6,7 @@ spring.jpa.database-platform: org.hibernate.dialect.H2Dialect spring: h2: console: - enabled: true \ No newline at end of file + enabled: true + +launchdarkly: + sdkKey: \ No newline at end of file diff --git a/spring-boot/zero-downtime/src/main/resources/db/migration/V002__add_address_columns.sql b/spring-boot/zero-downtime/src/main/resources/db/migration/V002__add_address_columns.sql new file mode 100644 index 0000000..eb5595f --- /dev/null +++ b/spring-boot/zero-downtime/src/main/resources/db/migration/V002__add_address_columns.sql @@ -0,0 +1,2 @@ +alter table customer add column address_street varchar(100) null; +alter table customer add column address_street_number varchar(100) null;