Skip to content

Commit 1fc7180

Browse files
author
tonylook
committed
Project Scaffolding: Clean Architecture with Spring Boot, MariaDB, Liquibase, Gradle, Docker.
1 parent 79a28aa commit 1fc7180

File tree

18 files changed

+627
-0
lines changed

18 files changed

+627
-0
lines changed

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.gradle
2+
build/
3+
!**/src/main/**/build/
4+
!**/src/test/**/build/
5+
6+
### IntelliJ IDEA ###
7+
.idea
8+
*.iws
9+
*.iml
10+
*.ipr
11+
out/
12+
!**/src/main/**/out/
13+
!**/src/test/**/out/
14+
15+
### Eclipse ###
16+
.apt_generated
17+
.classpath
18+
.factorypath
19+
.project
20+
.settings
21+
.springBeans
22+
.sts4-cache
23+
bin/
24+
!**/src/main/**/bin/
25+
!**/src/test/**/bin/
26+
27+
### VS Code ###
28+
.vscode/
29+
30+
### Mac OS ###
31+
.DS_Store

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM eclipse-temurin:21-jdk AS build
2+
WORKDIR /home/gradle/src
3+
COPY . /home/gradle/src
4+
RUN ./gradlew :application:bootJar --no-daemon
5+
6+
FROM eclipse-temurin:21-jre
7+
COPY --from=build /home/gradle/src/application/build/libs/application.jar /application.jar
8+
EXPOSE 8090
9+
ENTRYPOINT ["java","-jar","/application.jar"]

