mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-20 14:55:50 +00:00
Add optional seeding of pet types on startup from S3 (#3)
This commit is contained in:
parent
2ae3474248
commit
161183f27e
5 changed files with 148 additions and 3 deletions
|
@ -50,6 +50,14 @@ dependencies {
|
||||||
testImplementation 'org.testcontainers:mysql'
|
testImplementation 'org.testcontainers:mysql'
|
||||||
checkstyle 'io.spring.javaformat:spring-javaformat-checkstyle:0.0.41'
|
checkstyle 'io.spring.javaformat:spring-javaformat-checkstyle:0.0.41'
|
||||||
checkstyle 'com.puppycrawl.tools:checkstyle:10.12.5'
|
checkstyle 'com.puppycrawl.tools:checkstyle:10.12.5'
|
||||||
|
|
||||||
|
implementation platform('io.awspring.cloud:spring-cloud-aws-dependencies:3.1.0')
|
||||||
|
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'
|
||||||
|
|
||||||
|
implementation platform("software.amazon.awssdk:bom:2.24.13")
|
||||||
|
implementation 'software.amazon.awssdk:kms'
|
||||||
|
implementation 'software.amazon.awssdk:sso'
|
||||||
|
implementation 'software.amazon.awssdk:ssooidc'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
|
39
pom.xml
39
pom.xml
|
@ -35,8 +35,28 @@
|
||||||
<nohttp-checkstyle.version>0.0.11</nohttp-checkstyle.version>
|
<nohttp-checkstyle.version>0.0.11</nohttp-checkstyle.version>
|
||||||
<spring-format.version>0.0.40</spring-format.version>
|
<spring-format.version>0.0.40</spring-format.version>
|
||||||
|
|
||||||
|
<aws.java.sdk.version>2.24.13</aws.java.sdk.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.awspring.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-aws-dependencies</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>software.amazon.awssdk</groupId>
|
||||||
|
<artifactId>bom</artifactId>
|
||||||
|
<version>${aws.java.sdk.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Spring and Spring Boot dependencies -->
|
<!-- Spring and Spring Boot dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -139,6 +159,25 @@
|
||||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.awspring.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-aws-starter-s3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>software.amazon.awssdk</groupId>
|
||||||
|
<artifactId>kms</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>software.amazon.awssdk</groupId>
|
||||||
|
<artifactId>sso</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>software.amazon.awssdk</groupId>
|
||||||
|
<artifactId>ssooidc</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.springframework.samples.petclinic.pettypes;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.samples.petclinic.owner.PetType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||||
|
import software.amazon.awssdk.core.SdkBytes;
|
||||||
|
import software.amazon.awssdk.services.kms.KmsClient;
|
||||||
|
import software.amazon.awssdk.services.kms.model.DecryptResponse;
|
||||||
|
import software.amazon.awssdk.services.s3.S3Client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform some initializing of the supported pet types on startup by downloading them
|
||||||
|
* from S3, if enabled
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class InitPetTypes implements InitializingBean {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(InitPetTypes.class);
|
||||||
|
|
||||||
|
private final PetTypesRepository petTypesRepository;
|
||||||
|
|
||||||
|
private final KmsClient kmsClient;
|
||||||
|
|
||||||
|
private final S3Client s3Client;
|
||||||
|
|
||||||
|
@Value("${app.init.pet-types.key:petclinic-pettypes.txt}")
|
||||||
|
private String petTypesInitObjectKey;
|
||||||
|
|
||||||
|
@Value("${app.init.pet-types.kms-encrypted:false}")
|
||||||
|
private Boolean petTypesInitObjectKmsEncrypted;
|
||||||
|
|
||||||
|
InitPetTypes(PetTypesRepository petTypesRepository, Optional<AwsCredentialsProvider> awsCredentialsProvider,
|
||||||
|
Optional<S3Client> s3Client) {
|
||||||
|
this.petTypesRepository = petTypesRepository;
|
||||||
|
this.s3Client = s3Client.orElse(null);
|
||||||
|
|
||||||
|
AwsCredentialsProvider credentialsProvider = awsCredentialsProvider.orElse(null);
|
||||||
|
this.kmsClient = credentialsProvider != null
|
||||||
|
? KmsClient.builder().credentialsProvider(credentialsProvider).build() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (s3Client == null) {
|
||||||
|
logger.info("No S3Client configured, skipping loading pettypes.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Loading Pet types from \"spring-petclinic-init\" bucket at " + petTypesInitObjectKey);
|
||||||
|
String fileContents = s3Client
|
||||||
|
.getObjectAsBytes(b -> b.bucket("spring-petclinic-init").key(petTypesInitObjectKey))
|
||||||
|
.asUtf8String();
|
||||||
|
|
||||||
|
// if kms encrypted, attempt to decrypt it
|
||||||
|
if (petTypesInitObjectKmsEncrypted) {
|
||||||
|
logger.info("Decrypting pet types using KMS key...");
|
||||||
|
SdkBytes encryptedData = SdkBytes.fromUtf8String(fileContents);
|
||||||
|
DecryptResponse decryptResponse = kmsClient
|
||||||
|
.decrypt(b -> b.ciphertextBlob(encryptedData).keyId("spring-petclinic-init"));
|
||||||
|
fileContents = decryptResponse.plaintext().asUtf8String();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PetType> foundTypes = fileContents.lines().map(s -> {
|
||||||
|
PetType type = new PetType();
|
||||||
|
type.setName(s);
|
||||||
|
return type;
|
||||||
|
}).toList();
|
||||||
|
logger.info("Found " + foundTypes.size() + " pet types");
|
||||||
|
|
||||||
|
// load the found types into the database
|
||||||
|
if (!foundTypes.isEmpty()) {
|
||||||
|
petTypesRepository.saveAllAndFlush(foundTypes);
|
||||||
|
|
||||||
|
// clean up the file if we've successfully loaded from it
|
||||||
|
logger.info("Deleting Pet types file from S3");
|
||||||
|
s3Client.deleteObject(builder -> builder.bucket("spring-petclinic-init").key(petTypesInitObjectKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.springframework.samples.petclinic.pettypes;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.samples.petclinic.owner.PetType;
|
||||||
|
|
||||||
|
public interface PetTypesRepository extends JpaRepository<PetType, Integer> {
|
||||||
|
|
||||||
|
}
|
|
@ -23,3 +23,6 @@ logging.level.org.springframework=INFO
|
||||||
|
|
||||||
# Maximum time static resources should be cached
|
# Maximum time static resources should be cached
|
||||||
spring.web.resources.cache.cachecontrol.max-age=12h
|
spring.web.resources.cache.cachecontrol.max-age=12h
|
||||||
|
|
||||||
|
spring.cloud.aws.credentials.profile.name=${SPRING_AWS_PROFILE:dev}
|
||||||
|
spring.cloud.aws.s3.enabled=false
|
||||||
|
|
Loading…
Reference in a new issue