Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POSTGRES_USER=your_postgres_user
POSTGRES_PASSWORD=your_postgres_password
POSTGRES_DB=your_postgres_db
POSTGRES_PORT=5433
2 changes: 1 addition & 1 deletion .github/workflows/sonar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ jobs:
mkdir -p src/test/resources
echo ${{ secrets.APPLICATION_TEST_PROPERTIES }} | base64 -d > src/test/resources/application-test.properties
echo "spring.sql.init.mode=never" >> src/test/resources/application-test.properties
mvn clean verify sonar:sonar -Dsonar.qualitygate.wait=true
mvn clean verify sonar:sonar -DskipDocker=true -Dsonar.qualitygate.wait=true
Comment thread
MayuriXx marked this conversation as resolved.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ build/
### VS Code ###
.vscode/

### Environment variables ###
.env
# Test configuration generated in CI
src/test/resources/application-test.properties
185 changes: 99 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
# spring_boot_java_random_user

Spring Boot Java project that exposes a REST API consuming the public [Random User](https://randomuser.me/) API.
The interactive API documentation is available via **Swagger UI / OpenAPI**.
Spring Boot REST API that consumes the public [Random User](https://randomuser.me/) API and persists data in a PostgreSQL database.
Interactive API documentation is available via **Swagger UI / OpenAPI**.

---

## 🛠️ Tech Stack

| Technology | Version |
|----------------------|-----------------|
| Java | 25 |
| Spring Boot | 4.0.3 |
| Spring Web MVC | (managed by Boot) |
| Spring Actuator | (managed by Boot) |
| springdoc-openapi | 3.0.1 |
| PostgreSQL (driver) | (managed by Boot) |
| Testcontainers | (managed by Boot) |
| Maven | Wrapper included |
| Technology | Version |
|---|---|
| Java | 25 |
| Spring Boot | 4.0.3 |
| Spring Web MVC | (managed by Boot) |
| Spring Data JDBC | (managed by Boot) |
| Spring Actuator | (managed by Boot) |
| springdoc-openapi | 3.0.1 |
| PostgreSQL | 15 |
| dotenv-java | 5.2.2 |
| Docker / Docker Compose | - |
| Maven | Wrapper included |

---

## 📋 Prerequisites

- **Java 25** (or compatible version)
- **Java 25+**
- **Maven** (or use the included `./mvnw` wrapper)
- **PostgreSQL** running (if data persistence is enabled)
- **Docker Desktop**

---

## ⚙️ Configuration

The main configuration file is located at:
### 1. Environment variables

```
src/main/resources/application.properties
Copy the template and fill in the values:

```bash
cp .env.template .env
```

### Properties to configure
`.env` content:

```env
POSTGRES_USER={POSTGRES_USER}
POSTGRES_PASSWORD={POSTGRES_PASSWORD}
POSTGRES_DB={POSTGRES_DB}
POSTGRES_PORT={POSTGRES_PORT}
```

```properties
spring.application.name=spring_boot_java_random_user
> ⚠️ The `.env` file is git-ignored. Never commit it.

# Swagger UI — available at /api
springdoc.swagger-ui.path=/api
### 2. Test properties

# PostgreSQL datasource (add these if you use persistence)
spring.datasource.url=jdbc:postgresql://localhost:5432/<database_name>
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driver-class-name=org.postgresql.Driver
```bash
cp src/test/resources/application-test.properties.template src/test/resources/application-test.properties
```

> ⚠️ **Common startup error**:
> ```
> Failed to configure a DataSource: 'url' attribute is not specified
> and no embedded datasource could be configured.
> Reason: Failed to determine a suitable driver class
> ```
> This error occurs because the PostgreSQL driver is present in the dependencies but the datasource URL is not configured.
> **Fix**: either add the `spring.datasource.*` properties above, or exclude the DataSource auto-configuration if no database is needed:
> ```properties
> spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
> ```
> ⚠️ This file is also git-ignored.

---

## 🚀 Running the project

### Start the database

```bash
docker-compose up -d
```

### With the Maven Wrapper (recommended)

```bash
Expand All @@ -86,17 +88,17 @@ mvn spring-boot:run
java -jar target/spring_boot_java_random_user-0.0.1-SNAPSHOT.jar
```

The application will be available at: http://localhost:8080

---

## 📖 API Documentation (Swagger UI)

Once the project is running, the interactive documentation is available at:

```
http://localhost:8080/api
```

The raw OpenAPI specification (JSON) is available at:
Raw OpenAPI specification (JSON):

```
http://localhost:8080/v3/api-docs
Expand All @@ -106,8 +108,6 @@ http://localhost:8080/v3/api-docs

## 🔍 Monitoring (Actuator)

Spring Boot Actuator is enabled. Health endpoints are available at:

```
http://localhost:8080/actuator
http://localhost:8080/actuator/health
Expand All @@ -117,25 +117,24 @@ http://localhost:8080/actuator/health

## 🧪 Tests

Run unit and integration tests:
The Maven plugin starts and stops Docker Compose automatically during tests:

```bash
./mvnw test
./mvnw verify
```

Tests use **Testcontainers** to spin up ephemeral Docker containers for external dependencies (e.g. PostgreSQL).
Execution cycle:
1. `pre-integration-test` → `docker-compose up` (PostgreSQL starts)
2. `integration-test` → tests run
3. `post-integration-test` → `docker-compose down` (PostgreSQL stops)

> **Prerequisite for tests**: Docker must be installed and running.
> **Prerequisite**: Docker must be installed and running.

---

## 🔎 Code Quality (SonarQube)

A GitHub Actions workflow is configured in:

```bash
.github/workflows/sonar.yaml
```
A GitHub Actions workflow is configured in `.github/workflows/sonar.yaml`.

### Workflow triggers

Expand All @@ -147,45 +146,32 @@ A GitHub Actions workflow is configured in:
- Java 25 setup (Temurin)
- Maven build + tests + SonarQube analysis:

```bash
mvn clean verify sonar:sonar
```

The CI command waits for the Quality Gate result:

```bash
./mvnw clean verify sonar:sonar -Dsonar.qualitygate.wait=true
```

Before running tests, the workflow recreates:

```bash
src/test/resources/application-test.properties
```

from a Base64-encoded GitHub secret.

### Required GitHub Secrets

- `SONAR_TOKEN`
- `SONAR_HOST_URL`
- `APPLICATION_TEST_PROPERTIES` (Base64-encoded `application-test.properties` content)
Comment thread
MayuriXx marked this conversation as resolved.
| Secret | Description |
| `APPLICATION_TEST_PROPERTIES` (Base64-encoded `application-test.properties` content)
| `SONAR_TOKEN` | SonarQube authentication token |
| `SONAR_HOST_URL` | SonarQube instance URL |
| `POSTGRES_USER` | PostgreSQL user |
| `POSTGRES_PASSWORD` | PostgreSQL password |
| `POSTGRES_DB` | Database name |
| `POSTGRES_PORT` | PostgreSQL port |

> `GITHUB_TOKEN` is provided automatically by GitHub Actions.

### Generate the JaCoCo coverage report locally

Run:
### JaCoCo coverage report (local)

```bash
./mvnw clean verify
```

Generated reports:

- HTML report: `target/site/jacoco/index.html`
- XML report (used by SonarQube): `target/site/jacoco/jacoco.xml`

- HTML: `target/site/jacoco/index.html`
- XML (used by SonarQube): `target/site/jacoco/jacoco.xml`

---

Expand All @@ -195,16 +181,43 @@ Generated reports:
src/
├── main/
│ ├── java/com/xpeho/spring_boot_java_random_user/
│ │ └── SpringBootJavaRandomUserApplication.java # Entry point
│ │ └── SpringBootJavaRandomUserApplication.java Entry point, loads .env
│ └── resources/
│ └── application.properties # Configuration
│ ├── application.properties ← Spring configuration
│ └── schema.sql ← Database schema
└── test/
└── java/com/xpeho/spring_boot_java_random_user/
└── SpringBootJavaRandomUserApplicationTests.java
├── java/com/xpeho/spring_boot_java_random_user/
│ └── SpringBootJavaRandomUserApplicationTests.java
└── resources/
├── application-test.properties ← Test config (git-ignored)
└── application-test.properties.template ← Template to copy
.env ← Environment variables (git-ignored)
.env.template ← Template to copy
docker-compose.yml ← Local PostgreSQL
```

---

## 🗄️ Database

### Schema

The `user` table is created automatically on startup via `schema.sql`:

| Column | Type | Description |
|---|---|---|
| `id` | SERIAL PK | Auto-incremented identifier |
| `gender` | VARCHAR(20) | Gender |
| `firstname` | VARCHAR(100) | First name (`name.first`) |
| `lastname` | VARCHAR(100) | Last name (`name.last`) |
| `civility` | VARCHAR(20) | Title (`name.title`) |
| `email` | VARCHAR(255) | Email address |
| `phone` | VARCHAR(50) | Phone number |
| `picture` | VARCHAR(500) | Medium picture URL |
| `nationality` | VARCHAR(10) | Nationality |

---

## 🌐 External API

This project consumes the public **Random User Generator** API:
Expand All @@ -217,12 +230,12 @@ This project consumes the public **Random User Generator** API:
## ✅ Todo

- [x] [Add Sonarqube in the project](https://github.com/XPEHO/spring_boot_java_random_user/issues/2)
- [ ] [Add PostgreSQL database with docker](https://github.com/XPEHO/spring_boot_java_random_user/issues/6)
- [ ] [Add this endpoint get /user/random](https://github.com/XPEHO/spring_boot_java_random_user/issues/5)
- [ ] [Add this endpoint get /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/8)
- [ ] [Add this endpoint put /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/9)
- [ ] [Add this endpoint delete /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/10)
- [ ] [Add this endpoint post /user](https://github.com/XPEHO/spring_boot_java_random_user/issues/11)
- [x] [Add PostgreSQL database with docker](https://github.com/XPEHO/spring_boot_java_random_user/issues/6)
- [ ] [Add this endpoint GET /user/random](https://github.com/XPEHO/spring_boot_java_random_user/issues/5)
- [ ] [Add this endpoint GET /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/8)
- [ ] [Add this endpoint PUT /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/9)
- [ ] [Add this endpoint DELETE /user/{id}](https://github.com/XPEHO/spring_boot_java_random_user/issues/10)
- [ ] [Add this endpoint POST /user](https://github.com/XPEHO/spring_boot_java_random_user/issues/11)

---

Expand Down
31 changes: 31 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: '3.8'

services:
postgres:
image: postgres:17.9-alpine
container_name: xpeho_postgres
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
networks:
- xpeho_network

volumes:
postgres_data:
driver: local

networks:
xpeho_network:
driver: bridge

Loading