application/build.gradle.kts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apply {
2+
plugin("org.springframework.boot")
3+
}
4+
5+
val cucumberVersion = ""
6+
val jakartaVersion = ""
7+
dependencies {
8+
implementation(project(":core"))
9+
implementation(project(":mariadb"))
10+
implementation(project(":spring-web"))
11+
12+
implementation("org.liquibase:liquibase-core")
13+
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
14+
implementation("org.springframework.boot:spring-boot-configuration-processor")
15+
implementation("jakarta.validation:jakarta.validation-api:3.0.2")
16+
implementation("org.springframework.boot:spring-boot-starter-web")
17+
implementation("org.springframework.boot:spring-boot-starter-actuator")
18+
implementation("org.springframework.boot:spring-boot-starter-logging")
19+
implementation("io.swagger.core.v3:swagger-annotations:2.2.16")
20+
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0")
21+
22+
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
23+
runtimeOnly("io.micrometer:micrometer-registry-prometheus")
24+
25+
testImplementation("io.reactivex.rxjava2:rxjava:2.1.14")
26+
testImplementation("org.junit.platform:junit-platform-suite-engine")
27+
testImplementation("io.cucumber:cucumber-java:7.15.0")
28+
testImplementation("io.cucumber:cucumber-spring:7.15.0")
29+
testImplementation("io.cucumber:cucumber-junit-platform-engine:7.15.0")
30+
testImplementation("org.springframework.boot:spring-boot-testcontainers")
31+
testImplementation("org.testcontainers:junit-jupiter")
32+
testImplementation("org.testcontainers:mariadb")
33+
testImplementation("org.springframework.boot:spring-boot-starter-webflux")
34+
testImplementation("org.springframework.boot:spring-boot-starter-test")
35+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.qa.blog.application;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
import java.time.Clock;
7+
import java.time.ZoneId;
8+
9+
@Configuration
10+
public class ApplicationConfig {
11+
12+
@Bean
13+
public Clock clock() {
14+
return Clock.system(ZoneId.of("CET"));
15+
}
16+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.qa.blog.application;
2+
3+
import com.qa.blog.mariadb.MariaConfig;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
import org.springframework.context.annotation.ComponentScan;
7+
import org.springframework.context.annotation.Import;
8+
import org.springframework.scheduling.annotation.EnableScheduling;
9+
10+
@Import({MariaConfig.class})
11+
@ComponentScan(basePackages = "com.qa.blog")
12+
@SpringBootApplication
13+
@EnableScheduling
14+
public class BlogApplication {
15+
16+
public static void main(String[] args) {
17+
SpringApplication.run(BlogApplication.class, args);
18+
}
19+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
server:
2+
port: 8090
3+
spring:
4+
datasource:
5+
url: jdbc:mariadb://mariadb:3306/blog?useSSL=false&serverTimezone=Europe/Zurich&autoReconnect=true&maxReconnects=10&allowPublicKeyRetrieval=true
6+
username: root
7+
password: root
8+
liquibase:
9+
contexts: seed-blog
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
spring:
2+
application:
3+
name: blog
4+
datasource:
5+
driverClassName: org.mariadb.jdbc.Driver
6+
jpa:
7+
hibernate:
8+
ddl-auto: validate
9+
liquibase:
10+
contexts: no-seed-blog
11+
server:
12+
port: 8090

build.gradle.kts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
plugins {
2+
jacoco
3+
id("application")
4+
java
5+
id("org.springframework.boot") version "3.2.3" apply false
6+
id("io.spring.dependency-management") version "1.1.4"
7+
id("org.sonarqube") version "5.0.0.4638"
8+
}
9+
10+
group = "com.qa.blog"
11+
version = "1.0.0"
12+
description = "Kata"
13+
14+
java {
15+
sourceCompatibility = JavaVersion.VERSION_21
16+
}
17+
18+
repositories {
19+
mavenCentral()
20+
}
21+
22+
tasks.register<JacocoReport>("codeCoverageReport") {
23+
group = "Coverage"
24+
description = "Coverage report aggregation"
25+
// If a subproject applies the 'jacoco' plugin, add the result it to the report
26+
subprojects {
27+
val subproject = this
28+
subproject.plugins.withType<JacocoPlugin>().configureEach {
29+
subproject.tasks.matching({ it.extensions.findByType<JacocoTaskExtension>() != null }).configureEach {
30+
val testTask = this
31+
sourceSets(subproject.sourceSets.main.get())
32+
executionData(testTask)
33+
}
34+
35+
// To automatically run `test` every time `./gradlew codeCoverageReport` is called,
36+
// you may want to set up a task dependency between them as shown below.
37+
// Note that this requires the `test` tasks to be resolved eagerly (see `forEach`) which
38+
// may have a negative effect on the configuration time of your build.
39+
subproject.tasks.matching({ it.extensions.findByType<JacocoTaskExtension>() != null }).forEach {
40+
rootProject.tasks["codeCoverageReport"].dependsOn(it)
41+
}
42+
}
43+
}
44+
45+
// enable the different report types (html, xml, csv)
46+
reports {
47+
// xml is usually used to integrate code coverage with
48+
// other tools like SonarQube, Coveralls or Codecov
49+
xml.required = true
50+
51+
// HTML reports can be used to see code coverage
52+
// without any external tools
53+
html.required = true
54+
}
55+
}
56+
57+
subprojects {
58+
repositories {
59+
mavenCentral()
60+
}
61+
62+
apply {
63+
plugin("jacoco")
64+
plugin("application")
65+
plugin("java")
66+
67+
plugin("io.spring.dependency-management")
68+
}
69+
70+
dependencyManagement {
71+
imports {
72+
mavenBom("org.springframework.boot:spring-boot-dependencies:3.2.3")
73+
}
74+
}
75+
76+
tasks.withType<Test> {
77+
useJUnitPlatform()
78+
}
79+
}
80+
81+
tasks.check {
82+
dependsOn(tasks.named<JacocoReport>("codeCoverageReport"))
83+
}
84+
85+
sonar {
86+
properties {
87+
property("sonar.projectKey", "blog")
88+
property("sonar.projectName", "Blog")
89+
property("sonar.exclusions", "**/BlogApplication.java,**/ApplicationConfig.java,**/build.gradle.kts")
90+
property("sonar.coverage.exclusions", "**/ApplicationConfig.java,**/BlogApplication.java,**/build.gradle.kts")
91+
property("sonar.coverage.jacoco.xmlReportPaths", "${project.projectDir}/build/reports/jacoco/codeCoverageReport/codeCoverageReport.xml")
92+
property ("sonar.gradle.skipCompile", "true")
93+
}
94+
}

core/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
dependencies {
2+
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2")
3+
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.2")
4+
testImplementation("org.mockito:mockito-junit-jupiter:5.11.0")
5+
}

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# This file was generated by the Gradle 'init' task.
2+
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format

gradle/wrapper/gradle-wrapper.jar

42.4 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)