From 2ad7ac78460df2a3bc1ee1db494b9cfecffee527 Mon Sep 17 00:00:00 2001 From: alamgir-ahosain Date: Fri, 20 Feb 2026 11:24:24 +0600 Subject: [PATCH 1/5] add dockerfile ,env and change the github workflow --- .github/workflows/automate_tests.yml | 25 ++++++++++- database/init.sql | 43 +++++++++++++++++++ docker-compose.yml | 37 ++++++++++++++++ server/.gitignore | 2 + server/pom.xml | 13 ++++++ .../alamgir/server/ServerApplication.java | 3 ++ .../alamgir/server/config/EnvConfig.java | 23 ++++++++++ .../src/main/resources/application.properties | 9 ++-- 8 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 database/init.sql create mode 100644 docker-compose.yml create mode 100644 server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java diff --git a/.github/workflows/automate_tests.yml b/.github/workflows/automate_tests.yml index 4d60191..36c92a1 100644 --- a/.github/workflows/automate_tests.yml +++ b/.github/workflows/automate_tests.yml @@ -14,6 +14,22 @@ jobs: build: runs-on: ubuntu-latest + # creates a real Postgres instance inside the GitHub runner + services: + logistics-db: + image: postgres:15 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${{ secrets.DB_PASSWORD }} + POSTGRES_DB: logistics_db + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + defaults: run: working-directory: server @@ -32,6 +48,13 @@ jobs: - name: Build and Test with Maven run: mvn -B clean verify + env: + # find on ther GitHub Service Container + DB_HOST: localhost + DB_PORT: 5432 + DB_NAME: logistics_db + DB_USER: postgres + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} - name: Upload test reports if: always() @@ -47,4 +70,4 @@ jobs: name: JUnit Tests path: server/target/surefire-reports/*.xml reporter: java-junit - fail-on-error: true + fail-on-error: true \ No newline at end of file diff --git a/database/init.sql b/database/init.sql new file mode 100644 index 0000000..f0a4ec2 --- /dev/null +++ b/database/init.sql @@ -0,0 +1,43 @@ +-- 1. Locations Table +CREATE TABLE IF NOT EXISTS locations ( + id UUID PRIMARY KEY, + name VARCHAR(255), + type VARCHAR(50), -- Enum stored as String + city VARCHAR(255) +); + +-- 2. Products Table +CREATE TABLE IF NOT EXISTS products ( + id UUID PRIMARY KEY, + name VARCHAR(255), + min_temperature DOUBLE PRECISION, + max_temperature DOUBLE PRECISION +); + +-- 3. Storage Units Table +CREATE TABLE IF NOT EXISTS storage_units ( + id UUID PRIMARY KEY, + location_id UUID REFERENCES locations(id), + min_temperature DOUBLE PRECISION, + max_temperature DOUBLE PRECISION, + capacity INTEGER +); + +-- 4. Demands Table +CREATE TABLE IF NOT EXISTS demands ( + id UUID PRIMARY KEY, + location_id UUID REFERENCES locations(id), + product_id UUID REFERENCES products(id), + date VARCHAR(50), + min_quantity INTEGER, + max_quantity INTEGER +); + +-- 5. Routes Table +CREATE TABLE IF NOT EXISTS routes ( + id UUID PRIMARY KEY, + from_location_id UUID REFERENCES locations(id), + to_location_id UUID REFERENCES locations(id), + capacity INTEGER, + min_shipment INTEGER +); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..937f4d7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +services: + server: + build: ./server + ports: + - "8000:8000" + depends_on: + db-service: + condition: service_healthy + environment: + DB_HOST: db-service + DB_PORT: 5432 + DB_NAME: logistics_db + DB_USER: postgres + DB_PASSWORD: YourPassword123 + SERVER_PORT: 8000 + + db-service: + image: postgres:15 + container_name: logistics-db-container + restart: always + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: YourPassword123 + POSTGRES_DB: logistics_db + ports: + - "5432:5432" + volumes: + - postgres-data:/var/lib/postgresql/data + - ./database/Init.sql:/docker-entrypoint-initdb.d/Init.sql + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d logistics_db"] + interval: 5s + timeout: 5s + retries: 10 + +volumes: + postgres-data: \ No newline at end of file diff --git a/server/.gitignore b/server/.gitignore index 667aaef..ff0bebf 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -31,3 +31,5 @@ build/ ### VS Code ### .vscode/ + +.env \ No newline at end of file diff --git a/server/pom.xml b/server/pom.xml index f871bcd..566f63e 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -69,6 +69,19 @@ h2 test + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.8.4 + + + + io.github.cdimascio + java-dotenv + 5.2.2 + compile + diff --git a/server/src/main/java/csembstu/alamgir/server/ServerApplication.java b/server/src/main/java/csembstu/alamgir/server/ServerApplication.java index 9aa41bf..5fb15b2 100644 --- a/server/src/main/java/csembstu/alamgir/server/ServerApplication.java +++ b/server/src/main/java/csembstu/alamgir/server/ServerApplication.java @@ -1,5 +1,6 @@ package csembstu.alamgir.server; +import csembstu.alamgir.server.config.EnvConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -7,6 +8,8 @@ public class ServerApplication { public static void main(String[] args) { + + EnvConfig.loadEnv(); SpringApplication.run(ServerApplication.class, args); } diff --git a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java new file mode 100644 index 0000000..f1e6350 --- /dev/null +++ b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java @@ -0,0 +1,23 @@ +package csembstu.alamgir.server.config; + +import io.github.cdimascio.dotenv.Dotenv; + +public class EnvConfig { + public static void loadEnv() { + + Dotenv dotenv = Dotenv.configure().load(); + + String dbhost = dotenv.get("DB_HOST"); + String dbport = dotenv.get("DB_PORT"); + String dbname = dotenv.get("DB_NAME"); + String dbuser = dotenv.get("DB_USER"); + String dbpassword = dotenv.get("DB_PASSWORD"); + + System.setProperty("DB_HOST", dbhost); + System.setProperty("DB_PORT", dbport); + System.setProperty("DB_NAME", dbname); + System.setProperty("DB_USER", dbuser); + System.setProperty("DB_PASSWORD", dbpassword); + + } +} diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties index d55da46..b823d9e 100644 --- a/server/src/main/resources/application.properties +++ b/server/src/main/resources/application.properties @@ -1,16 +1,17 @@ spring.application.name=server - +server.port=8000 # Database Setup for PostgreSQL -spring.datasource.url=jdbc:postgresql://localhost:5432/logisticsdb -spring.datasource.username=postgres -spring.datasource.password=postgresql +spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} +spring.datasource.username=${DB_USER} +spring.datasource.password=${DB_PASSWORD} spring.datasource.driver-class-name=org.postgresql.Driver # spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true + #hide the stack trace in error responses server.error.include-stacktrace=never server.error.include-message=always From a43ac0265ddd3d539bda1d399974e453b4c17095 Mon Sep 17 00:00:00 2001 From: alamgir-ahosain Date: Fri, 20 Feb 2026 12:24:10 +0600 Subject: [PATCH 2/5] solve env load and add Dockerfile --- database/{init.sql => Init.sql} | 22 +++++++++---------- docker-compose.yml | 10 ++++++--- server/Dockerfile | 18 +++++++++++++++ .../alamgir/server/config/EnvConfig.java | 4 +++- 4 files changed, 39 insertions(+), 15 deletions(-) rename database/{init.sql => Init.sql} (59%) create mode 100644 server/Dockerfile diff --git a/database/init.sql b/database/Init.sql similarity index 59% rename from database/init.sql rename to database/Init.sql index f0a4ec2..43a83da 100644 --- a/database/init.sql +++ b/database/Init.sql @@ -1,14 +1,14 @@ -- 1. Locations Table CREATE TABLE IF NOT EXISTS locations ( - id UUID PRIMARY KEY, + id VARCHAR(36) PRIMARY KEY, name VARCHAR(255), - type VARCHAR(50), -- Enum stored as String + type VARCHAR(50), city VARCHAR(255) ); -- 2. Products Table CREATE TABLE IF NOT EXISTS products ( - id UUID PRIMARY KEY, + id VARCHAR(36) PRIMARY KEY, name VARCHAR(255), min_temperature DOUBLE PRECISION, max_temperature DOUBLE PRECISION @@ -16,8 +16,8 @@ CREATE TABLE IF NOT EXISTS products ( -- 3. Storage Units Table CREATE TABLE IF NOT EXISTS storage_units ( - id UUID PRIMARY KEY, - location_id UUID REFERENCES locations(id), + id VARCHAR(36) PRIMARY KEY, + location_id VARCHAR(36) REFERENCES locations(id), min_temperature DOUBLE PRECISION, max_temperature DOUBLE PRECISION, capacity INTEGER @@ -25,9 +25,9 @@ CREATE TABLE IF NOT EXISTS storage_units ( -- 4. Demands Table CREATE TABLE IF NOT EXISTS demands ( - id UUID PRIMARY KEY, - location_id UUID REFERENCES locations(id), - product_id UUID REFERENCES products(id), + id VARCHAR(36) PRIMARY KEY, + location_id VARCHAR(36) REFERENCES locations(id), + product_id VARCHAR(36) REFERENCES products(id), date VARCHAR(50), min_quantity INTEGER, max_quantity INTEGER @@ -35,9 +35,9 @@ CREATE TABLE IF NOT EXISTS demands ( -- 5. Routes Table CREATE TABLE IF NOT EXISTS routes ( - id UUID PRIMARY KEY, - from_location_id UUID REFERENCES locations(id), - to_location_id UUID REFERENCES locations(id), + id VARCHAR(36) PRIMARY KEY, + from_location_id VARCHAR(36) REFERENCES locations(id), + to_location_id VARCHAR(36) REFERENCES locations(id), capacity INTEGER, min_shipment INTEGER ); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 937f4d7..42ab50f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,11 @@ services: server: build: ./server + container_name: logistics-platform-server ports: - "8000:8000" + env_file: + - ./server/.env depends_on: db-service: condition: service_healthy @@ -23,10 +26,10 @@ services: POSTGRES_PASSWORD: YourPassword123 POSTGRES_DB: logistics_db ports: - - "5432:5432" + - "5433:5432" volumes: - postgres-data:/var/lib/postgresql/data - - ./database/Init.sql:/docker-entrypoint-initdb.d/Init.sql + - ./database/Init.sql:/docker-entrypoint-initdb.d/Init.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d logistics_db"] interval: 5s @@ -34,4 +37,5 @@ services: retries: 10 volumes: - postgres-data: \ No newline at end of file + postgres-data: + driver: local \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..3e2b583 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,18 @@ + + +# Stage 1: Build + +FROM maven:3.9.6-eclipse-temurin-21 AS build +WORKDIR /app +COPY pom.xml . +RUN mvn dependency:go-offline -B +COPY src ./src +RUN mvn clean package -DskipTests + +# Stage 2: Runtime + +FROM eclipse-temurin:21-jre +WORKDIR /app +COPY --from=build /app/target/*.jar app.jar +EXPOSE 8000 +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java index f1e6350..f48e360 100644 --- a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java +++ b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java @@ -5,7 +5,9 @@ public class EnvConfig { public static void loadEnv() { - Dotenv dotenv = Dotenv.configure().load(); + Dotenv dotenv = Dotenv.configure() + .ignoreIfMissing() + .load(); String dbhost = dotenv.get("DB_HOST"); String dbport = dotenv.get("DB_PORT"); From 6bea8e0368704d71b0099ddd86bf471f8266d8ba Mon Sep 17 00:00:00 2001 From: alamgir-ahosain Date: Fri, 20 Feb 2026 17:15:32 +0600 Subject: [PATCH 3/5] add render datasource url --- .../main/java/csembstu/alamgir/server/ServerApplication.java | 1 - server/src/main/resources/application.properties | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/csembstu/alamgir/server/ServerApplication.java b/server/src/main/java/csembstu/alamgir/server/ServerApplication.java index 5fb15b2..1153055 100644 --- a/server/src/main/java/csembstu/alamgir/server/ServerApplication.java +++ b/server/src/main/java/csembstu/alamgir/server/ServerApplication.java @@ -6,7 +6,6 @@ @SpringBootApplication public class ServerApplication { - public static void main(String[] args) { EnvConfig.loadEnv(); diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties index b823d9e..4bad690 100644 --- a/server/src/main/resources/application.properties +++ b/server/src/main/resources/application.properties @@ -4,11 +4,12 @@ spring.application.name=server server.port=8000 # Database Setup for PostgreSQL -spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} +spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}} spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASSWORD} + spring.datasource.driver-class-name=org.postgresql.Driver -# spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true From 68a42983b29ba76a5b5a288c6a29ec78f4b7ca58 Mon Sep 17 00:00:00 2001 From: alamgir-ahosain Date: Fri, 20 Feb 2026 18:51:15 +0600 Subject: [PATCH 4/5] solve NullPointerPointerException : local env but not present in production --- .../alamgir/server/config/EnvConfig.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java index f48e360..a30bd0a 100644 --- a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java +++ b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java @@ -1,25 +1,21 @@ package csembstu.alamgir.server.config; import io.github.cdimascio.dotenv.Dotenv; +import io.github.cdimascio.dotenv.DotenvEntry; public class EnvConfig { public static void loadEnv() { - Dotenv dotenv = Dotenv.configure() .ignoreIfMissing() .load(); - String dbhost = dotenv.get("DB_HOST"); - String dbport = dotenv.get("DB_PORT"); - String dbname = dotenv.get("DB_NAME"); - String dbuser = dotenv.get("DB_USER"); - String dbpassword = dotenv.get("DB_PASSWORD"); - - System.setProperty("DB_HOST", dbhost); - System.setProperty("DB_PORT", dbport); - System.setProperty("DB_NAME", dbname); - System.setProperty("DB_USER", dbuser); - System.setProperty("DB_PASSWORD", dbpassword); + for (DotenvEntry entry : dotenv.entries()) { + String key = entry.getKey(); + String value = entry.getValue(); + if (value != null && !value.isEmpty()) { + System.setProperty(key, value); + } + } } -} +} \ No newline at end of file From 53cd47bd5c30c0c5831ab162771ce6f7a0760553 Mon Sep 17 00:00:00 2001 From: alamgir-ahosain Date: Fri, 20 Feb 2026 19:10:35 +0600 Subject: [PATCH 5/5] check loaded value via log --- .../main/java/csembstu/alamgir/server/config/EnvConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java index a30bd0a..e79cb37 100644 --- a/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java +++ b/server/src/main/java/csembstu/alamgir/server/config/EnvConfig.java @@ -2,8 +2,11 @@ import io.github.cdimascio.dotenv.Dotenv; import io.github.cdimascio.dotenv.DotenvEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EnvConfig { + private static final Logger log = LoggerFactory.getLogger(EnvConfig.class); public static void loadEnv() { Dotenv dotenv = Dotenv.configure() .ignoreIfMissing() @@ -15,6 +18,7 @@ public static void loadEnv() { if (value != null && !value.isEmpty()) { System.setProperty(key, value); + log.info("Loaded property: {}", key); } } }