migrate from mongodb to postgresql 19/140219/7 0.2.0
authorbenzelleroehr <ben.zelleroehr@telekom.de>
Thu, 13 Feb 2025 15:20:29 +0000 (16:20 +0100)
committerbenzelleroehr <ben.zelleroehr@telekom.de>
Thu, 13 Mar 2025 07:22:14 +0000 (08:22 +0100)
- add liquibase for schema definition
- add testcontainers
- remove embedMongo

Change-Id: Ie56c8312011ead0d50d4b67d9b31d49a42526d8a
Issue-ID: PORTALNG-133
Signed-off-by: benzelleroehr <ben.zelleroehr@telekom.de>
app/build.gradle
app/src/main/java/org/onap/portalng/preferences/entities/PreferencesDto.java
app/src/main/java/org/onap/portalng/preferences/repository/PreferencesRepository.java
app/src/main/java/org/onap/portalng/preferences/services/PreferencesService.java
app/src/main/resources/application-local.yml
app/src/main/resources/application.yml
app/src/main/resources/db/changelog.xml [new file with mode: 0644]
app/src/main/resources/db/changelog/v001_create_schema.xml [new file with mode: 0644]
app/src/test/java/org/onap/portalng/preferences/preferences/PreferencesControllerIntegrationTest.java
app/src/test/resources/application.yml

