From 2572c86560f020ea7139d09b55650b2f28538c4b Mon Sep 17 00:00:00 2001 From: liosha84 <138026690+liosha84@users.noreply.github.com> Date: Sun, 15 Jun 2025 19:22:14 +0300 Subject: [PATCH] Add initial database migration script to create tables and seed data. Add Dockerfile and docker-compose.yml for containerizing the Spring Boot application with PostgreSQL --- build.gradle | 5 ++ src/Docker/Dockerfile | 15 +++++ src/Docker/db_password.txt | 1 + src/Docker/docker-compose.yml | 42 +++++++++++++ .../configuretions/FlyWayConfiguration.java | 27 ++++++++ .../{ => configuretions}/MvcConfig.java | 2 +- .../{ => configuretions}/NotFoundHandler.java | 2 +- .../jambotron/model/Tutorial.java | 2 +- .../jambotronGroup/jambotron/model/User.java | 2 +- src/main/resources/application.properties | 19 +++++- .../db/migration/V1__create_table.sql | 62 +++++++++++++++++++ 11 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 src/Docker/Dockerfile create mode 100644 src/Docker/db_password.txt create mode 100644 src/Docker/docker-compose.yml create mode 100644 src/main/java/com/jambotronGroup/jambotron/configuretions/FlyWayConfiguration.java rename src/main/java/com/jambotronGroup/jambotron/{ => configuretions}/MvcConfig.java (92%) rename src/main/java/com/jambotronGroup/jambotron/{ => configuretions}/NotFoundHandler.java (96%) create mode 100644 src/main/resources/db/migration/V1__create_table.sql diff --git a/build.gradle b/build.gradle index 9e02775..111bd56 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.projectlombok:lombok:1.18.26' + implementation 'org.projectlombok:lombok:1.18.26' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0' @@ -30,6 +32,9 @@ dependencies { runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' // For JSON serialization/deserialization implementation 'org.postgresql:postgresql:42.6.0' + implementation 'org.flywaydb:flyway-core' + implementation("org.flywaydb:flyway-database-postgresql:10.4.1") + } // copyResouces( type:Copy diff --git a/src/Docker/Dockerfile b/src/Docker/Dockerfile new file mode 100644 index 0000000..766fe68 --- /dev/null +++ b/src/Docker/Dockerfile @@ -0,0 +1,15 @@ +#FROM openjdk:24 AS BUILD_IMAGE +#ENV APP_HOME=/jambotron +#RUN mkdir -p $APP_HOME/src/main/java +#WORKDIR $APP_HOME +#COPY ./build.gradle ./gradlew ./gradlew.bat $APP_HOME/ +#COPY gradle $APP_HOME/gradle +#COPY ./src/ $APP_HOME/src/ +#RUN ./gradlew clean build + +FROM openjdk:24 +WORKDIR /jambotron/ +COPY './build/libs/jambotron-0.0.1-SNAPSHOT.jar' '/app/jambotron.jar' +#COPY --from=BUILD_IMAGE '/jambotron/build/libs/jambotron-0.0.1-SNAPSHOT.jar' '/app/jambotron.jar' +EXPOSE 8080 +CMD ["java","-jar","/app/jambotron.jar"] \ No newline at end of file diff --git a/src/Docker/db_password.txt b/src/Docker/db_password.txt new file mode 100644 index 0000000..8c30b51 --- /dev/null +++ b/src/Docker/db_password.txt @@ -0,0 +1 @@ +postgrespw \ No newline at end of file diff --git a/src/Docker/docker-compose.yml b/src/Docker/docker-compose.yml new file mode 100644 index 0000000..76b9380 --- /dev/null +++ b/src/Docker/docker-compose.yml @@ -0,0 +1,42 @@ +services: + app: + image: 'jambotron' + container_name: 'jambotron-container' + build: + context: ../../ + dockerfile: ./src/Docker/Dockerfile + ports: + - "8080:8080" + depends_on: + - postgres_jambotron + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres_jambotron:5432/jambotronDB + SPRING_DATASOURCE_USERNAME: admin + SPRING_DATASOURCE_PASSWORD: postgrespw + SPRING_FLYWAY_LOCATIONS: classpath:db.migration + FLYWAY_USER: admin + FLYWAY_PASSWORD: postgrespw + FLYWAY_SCHEMAS: jambotronDB + FLYWAY_URL: jdbc:postgresql://postgres_jambotron:5432/jambotronDB + +# SPRING_DATASOURCE_PASSWORD: /run/secrets/db_password +# secrets: +# - db_password + + + postgres_jambotron: + image: 'postgres:13-alpine' + container_name: 'jambotron-postgres-container' + ports: + - "5432:5432" + environment: + POSTGRES_USER: admin + POSTGRES_PASSWORD: postgrespw +# POSTGRES_PASSWORD: /run/secrets/db_password + POSTGRES_DB: jambotronDB +# secrets: +# - db_password +# +#secrets: +# db_password: +# file: db_password.txt \ No newline at end of file diff --git a/src/main/java/com/jambotronGroup/jambotron/configuretions/FlyWayConfiguration.java b/src/main/java/com/jambotronGroup/jambotron/configuretions/FlyWayConfiguration.java new file mode 100644 index 0000000..ee0d060 --- /dev/null +++ b/src/main/java/com/jambotronGroup/jambotron/configuretions/FlyWayConfiguration.java @@ -0,0 +1,27 @@ +package com.jambotronGroup.jambotron.configuretions; + +import lombok.RequiredArgsConstructor; +import org.flywaydb.core.Flyway; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +@RequiredArgsConstructor +public class FlyWayConfiguration { + + @Autowired + private Environment environment; + + @Bean(initMethod = "migrate") + public Flyway flyway() { + return new Flyway(Flyway.configure() + .baselineOnMigrate(true) + .dataSource( + environment.getRequiredProperty("flyway.url"), + environment.getRequiredProperty("flyway.user"), + environment.getRequiredProperty("flyway.password")) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/jambotronGroup/jambotron/MvcConfig.java b/src/main/java/com/jambotronGroup/jambotron/configuretions/MvcConfig.java similarity index 92% rename from src/main/java/com/jambotronGroup/jambotron/MvcConfig.java rename to src/main/java/com/jambotronGroup/jambotron/configuretions/MvcConfig.java index 4fdecc9..facdcb8 100644 --- a/src/main/java/com/jambotronGroup/jambotron/MvcConfig.java +++ b/src/main/java/com/jambotronGroup/jambotron/configuretions/MvcConfig.java @@ -1,4 +1,4 @@ -package com.jambotronGroup.jambotron; +package com.jambotronGroup.jambotron.configuretions; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/jambotronGroup/jambotron/NotFoundHandler.java b/src/main/java/com/jambotronGroup/jambotron/configuretions/NotFoundHandler.java similarity index 96% rename from src/main/java/com/jambotronGroup/jambotron/NotFoundHandler.java rename to src/main/java/com/jambotronGroup/jambotron/configuretions/NotFoundHandler.java index 170f62c..2965bbd 100644 --- a/src/main/java/com/jambotronGroup/jambotron/NotFoundHandler.java +++ b/src/main/java/com/jambotronGroup/jambotron/configuretions/NotFoundHandler.java @@ -1,4 +1,4 @@ -package com.jambotronGroup.jambotron; +package com.jambotronGroup.jambotron.configuretions; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java b/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java index 50dadc4..0c92d84 100644 --- a/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java +++ b/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java @@ -9,7 +9,7 @@ import jakarta.persistence.*; public class Tutorial { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "title") diff --git a/src/main/java/com/jambotronGroup/jambotron/model/User.java b/src/main/java/com/jambotronGroup/jambotron/model/User.java index 42e639a..cc0843a 100644 --- a/src/main/java/com/jambotronGroup/jambotron/model/User.java +++ b/src/main/java/com/jambotronGroup/jambotron/model/User.java @@ -18,7 +18,7 @@ import java.util.Set; }) public class User { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "username") diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f09f37d..5407917 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,9 +1,14 @@ spring.application.name=jambotron -spring.datasource.url= jdbc:postgresql://localhost:5432/springangulardb +spring.datasource.url= jdbc:postgresql://localhost:5432/jambotronDB spring.datasource.username= admin spring.datasource.password= postgrespw +#spring.datasource.url=${SPRING_DATASOURCE_URL} +#spring.datasource.username=${SPRING_DATASOURCE_USERNAME} +#spring.datasource.password=${SPRING_DATASOURCE_PASSWORD} + + spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect @@ -19,8 +24,18 @@ app.origin=http://localhost:4200 spring.mvc.throw-exception-if-no-handler-found=true # Disable the default mappings -spring.resources.add-mappings=false +#spring.resources.add-mappings=false spring.resources.static-locations=classpath:/public spring.resources.cache.period=31557600s # 1 year if you want spa.default-file=classpath:/public/browser/index.html + + +spring.docker.compose.file=../Docker/docker-compose.yml + +spring.flyway.locations=classpath:db.migration + +flyway.user=admin +flyway.password=postgrespw +flyway.schemas=jambotronDB +flyway.url=jdbc:postgresql://localhost:5432/jambotronDB \ No newline at end of file diff --git a/src/main/resources/db/migration/V1__create_table.sql b/src/main/resources/db/migration/V1__create_table.sql new file mode 100644 index 0000000..bc61de3 --- /dev/null +++ b/src/main/resources/db/migration/V1__create_table.sql @@ -0,0 +1,62 @@ + + +CREATE TABLE IF NOT EXISTS public.roles +( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name character varying(20) COLLATE pg_catalog."default" + +); + +CREATE TABLE IF NOT EXISTS public.users +( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email character varying(50) COLLATE pg_catalog."default", + password character varying(120) COLLATE pg_catalog."default", + username character varying(20) COLLATE pg_catalog."default", + + CONSTRAINT uk6dotkott2kjsp8vw4d0m25fb7 UNIQUE (email), + CONSTRAINT ukr43af9ap4edm43mmtq01oddj6 UNIQUE (username) +); + + +CREATE TABLE IF NOT EXISTS public.user_roles +( + user_id bigint NOT NULL, + role_id integer NOT NULL, + CONSTRAINT user_roles_pkey PRIMARY KEY (user_id, role_id), + CONSTRAINT fkh8ciramu9cc9q3qcqiv4ue8a6 FOREIGN KEY (role_id) + REFERENCES public.roles (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION, + CONSTRAINT fkhfh9dx7w3ubf1co1vdev94g3f FOREIGN KEY (user_id) + REFERENCES public.users (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION +); + +CREATE TABLE IF NOT EXISTS public.tutorials +( + id bigint NOT NULL, + description character varying(255) COLLATE pg_catalog."default", + published boolean, + title character varying(255) COLLATE pg_catalog."default", + CONSTRAINT tutorials_pkey PRIMARY KEY (id) +); + + +INSERT INTO roles (id, name) VALUES (1, 'ROLE_USER'); +INSERT INTO roles (id, name) VALUES (2, 'ROLE_MODERATOR'); +INSERT INTO roles (id, name) VALUES (3, 'ROLE_ADMIN'); + +INSERT INTO users (id, email, password, username) +VALUES (1, 'liosha84@gmail.com', '$2a$10$qyoKXYSukha6XCjorTzoweF4Os1pwmwyzbaSsb3RCVB0LK6WLQKPC', 'Admin'); +INSERT INTO users (id, email, password, username) +VALUES (4, 'Moderator@gmail.com', '$2a$10$zLo5th8Xbfq.MM7y/dCRQu3Ud7HHyAwm.7.yS08ytJtkHMKrbOJlu', 'Moderator'); +INSERT INTO users (id, email, password, username) +VALUES (5, 'user@gmail.com', '$2a$10$2EcwYffteBF3GhVaf5qPB.I7XiHepDEauU5D4fx9fpBXMTZI/QnnC', 'User'); + + +INSERT INTO user_roles (user_id, role_id) VALUES (5, 1); +INSERT INTO user_roles (user_id, role_id) VALUES (1, 3); +INSERT INTO user_roles (user_id, role_id) VALUES (4, 2); +