diff --git a/.gitignore b/.gitignore index 549e00a..bf01670 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +1,9 @@ -HELP.md target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### +.idea/ .vscode/ +*.iml +*.log +.env +.env.* +!.env.example +data/ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 642d572..d853aaf 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/pom.xml b/pom.xml index 1f6c46d..751cff3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,67 +1,74 @@ - 4.0.0 + org.springframework.boot spring-boot-starter-parent - 2.3.4.RELEASE - + 3.5.16 + + com.hoelee - demo - 0.0.1-SNAPSHOT - war - demo - Demo project for Spring Boot + springboot-jsonplaceholder-demo + 1.0.0 + springboot-jsonplaceholder-demo + A production-minded Spring Boot REST API showcase. - 1.8 + 21 - - org.springframework.boot - spring-boot-starter-thymeleaf - org.springframework.boot spring-boot-starter-web - org.springframework.boot - spring-boot-starter-tomcat - provided + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-cache + + + com.github.ben-manes.caffeine + caffeine + + + org.springframework.boot + spring-boot-starter-actuator + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true org.springframework.boot spring-boot-starter-test test - - - org.junit.vintage - junit-vintage-engine - - - - - - - org.json - json - jar - 20200518 - com.squareup.okhttp3 - okhttp - jar - - - org.thymeleaf - thymeleaf - jar + org.springframework.security + spring-security-test + test @@ -73,5 +80,4 @@ - diff --git a/src/main/java/com/hoelee/jsonplaceholder/ShowcaseApplication.java b/src/main/java/com/hoelee/jsonplaceholder/ShowcaseApplication.java new file mode 100644 index 0000000..4cb75e9 --- /dev/null +++ b/src/main/java/com/hoelee/jsonplaceholder/ShowcaseApplication.java @@ -0,0 +1,23 @@ +package com.hoelee.jsonplaceholder; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +/** + * @version v1, 2024-10-21 08:05:00PM + * @author hoelee + * Learning note: configuration scanning and JPA auditing keep cross-cutting setup explicit and compact. + */ +@SpringBootApplication +@ConfigurationPropertiesScan +@EnableJpaAuditing +public class ShowcaseApplication { + + public static void main(String[] args) { + SpringApplication.run(ShowcaseApplication.class, args); + } +} + +//~ v1, 2024-10-21 08:05:00PM - Last edited by hoelee diff --git a/src/main/java/com/hoelee/jsonplaceholder/config/ApiProperties.java b/src/main/java/com/hoelee/jsonplaceholder/config/ApiProperties.java new file mode 100644 index 0000000..b7519ed --- /dev/null +++ b/src/main/java/com/hoelee/jsonplaceholder/config/ApiProperties.java @@ -0,0 +1,23 @@ +package com.hoelee.jsonplaceholder.config; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import java.time.Duration; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +/** + * @version v1, 2024-10-21 09:05:00PM + * @author hoelee + * Learning note: typed, validated properties make operational settings discoverable and fail fast. + */ +@Validated +@ConfigurationProperties(prefix = "app.api") +public record ApiProperties( + @NotBlank String jsonPlaceholderBaseUrl, + Duration requestTimeout, + @Min(1) @Max(100) int importLimit) { +} + +//~ v1, 2024-10-21 09:05:00PM - Last edited by hoelee diff --git a/src/main/java/com/hoelee/jsonplaceholder/config/SecurityProperties.java b/src/main/java/com/hoelee/jsonplaceholder/config/SecurityProperties.java new file mode 100644 index 0000000..16a2503 --- /dev/null +++ b/src/main/java/com/hoelee/jsonplaceholder/config/SecurityProperties.java @@ -0,0 +1,19 @@ +package com.hoelee.jsonplaceholder.config; + +import jakarta.validation.constraints.NotBlank; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +/** + * @version v1, 2024-10-21 10:05:00PM + * @author hoelee + * Learning note: credentials are externalized so a repository never needs a real environment secret. + */ +@Validated +@ConfigurationProperties(prefix = "app.security") +public record SecurityProperties( + @NotBlank String editorUsername, + @NotBlank String editorPassword) { +} + +//~ v1, 2024-10-21 10:05:00PM - Last edited by hoelee diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..6bcd053 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,35 @@ +spring: + application: + name: jsonplaceholder-showcase + datasource: + url: jdbc:h2:mem:postshowcase;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + password: + jpa: + open-in-view: false + hibernate: + ddl-auto: update + cache: + caffeine: + spec: maximumSize=500,expireAfterWrite=10m + mvc: + problemdetails: + enabled: true + +management: + endpoints: + web: + exposure: + include: health,info + endpoint: + health: + show-details: never + +app: + api: + json-placeholder-base-url: https://jsonplaceholder.typicode.com + request-timeout: 2s + import-limit: 20 + security: + editor-username: ${APP_EDITOR_USERNAME:demo-editor} + editor-password: ${APP_EDITOR_PASSWORD:changeit} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..948d7f9 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,11 @@ +spring: + datasource: + url: jdbc:h2:mem:postshowcase-test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + jpa: + hibernate: + ddl-auto: create-drop + +app: + security: + editor-username: test-editor + editor-password: test-password