A comprehensive Spring Boot API template built with Kotlin, following SOLID principles and best practices.
API Controllers โ Facades โ Repositories
src/main/kotlin/
โโโ controller/ # REST endpoints (@RestController)
โโโ facade/ # Business logic layer (@Service, @Transactional)
โโโ service/ # External service integrations
โโโ repository/ # Data access layer (@Repository)
โโโ model/ # Entity classes (plain data classes)
โโโ dto/ # Data Transfer Objects with OpenAPI schemas
โโโ config/ # Configuration classes (@Configuration)
โโโ exception/ # Custom exceptions and handlers
Component | Technology | Version |
---|---|---|
Language | Kotlin | 1.9.24 |
Framework | Spring Boot | 3.3.2 |
Build Tool | Maven | 3.9.x |
Database | Oracle Database | 23ai |
Connection Pool | HikariCP | Built-in |
Migration | Flyway | 10.15.2 |
Documentation | SpringDoc OpenAPI | 2.6.0 |
Security | Spring Security OAuth2 | Built-in |
Testing | Kotest + MockK | 5.9.1 |
Containers | TestContainers | 1.19.8 |
git clone https://github.com/norvaldb/base-springboot-api-kotlin.git
cd base-springboot-api-kotlin
# Pull Oracle XE image
podman pull container-registry.oracle.com/database/express:latest
# Run Oracle XE container
podman run -d \
--name oracle-xe \
-p 1521:1521 \
-e ORACLE_PWD=password123 \
-e ORACLE_CHARACTERSET=AL32UTF8 \
container-registry.oracle.com/database/express:latest
# Wait for database to be ready (2-3 minutes)
podman logs -f oracle-xe
export DB_USERNAME=dev_user
export DB_PASSWORD=dev_password
export DB_SCHEMA=DEV_SCHEMA
export JWT_ISSUER_URI=https://your-oauth2-provider.com
# Create database schema and user (connect as system)
sqlplus system/password123@localhost:1521/XEPDB1
# In SQL*Plus:
CREATE USER dev_user IDENTIFIED BY dev_password;
GRANT DBA TO dev_user;
CREATE SCHEMA AUTHORIZATION dev_user;
# Run Flyway migrations
mvn flyway:migrate
# Build the application with automatic reports
mvn clean install
# Run tests only
mvn test
# Run integration tests
mvn verify
# Generate code coverage report (manual)
mvn jacoco:report
# Generate Allure report (manual)
mvn allure:report
# Start the application
mvn spring-boot:run
Both JaCoCo coverage and Allure test reports are automatically generated during mvn install
:
# Single command generates everything
mvn clean install
Generated Reports:
target/site/jacoco/index.html
target/allure-report/index.html
For individual report generation (optional):
# Generate coverage report only
mvn jacoco:report
# Generate Allure report only
mvn allure:report
# Serve interactive Allure report
mvn allure:serve
# Serve interactive Allure report
mvn allure:serve
Coverage Reports Location:
target/site/jacoco/index.html
target/site/jacoco/jacoco.xml
(for CI/CD)target/allure-report/index.html
Performance Optimizations:
Coverage Thresholds:
jacoco-check
execution in pom.xml
to enableThe API is fully documented using OpenAPI 3.0 specification. Visit the Swagger UI at http://localhost:8080/swagger-ui.html for interactive documentation.
The API uses OAuth2 JWT Bearer tokens for authentication:
Authorization: Bearer <your-jwt-token>
GET /api/users/{id}
- Get user by IDPOST /api/users
- Create new userGET /actuator/health
- Health check# Run unit tests
mvn test
# Run integration tests (includes TestContainers)
mvn verify
This project is configured to produce Allure results for both unit and integration tests.
target/allure-results
mvn allure:report
(output in target/site/allure-maven/index.html
)mvn allure:serve
Notes:
AllureTestReporter
. See src/test/kotlin/ProjectConfig.kt
.mvn test
or mvn verify
.# Run OWASP dependency vulnerability scan
mvn org.owasp:dependency-check-maven:check
# Generate report without failing build
mvn org.owasp:dependency-check-maven:check -DfailBuildOnCVSS=11
Generated Reports:
target/dependency-check-report.html
target/dependency-check-report.json
target/dependency-check-report.xml
Configuration:
owasp-suppressions.xml
(false positive management)NVD_API_KEY
environment variable for faster updatesSetting up NVD API Key:
export NVD_API_KEY=your-key-here
NVD_API_KEY
as a repository secret in Settings โ Secrets and variables โ Actionsclass UserFacadeTest : FunSpec({
val userRepository = mockk<UserRepository>()
val userFacade = UserFacadeImpl(userRepository)
test("should find user by id") {
// Given
val userId = 1L
val user = User(id = userId, email = "test@example.com")
every { userRepository.findById(userId) } returns user
// When
val result = userFacade.findById(userId)
// Then
result shouldNotBe null
result?.id shouldBe userId
result?.email shouldBe "test@example.com"
}
})
This project includes comprehensive GitHub Actions workflows for automated testing and reporting:
ci.yml
)Triggers: Push to main/develop, Pull Requests to main
Features:
test-reports.yml
)Triggers: Push to main/develop, Pull Requests to main
Features:
JaCoCo Coverage Reports:
Allure Test Reports:
To enable automatic deployment of test reports to GitHub Pages:
gh-pages
/
(root)The CI pipeline will automatically deploy Allure reports with test history to your GitHub Pages site.
The workflows enforce coverage thresholds:
Failed coverage checks will be reported in PR comments and workflow status.
The application uses Oracle Database 23ai with the following configuration:
jdbc:oracle:thin:@localhost:1521:XEPDB1
DB_SCHEMA
environment variableDatabase migrations are located in src/main/resources/db/migration/
:
db/migration/
โโโ V1__Create_users_table.sql
โโโ V2__Add_user_indexes.sql
โโโ V3__Create_audit_tables.sql
-- V1__Create_users_table.sql
CREATE TABLE users (
user_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
email VARCHAR2(255) NOT NULL UNIQUE,
status VARCHAR2(50) DEFAULT 'ACTIVE',
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);
Variable | Description | Default |
---|---|---|
DB_USERNAME |
Database username | dev_user |
DB_PASSWORD |
Database password | dev_password |
DB_SCHEMA |
Database schema | DEV_SCHEMA |
JWT_ISSUER_URI |
OAuth2 JWT issuer | https://your-oauth2-provider.com |
CORS_ALLOWED_ORIGINS |
CORS allowed origins | http://localhost:3000 |
This project follows the comprehensive Copilot instructions located in .github/copilot-instructions.md
. Key principles:
val
over var
# Start Oracle Database
podman run -d \
--name oracle-xe \
-p 1521:1521 \
-e ORACLE_PWD=password123 \
container-registry.oracle.com/database/express:latest
FROM openjdk:21-jdk-slim
COPY target/base-springboot-api-kotlin-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
git checkout -b feature/amazing-feature
).github/copilot-instructions.md
git commit -m 'Add amazing feature'
)git push origin feature/amazing-feature
)This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
For questions and support:
Built with โค๏ธ using Kotlin and Spring Boot