index 6b91426..9df2f3f 100644 (file)
@@ -45,27 +45,30 @@ repositories {
 ext {
   problemVersion = '0.27.1'
   logstashLogbackVersion = '7.2'
-  embedMongoVersion = '4.7.0'
-  embedMongoIntegrationVersion = '4.7.0'
   springCloudWiremockVersion = '4.0.3'
-       micrometerVersion = '1.0.0'
+  micrometerVersion = '1.0.0'
+  liquibaseCoreVersion = '4.31.0'
 }
 
 dependencies {
        implementation project(':openapi')
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
-       implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
        implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
        implementation 'org.springframework.boot:spring-boot-starter-security'
        implementation 'org.springframework.boot:spring-boot-starter-webflux'
        implementation 'org.springframework.boot:spring-boot-starter-validation'
+    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
        implementation "org.zalando:problem:$problemVersion"
        implementation "net.logstash.logback:logstash-logback-encoder:$logstashLogbackVersion"
 
+    implementation "org.liquibase:liquibase-core:$liquibaseCoreVersion"
+    implementation 'org.postgresql:postgresql'
+
        implementation 'io.micrometer:micrometer-tracing'
        implementation 'io.micrometer:micrometer-tracing-bridge-otel'
        implementation 'io.opentelemetry:opentelemetry-exporter-zipkin'
     implementation 'io.micrometer:micrometer-registry-prometheus'
+    implementation 'org.apache.commons:commons-lang3:3.15.0'
 
        compileOnly 'org.projectlombok:lombok'
 
@@ -78,8 +81,7 @@ dependencies {
        testImplementation 'io.projectreactor:reactor-test'
        testImplementation 'io.rest-assured:rest-assured'
        testImplementation "org.springframework.cloud:spring-cloud-contract-wiremock:$springCloudWiremockVersion"
-       testImplementation "de.flapdoodle.embed:de.flapdoodle.embed.mongo:$embedMongoVersion"
-       testImplementation "de.flapdoodle.embed:de.flapdoodle.embed.mongo.spring30x:$embedMongoIntegrationVersion"
+    testImplementation "org.testcontainers:postgresql"
        testCompileOnly 'org.projectlombok:lombok'
        testAnnotationProcessor 'org.projectlombok:lombok'
 }
index a86c229..390a720 100644 (file)
@@ -23,17 +23,28 @@ package org.onap.portalng.preferences.entities;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.springframework.data.annotation.Id;
-import org.springframework.data.mongodb.core.mapping.Document;
 
-@Document
+import java.util.Map;
+
+import org.hibernate.annotations.JdbcTypeCode;
+import org.hibernate.type.SqlTypes;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+@Entity
 @Getter
 @Setter
+@Table(name = "preferences")
 public class PreferencesDto {
   @Id
   private String userId;
 
-  private Object properties;
+  @JdbcTypeCode(SqlTypes.JSON)
+  private JsonNode properties;
 
 }
 
index 264cdf5..537ee7e 100644 (file)
@@ -22,7 +22,7 @@
 package org.onap.portalng.preferences.repository;
 
 import org.onap.portalng.preferences.entities.PreferencesDto;
-import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
+import org.springframework.data.jpa.repository.JpaRepository;
 
-public interface PreferencesRepository extends ReactiveMongoRepository<PreferencesDto, String> {
+public interface PreferencesRepository extends JpaRepository<PreferencesDto, String> {
 }
index 4e7dfb3..df2ad1b 100644 (file)
@@ -29,18 +29,23 @@ import org.onap.portalng.preferences.util.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lombok.RequiredArgsConstructor;
 import reactor.core.publisher.Mono;
 
+@RequiredArgsConstructor
 @Service
 public class PreferencesService {
 
-  @Autowired
-  private PreferencesRepository repository;
+  private final PreferencesRepository repository;
+
+  private final ObjectMapper objectMapper;
 
   public Mono<Preferences> getPreferences(String userId){
-    return repository
+    return Mono.just(repository
       .findById(userId)
-      .switchIfEmpty(defaultPreferences())
+      .orElse(defaultPreferences()))
       .map(this::toPreferences);
   }
 
@@ -48,11 +53,10 @@ public class PreferencesService {
 
     var preferencesDto = new PreferencesDto();
     preferencesDto.setUserId(userId);
-    preferencesDto.setProperties(preferences.getProperties());
+    preferencesDto.setProperties(objectMapper.valueToTree(preferences.getProperties()));
 
-    return repository
-      .save(preferencesDto)
-      .map(this::toPreferences)  
+    return Mono.just(repository.save(preferencesDto))
+      .map(this::toPreferences)
       .onErrorResume(ProblemException.class, ex -> {
         Logger.errorLog(xRequestId,"user prefrences", userId, "preferences" );
         return Mono.error(ex);
@@ -63,7 +67,7 @@ public class PreferencesService {
   private Preferences toPreferences(PreferencesDto preferencesDto) {
     var preferences = new Preferences();
     preferences.setProperties(preferencesDto.getProperties());
-    return preferences; 
+    return preferences;
   }
 
   /**
@@ -72,9 +76,9 @@ public class PreferencesService {
    * b) for security reasons
    * @return PreferencesDto
    */
-  private Mono<PreferencesDto> defaultPreferences() {
+  private PreferencesDto defaultPreferences() {
     var preferencesDto = new PreferencesDto();
-    preferencesDto.setProperties("");
-    return Mono.just(preferencesDto);
+    preferencesDto.setProperties(null);
+    return preferencesDto;
   }
 }
index 5d7376c..d5a196a 100644 (file)
@@ -12,13 +12,12 @@ spring:
       resourceserver:
         jwt:
           jwk-set-uri: http://localhost:8080/realms/ONAP/protocol/openid-connect/certs #Keycloak Endpoint
-  data:
-    mongodb:
-      database: portal_preferences
-      host: localhost
-      port: 27017
-      username: root
-      password: password
+  datasource:
+    url: jdbc:postgresql://localhost:5441/preferences
+    username: postgres
+    password: postgres
+  jpa:
+    show-sql: true
 
 preferences:
     realm: ONAP
index 85156b1..e4688c0 100644 (file)
@@ -14,13 +14,24 @@ spring:
       resourceserver:
         jwt:
           jwk-set-uri: ${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/certs #Keycloak Endpoint
-  data:
-    mongodb:
-      database: ${MONGO_DATABASE}
-      host: ${MONGO_HOST}
-      port: ${MONGO_PORT}
-      username: ${MONGO_USERNAME}
-      password: ${MONGO_PASSWORD}
+  datasource:
+    url: jdbc:postgresql://${PREFERENCES_DB_HOST}:${PREFERENCES_DB_PORT}/${PREFERENCES_DB}
+    username: ${PREFERENCES_DB_USERNAME}
+    password: ${PREFERENCES_DB_PASSWORD}
+  jpa:
+    database: postgresql
+    properties:
+      hibernate:
+        session:
+          events:
+            log:
+              LOG_QUERIES_SLOWER_THAN_MS: 100
+        jdbc:
+          lob:
+            non_contextual_creation: true
+        dialect: org.hibernate.dialect.PostgreSQLDialect
+  liquibase:
+    change-log: "classpath:/db/changelog.xml"
 
 preferences:
     realm: ${KEYCLOAK_REALM}
@@ -50,4 +61,4 @@ logger:
   traceIdHeaderName: "X-Request-Id"
   enabled: true
   excludePaths:
-    - "/actuator/**"
\ No newline at end of file
+    - "/actuator/**"
diff --git a/app/src/main/resources/db/changelog.xml b/app/src/main/resources/db/changelog.xml
new file mode 100644 (file)
index 0000000..bdb8c10
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<databaseChangeLog
+    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
+    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
+        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
+        http://www.liquibase.org/xml/ns/dbchangelog-ext
+        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
+
+        <include file="changelog/v001_create_schema.xml" relativeToChangelogFile="true"/>
+</databaseChangeLog>
diff --git a/app/src/main/resources/db/changelog/v001_create_schema.xml b/app/src/main/resources/db/changelog/v001_create_schema.xml
new file mode 100644 (file)
index 0000000..3f568c4
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<databaseChangeLog
+    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
+    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
+        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
+        http://www.liquibase.org/xml/ns/dbchangelog-ext
+        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
+
+    <changeSet  id="1"  author="benzelleroehr" dbms="postgresql">
+        <createTable  tableName="preferences">
+            <column  name="user_id"  type="text">
+                <constraints primaryKey="true"/>
+            </column>
+            <column  name="properties"  type="jsonb"> </column>
+        </createTable>
+    </changeSet>
+</databaseChangeLog>
index 6eb1148..f446a9a 100644 (file)
@@ -45,11 +45,7 @@ class PreferencesControllerIntegrationTest extends BaseIntegrationTest {
     void thatUserPreferencesCanBeRetrieved() {
         // First save a user preference before a GET can run
         Preferences expectedResponse = new Preferences()
-            .properties("{\n" +
-                "    \"properties\": { \"appStarter\": \"value1\",\n" +
-                "    \"dashboard\": {\"key1:\" : \"value2\"}\n" +
-                "    } \n" +
-                "}");
+            .properties("{\"properties\": {\"dashboard\": {\"key1:\": \"value2\"}, \"appStarter\": \"value1\"}}");
         preferencesService
             .savePreferences(X_REQUEST_ID,"test-user", expectedResponse)
             .block();
@@ -69,7 +65,7 @@ class PreferencesControllerIntegrationTest extends BaseIntegrationTest {
         assertThat(actualResponse).isNotNull();
         assertThat(actualResponse.getProperties()).isEqualTo(expectedResponse.getProperties());
     }
-    
+
     @Test
     void thatUserPreferencesCanNotBeRetrieved() {
         unauthenticatedRequestSpecification()
@@ -162,7 +158,7 @@ class PreferencesControllerIntegrationTest extends BaseIntegrationTest {
             .as(Preferences.class);
 
         assertThat(actualResponse).isNotNull();
-        assertThat(actualResponse.getProperties()).isEqualTo("");
+        assertThat(actualResponse.getProperties()).isNull();
     }
 
     @Test
index 499b8e4..2eecc93 100644 (file)
@@ -18,6 +18,25 @@ spring:
       resourceserver:
         jwt:
           jwk-set-uri: http://localhost:${wiremock.server.port}/realms/ONAP/protocol/openid-connect/certs #Keycloak Endpoint
+  datasource:
+    url: jdbc:tc:postgresql:16:///preferences
+    username: postgres
+    password: postgres
+  jpa:
+    show-sql: true
+    database: postgresql
+    properties:
+      hibernate:
+        session:
+          events:
+            log:
+              LOG_QUERIES_SLOWER_THAN_MS: 100
+        jdbc:
+          lob:
+            non_contextual_creation: true
+        dialect: org.hibernate.dialect.PostgreSQLDialect
+  liquibase:
+    change-log: "classpath:/db/changelog.xml"
 
 preferences:
   realm: ONAP
@@ -41,4 +60,4 @@ logger:
   traceIdHeaderName: "X-Request-Id"
   enabled: true
   excludePaths:
-    - "/actuator/**"
\ No newline at end of file
+    - "/actuator/**"