summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul-Christian Volkmer2026-05-12 09:51:22 +0200
committerGitHub2026-05-12 07:51:22 +0000
commit6c50e2b76e78b44d65de9d68b842a9f77bab85c3 (patch)
treea33d8e5dbe3162d785ed8a3b64f0c72456927b0f
parentf6351d7a431bc539b4e57da94b4c5da87bcb262e (diff)
feat: use Jackson 3 for JSON serde (#286)
-rw-r--r--build.gradle.kts2
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/AbstractTestcontainerTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorApplicationTests.kt13
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorArchTest.kt33
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt6
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/config/GPasConfigPropertiesTest.kt20
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/helpers.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt19
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt14
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/ConfigControllerTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/LoginControllerTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsControllerTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt3
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/AbstractConsentService.java2
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/ConsentDomain.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentService.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/IConsentService.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluator.java2
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/MtbFileConsentService.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/pseudonym/Generator.java3
-rw-r--r--src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java3
-rw-r--r--src/main/java/dev/dnpm/etl/processor/pseudonym/PseudonymRequestFailed.java20
-rw-r--r--src/main/java/dev/dnpm/etl/processor/pseudonym/PsnDomainType.java20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/EtlProcessorApplication.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/Exceptions.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/ServletInitializer.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt525
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppFhirConfig.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppJdbcConfiguration.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppKafkaConfiguration.kt17
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppRestConfiguration.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppSecurityConfiguration.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppWebConfig.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AuditConfiguration.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/Jackson2Config.kt85
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/JacksonConfig.kt67
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/functions.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt9
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckService.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/ReportService.kt96
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestStatus.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestType.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/SubmissionType.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt11
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/output/MtbFileSender.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSender.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSender.kt2
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt20
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/security/TokenService.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/security/UserRole.kt4
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/security/UserRoleService.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt37
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt8
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/RequestService.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/ResponseProcessor.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt13
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessor.kt98
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/types.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/ApplicationControllerAdvice.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/ConfigController.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/HomeController.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/LoginController.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsController.kt3
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsRestController.kt10
-rw-r--r--src/main/resources/static/icon.svg2
-rw-r--r--src/main/resources/static/user.svg1
-rw-r--r--src/main/resources/templates/report.html2
-rw-r--r--src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java20
-rw-r--r--src/test/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentServiceTest.java20
-rw-r--r--src/test/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluatorTest.java20
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt92
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt50
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt28
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/helpers.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt22
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt20
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt24
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt31
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt490
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt451
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt32
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt40
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt33
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt3
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt9
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt15
108 files changed, 1887 insertions, 1058 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index e428580..afa84ca 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -74,7 +74,7 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-flyway")
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")
- implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
+ implementation("tools.jackson.module:jackson-module-kotlin")
implementation("org.springframework.kafka:spring-kafka")
implementation("org.springframework.retry:spring-retry:${springRetryVersion}")
implementation("org.flywaydb:flyway-database-postgresql")
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/AbstractTestcontainerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/AbstractTestcontainerTest.kt
index 136691e..d8564c0 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/AbstractTestcontainerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/AbstractTestcontainerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorApplicationTests.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorApplicationTests.kt
index cc1ff2b..248f889 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorApplicationTests.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorApplicationTests.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,7 +20,6 @@
package dev.dnpm.etl.processor
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.monitoring.RequestRepository
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.output.DnpmV2MtbFileRequest
@@ -43,6 +43,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.post
import org.testcontainers.junit.jupiter.Testcontainers
+import tools.jackson.databind.json.JsonMapper
@Testcontainers
@ExtendWith(SpringExtension::class)
@@ -84,16 +85,16 @@ class EtlProcessorApplicationTests : AbstractTestcontainerTest() {
@MockitoBean private lateinit var mtbFileSender: MtbFileSender
private lateinit var mockMvc: MockMvc
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(
@Autowired mockMvc: MockMvc,
- @Autowired objectMapper: ObjectMapper,
+ @Autowired jsonMapper: JsonMapper,
@Autowired requestRepository: RequestRepository
) {
this.mockMvc = mockMvc
- this.objectMapper = objectMapper
+ this.jsonMapper = jsonMapper
requestRepository.deleteAll()
}
@@ -135,7 +136,7 @@ class EtlProcessorApplicationTests : AbstractTestcontainerTest() {
mockMvc
.post("/mtbfile") {
- content = objectMapper.writeValueAsString(mtbFile)
+ content = jsonMapper.writeValueAsString(mtbFile)
contentType = MediaType.APPLICATION_JSON
with(user("admin").roles("ADMIN"))
}
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorArchTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorArchTest.kt
index 1ebf458..eeca93f 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorArchTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/EtlProcessorArchTest.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor
import com.tngtech.archunit.core.domain.JavaClasses
@@ -84,4 +104,17 @@ class EtlProcessorArchTest {
rule.check(noTestClasses)
}
+
+ @Test
+ fun noClassesDependOnJackson2() {
+ val rule =
+ noClasses()
+ .that()
+ .haveSimpleNameNotStartingWith("Jackson")
+ .should()
+ .dependOnClassesThat()
+ .resideInAPackage("com.fasterxml.jackson.*")
+
+ rule.check(noTestClasses)
+ }
}
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
index b0fa70f..b4d6e06 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -49,6 +50,7 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.bean.override.mockito.MockitoBean
+import tools.jackson.databind.json.JsonMapper
@SpringBootTest
@ContextConfiguration(
@@ -62,7 +64,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean
ConsentEvaluator::class,
],
)
-@MockitoBean(types = [ObjectMapper::class])
+@MockitoBean(types = [ObjectMapper::class, JsonMapper::class])
@TestPropertySource(
properties =
[
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/GPasConfigPropertiesTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/GPasConfigPropertiesTest.kt
index 7ba171e..609e4c4 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/GPasConfigPropertiesTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/GPasConfigPropertiesTest.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import org.assertj.core.api.Assertions.assertThat
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/helpers.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/helpers.kt
index 5ee6922..5f50bed 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/helpers.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/helpers.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
index e0e8162..ba793f2 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,7 +20,6 @@
package dev.dnpm.etl.processor.input
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.config.AppSecurityConfiguration
import dev.dnpm.etl.processor.consent.ConsentEvaluation
@@ -36,8 +36,6 @@ import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
-import org.mockito.ArgumentCaptor
-import org.mockito.Mockito
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.*
import org.springframework.beans.factory.annotation.Autowired
@@ -53,6 +51,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.delete
import org.springframework.test.web.servlet.post
+import tools.jackson.databind.json.JsonMapper
import java.time.Instant
import java.util.*
@@ -119,7 +118,7 @@ class MtbFileRestControllerTest {
.post(url) {
with(user("onkostarserver").roles("MTBFILE"))
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isAccepted() } }
@@ -147,7 +146,7 @@ class MtbFileRestControllerTest {
.post(url) {
with(user("onkostarserver").roles("ADMIN"))
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isAccepted() } }
@@ -175,7 +174,7 @@ class MtbFileRestControllerTest {
.post(url) {
with(user("testuser").roles("USER"))
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isAccepted() } }
@@ -200,7 +199,7 @@ class MtbFileRestControllerTest {
mockMvc
.post(url) {
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isUnauthorized() } }
@@ -308,7 +307,7 @@ class MtbFileRestControllerTest {
.post(url) {
with(user("onkostarserver").roles("ADMIN"))
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isAccepted() } }
@@ -336,7 +335,7 @@ class MtbFileRestControllerTest {
.post(url) {
with(user("onkostarserver").roles("USER"))
contentType = MediaType.APPLICATION_JSON
- content = ObjectMapper().writeValueAsString(mtbFile)
+ content = JsonMapper().writeValueAsString(mtbFile)
}
.andExpect { status { isAccepted() } }
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
index 17b49eb..a712ee7 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
index d27aa4c..bb24ea0 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2025 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -20,19 +20,16 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.config.AppConfiguration
import dev.dnpm.etl.processor.config.AppRestConfiguration
import dev.dnpm.etl.processor.config.AppSecurityConfiguration
+import dev.dnpm.etl.processor.config.JacksonConfig
import dev.dnpm.etl.processor.config.RestTargetProperties
import dev.dnpm.etl.processor.consent.ConsentEvaluator
import dev.dnpm.etl.processor.monitoring.ReportService
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.pcvolkmer.mv64e.mtb.*
-import java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.hamcrest.CoreMatchers.not
import org.hamcrest.Matchers.containsString
@@ -53,6 +50,10 @@ import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
import org.springframework.web.client.RestTemplate
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.module.kotlin.KotlinModule
+import java.time.Instant
+import java.util.*
@SpringBootTest
@MockitoBean(types = [ReportService::class])
@@ -78,8 +79,7 @@ class RestDipMtbFileSenderTest {
private lateinit var restMtbFileSender: RestMtbFileSender
private var reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
-
+ ReportService(JsonMapper.builder().addModule(KotlinModule.Builder().build()).build())
@BeforeEach
fun setup(@Autowired restTemplate: RestTemplate) {
val restTemplate = restTemplate
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
index cccd614..78089d6 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
index 63dd5dc..bbade1c 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/ConfigControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/ConfigControllerTest.kt
index b946da8..3978b33 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/ConfigControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/ConfigControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
index fdc2066..65aa0d8 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/LoginControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/LoginControllerTest.kt
index efe36ae..d37cc24 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/LoginControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/LoginControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsControllerTest.kt
index f375f2c..20cffe8 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
index cb19cf4..c7440f8 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/AbstractConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/AbstractConsentService.java
index 5c9878c..1dcb74e 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/AbstractConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/AbstractConsentService.java
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2025 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/ConsentDomain.java b/src/main/java/dev/dnpm/etl/processor/consent/ConsentDomain.java
index e339ba4..9c0359a 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/ConsentDomain.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/ConsentDomain.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
public enum ConsentDomain {
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
index d445182..20fa3c4 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import dev.dnpm.etl.processor.config.AppFhirConfig;
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentService.java
index d657306..2439e44 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentService.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import dev.dnpm.etl.processor.config.AppFhirConfig;
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/IConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/IConsentService.java
index f9230ec..43c000c 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/IConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/IConsentService.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import java.util.Date;
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluator.java b/src/main/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluator.java
index c815f7a..28ee6be 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluator.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluator.java
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2025 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/MtbFileConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/MtbFileConsentService.java
index cc8107f..db9d690 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/MtbFileConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/MtbFileConsentService.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import java.util.Date;
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java b/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java
index b92f58d..7aacb20 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/TtpConsentStatus.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
public enum TtpConsentStatus {
diff --git a/src/main/java/dev/dnpm/etl/processor/pseudonym/Generator.java b/src/main/java/dev/dnpm/etl/processor/pseudonym/Generator.java
index e72a8f8..79e90db 100644
--- a/src/main/java/dev/dnpm/etl/processor/pseudonym/Generator.java
+++ b/src/main/java/dev/dnpm/etl/processor/pseudonym/Generator.java
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java b/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java
index 478c5c9..b4641aa 100644
--- a/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java
+++ b/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/java/dev/dnpm/etl/processor/pseudonym/PseudonymRequestFailed.java b/src/main/java/dev/dnpm/etl/processor/pseudonym/PseudonymRequestFailed.java
index 397455a..b1a215e 100644
--- a/src/main/java/dev/dnpm/etl/processor/pseudonym/PseudonymRequestFailed.java
+++ b/src/main/java/dev/dnpm/etl/processor/pseudonym/PseudonymRequestFailed.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.pseudonym;
public class PseudonymRequestFailed extends RuntimeException {
diff --git a/src/main/java/dev/dnpm/etl/processor/pseudonym/PsnDomainType.java b/src/main/java/dev/dnpm/etl/processor/pseudonym/PsnDomainType.java
index 55cb212..b1cec26 100644
--- a/src/main/java/dev/dnpm/etl/processor/pseudonym/PsnDomainType.java
+++ b/src/main/java/dev/dnpm/etl/processor/pseudonym/PsnDomainType.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.pseudonym;
public enum PsnDomainType {
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/EtlProcessorApplication.kt b/src/main/kotlin/dev/dnpm/etl/processor/EtlProcessorApplication.kt
index 75147ea..26d87da 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/EtlProcessorApplication.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/EtlProcessorApplication.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/Exceptions.kt b/src/main/kotlin/dev/dnpm/etl/processor/Exceptions.kt
index 1c590fc..92eff9a 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/Exceptions.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/Exceptions.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/ServletInitializer.kt b/src/main/kotlin/dev/dnpm/etl/processor/ServletInitializer.kt
index e35cddf..1963bd3 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/ServletInitializer.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/ServletInitializer.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
index 63f50a6..01bab32 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
index 61f3c40..1c18aab 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2025 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -45,7 +45,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.ConfigurationCondition
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration
import org.springframework.http.converter.StringHttpMessageConverter
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
+import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter
import org.springframework.retry.RetryCallback
import org.springframework.retry.RetryContext
import org.springframework.retry.RetryListener
@@ -58,6 +58,7 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
import org.springframework.web.client.HttpClientErrorException
import org.springframework.web.client.RestTemplate
import reactor.core.publisher.Sinks
+import tools.jackson.databind.json.JsonMapper
import kotlin.time.Duration.Companion.seconds
import kotlin.time.toJavaDuration
@@ -75,280 +76,276 @@ import kotlin.time.toJavaDuration
@EnableScheduling
class AppConfiguration {
- private val logger = LoggerFactory.getLogger(AppConfiguration::class.java)
-
- fun stringHttpMessageConverter(): StringHttpMessageConverter {
- return StringHttpMessageConverter()
- }
-
- @Bean
- fun mappingJacksonHttpMessageConverter(
- objectMapper: ObjectMapper
- ): MappingJackson2HttpMessageConverter {
- val converter = MappingJackson2HttpMessageConverter()
- converter.setObjectMapper(objectMapper)
- return converter
- }
-
- @Bean
- fun restTemplate(objectMapper: ObjectMapper): RestTemplate {
- return RestTemplateBuilder()
- .messageConverters(
- stringHttpMessageConverter(),
- mappingJacksonHttpMessageConverter(objectMapper),
+ private val logger = LoggerFactory.getLogger(AppConfiguration::class.java)
+
+ fun stringHttpMessageConverter(): StringHttpMessageConverter {
+ return StringHttpMessageConverter()
+ }
+
+ @Bean
+ fun jacksonJsonHttpMapperConverter(jsonMapper: JsonMapper): JacksonJsonHttpMessageConverter {
+ return JacksonJsonHttpMessageConverter(jsonMapper)
+ }
+
+ @Bean
+ fun restTemplate(jsonMapper: JsonMapper): RestTemplate {
+ return RestTemplateBuilder()
+ .messageConverters(
+ stringHttpMessageConverter(),
+ jacksonJsonHttpMapperConverter(jsonMapper),
+ )
+ .build()
+ }
+
+ @Bean
+ fun appFhirConfig(): AppFhirConfig {
+ return AppFhirConfig()
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapProxyFactoryBean(gpasConfigProperties: GPasConfigProperties): JaxWsProxyFactoryBean {
+ val proxyFactory = JaxWsProxyFactoryBean()
+ proxyFactory.serviceClass = GpasSoapService::class.java
+ proxyFactory.address = gpasConfigProperties.soapEndpoint
+ return proxyFactory
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapProxy(gpasConfigProperties: GPasConfigProperties): GpasSoapService {
+ return gpasSoapProxyFactoryBean(gpasConfigProperties).create() as GpasSoapService
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapPseudonymGenerator(
+ configProperties: GPasConfigProperties,
+ retryTemplate: RetryTemplate,
+ gpasSoapService: GpasSoapService,
+ appFhirConfig: AppFhirConfig,
+ ): Generator {
+ logger.info("Selected 'GpasSoapPseudonym Generator'")
+ return GpasSoapPseudonymGenerator(
+ configProperties,
+ retryTemplate,
+ gpasSoapService,
+ appFhirConfig,
)
- .build()
- }
-
- @Bean
- fun appFhirConfig(): AppFhirConfig {
- return AppFhirConfig()
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
- @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
- @Bean
- fun gpasSoapProxyFactoryBean(gpasConfigProperties: GPasConfigProperties): JaxWsProxyFactoryBean {
- val proxyFactory = JaxWsProxyFactoryBean()
- proxyFactory.serviceClass = GpasSoapService::class.java
- proxyFactory.address = gpasConfigProperties.soapEndpoint
- return proxyFactory
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
- @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
- @Bean
- fun gpasSoapProxy(gpasConfigProperties: GPasConfigProperties): GpasSoapService {
- return gpasSoapProxyFactoryBean(gpasConfigProperties).create() as GpasSoapService
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
- @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
- @Bean
- fun gpasSoapPseudonymGenerator(
- configProperties: GPasConfigProperties,
- retryTemplate: RetryTemplate,
- gpasSoapService: GpasSoapService,
- appFhirConfig: AppFhirConfig,
- ): Generator {
- logger.info("Selected 'GpasSoapPseudonym Generator'")
- return GpasSoapPseudonymGenerator(
- configProperties,
- retryTemplate,
- gpasSoapService,
- appFhirConfig,
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.uri"])
+ @Bean
+ fun gpasPseudonymGenerator(
+ configProperties: GPasConfigProperties,
+ retryTemplate: RetryTemplate,
+ restTemplate: RestTemplate,
+ appFhirConfig: AppFhirConfig,
+ ): Generator {
+ logger.info("Selected 'GpasPseudonym Generator'")
+ return GpasPseudonymGenerator(configProperties, retryTemplate, restTemplate, appFhirConfig)
+ }
+
+ @ConditionalOnProperty(
+ value = ["app.pseudonymize.generator"],
+ havingValue = "BUILDIN",
+ matchIfMissing = true,
)
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
- @ConditionalOnProperty(value = ["app.pseudonymize.gpas.uri"])
- @Bean
- fun gpasPseudonymGenerator(
- configProperties: GPasConfigProperties,
- retryTemplate: RetryTemplate,
- restTemplate: RestTemplate,
- appFhirConfig: AppFhirConfig,
- ): Generator {
- logger.info("Selected 'GpasPseudonym Generator'")
- return GpasPseudonymGenerator(configProperties, retryTemplate, restTemplate, appFhirConfig)
- }
-
- @ConditionalOnProperty(
- value = ["app.pseudonymize.generator"],
- havingValue = "BUILDIN",
- matchIfMissing = true,
- )
- @Bean
- fun buildinPseudonymGenerator(): Generator {
- logger.info("Selected 'BUILDIN Pseudonym Generator'")
- return AnonymizingGenerator()
- }
-
- @Bean
- fun pseudonymizeService(
- generator: Generator,
- pseudonymizeConfigProperties: PseudonymizeConfigProperties,
- ): PseudonymizeService {
- return PseudonymizeService(generator, pseudonymizeConfigProperties)
- }
-
- @Bean
- fun reportService(): ReportService {
- return ReportService(getObjectMapper())
- }
-
- @Bean
- fun getObjectMapper(): ObjectMapper {
- return JacksonConfig().objectMapper()
- }
-
- @Bean
- fun transformationService(configProperties: AppConfigProperties): TransformationService {
- logger.info("Apply ${configProperties.transformations.size} transformation rules")
- return TransformationService(
- getObjectMapper(),
- configProperties.transformations.map { Transformation.of(it.path) from it.from to it.to },
- )
- }
-
- @Bean
- fun retryTemplate(configProperties: AppConfigProperties): RetryTemplate {
- return RetryTemplateBuilder()
- .notRetryOn(IllegalArgumentException::class.java)
- .notRetryOn(HttpClientErrorException.BadRequest::class.java)
- .notRetryOn(HttpClientErrorException.UnprocessableContent::class.java)
- .exponentialBackoff(2.seconds.toJavaDuration(), 1.25, 5.seconds.toJavaDuration())
- .customPolicy(SimpleRetryPolicy(configProperties.maxRetryAttempts))
- .withListener(
- object : RetryListener {
- override fun <T : Any, E : Throwable> onError(
- context: RetryContext,
- callback: RetryCallback<T, E>,
- throwable: Throwable,
- ) {
- logger.warn("Error occured: {}. Retrying {}", throwable.message, context.retryCount)
- }
- }
+ @Bean
+ fun buildinPseudonymGenerator(): Generator {
+ logger.info("Selected 'BUILDIN Pseudonym Generator'")
+ return AnonymizingGenerator()
+ }
+
+ @Bean
+ fun pseudonymizeService(
+ generator: Generator,
+ pseudonymizeConfigProperties: PseudonymizeConfigProperties,
+ ): PseudonymizeService {
+ return PseudonymizeService(generator, pseudonymizeConfigProperties)
+ }
+
+ @Bean
+ fun reportService(): ReportService {
+ return ReportService(getJsonMapper())
+ }
+
+ @Bean
+ fun getJsonMapper(): JsonMapper {
+ return JacksonConfig().jsonMapper()
+ }
+
+ @Bean
+ fun transformationService(configProperties: AppConfigProperties): TransformationService {
+ logger.info("Apply ${configProperties.transformations.size} transformation rules")
+ return TransformationService(
+ getJsonMapper(),
+ configProperties.transformations.map { Transformation.of(it.path) from it.from to it.to },
)
- .build()
- }
-
- @ConditionalOnProperty(value = ["app.security.enable-tokens"], havingValue = "true")
- @Bean
- fun tokenService(
- userDetailsManager: InMemoryUserDetailsManager,
- passwordEncoder: PasswordEncoder,
- tokenRepository: TokenRepository,
- ): TokenService {
- return TokenService(userDetailsManager, passwordEncoder, tokenRepository)
- }
-
- @Bean
- fun statisticsUpdateProducer(): Sinks.Many<Any> {
- return Sinks.many().multicast().directBestEffort()
- }
-
- @Bean
- fun connectionCheckUpdateProducer(): Sinks.Many<ConnectionCheckResult> {
- return Sinks.many().multicast().onBackpressureBuffer()
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
- @Bean
- fun gPasConnectionCheckService(
- restTemplate: RestTemplate,
- gPasConfigProperties: GPasConfigProperties,
- connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
- ): ConnectionCheckService {
- return GPasConnectionCheckService(
- restTemplate,
- gPasConfigProperties,
- connectionCheckUpdateProducer,
- )
- }
-
- @ConditionalOnProperty(value = ["app.pseudonymizer"], havingValue = "GPAS")
- @ConditionalOnMissingBean
- @Bean
- fun gPasConnectionCheckServiceOnDeprecatedProperty(
- restTemplate: RestTemplate,
- gPasConfigProperties: GPasConfigProperties,
- connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
- ): ConnectionCheckService {
- return GPasConnectionCheckService(
- restTemplate,
- gPasConfigProperties,
- connectionCheckUpdateProducer,
- )
- }
-
- @Bean
- fun jdbcConfiguration(): AbstractJdbcConfiguration {
- return AppJdbcConfiguration()
- }
-
- @Conditional(GicsEnabledCondition::class)
- @Bean
- fun gicsConsentService(
- gIcsConfigProperties: GIcsConfigProperties,
- retryTemplate: RetryTemplate,
- restTemplate: RestTemplate,
- appFhirConfig: AppFhirConfig,
- ): IConsentService {
- return GicsConsentService(gIcsConfigProperties, retryTemplate, restTemplate, appFhirConfig)
- }
-
- @Conditional(GicsGetBroadConsentEnabledCondition::class)
- @Bean
- fun gicsGetBroadConsentService(
- gIcsConfigProperties: GIcsConfigProperties,
- retryTemplate: RetryTemplate,
- restTemplate: RestTemplate,
- appFhirConfig: AppFhirConfig,
- ): IConsentService {
- return GicsGetBroadConsentService(
- gIcsConfigProperties,
- retryTemplate,
- restTemplate,
- appFhirConfig,
- )
- }
-
- @Conditional(GicsEnabledCondition::class)
- @Bean
- fun consentProcessor(
- configProperties: AppConfigProperties,
- gIcsConfigProperties: GIcsConfigProperties,
- getObjectMapper: ObjectMapper,
- appFhirConfig: AppFhirConfig,
- gicsConsentService: IConsentService,
- ): ConsentProcessor {
- return ConsentProcessor(
- configProperties,
- gIcsConfigProperties,
- getObjectMapper,
- appFhirConfig.fhirContext(),
- gicsConsentService,
- )
- }
-
- @Conditional(GicsEnabledCondition::class)
- @Bean
- fun gIcsConnectionCheckService(
- restTemplate: RestTemplate,
- gIcsConfigProperties: GIcsConfigProperties,
- connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
- ): ConnectionCheckService {
- return GIcsConnectionCheckService(
- restTemplate,
- gIcsConfigProperties,
- connectionCheckUpdateProducer,
- )
- }
+ }
+
+ @Bean
+ fun retryTemplate(configProperties: AppConfigProperties): RetryTemplate {
+ return RetryTemplateBuilder()
+ .notRetryOn(IllegalArgumentException::class.java)
+ .notRetryOn(HttpClientErrorException.BadRequest::class.java)
+ .notRetryOn(HttpClientErrorException.UnprocessableContent::class.java)
+ .exponentialBackoff(2.seconds.toJavaDuration(), 1.25, 5.seconds.toJavaDuration())
+ .customPolicy(SimpleRetryPolicy(configProperties.maxRetryAttempts))
+ .withListener(
+ object : RetryListener {
+ override fun <T : Any, E : Throwable> onError(
+ context: RetryContext,
+ callback: RetryCallback<T, E>,
+ throwable: Throwable,
+ ) {
+ logger.warn("Error occured: {}. Retrying {}", throwable.message, context.retryCount)
+ }
+ }
+ )
+ .build()
+ }
+
+ @ConditionalOnProperty(value = ["app.security.enable-tokens"], havingValue = "true")
+ @Bean
+ fun tokenService(
+ userDetailsManager: InMemoryUserDetailsManager,
+ passwordEncoder: PasswordEncoder,
+ tokenRepository: TokenRepository,
+ ): TokenService {
+ return TokenService(userDetailsManager, passwordEncoder, tokenRepository)
+ }
+
+ @Bean
+ fun statisticsUpdateProducer(): Sinks.Many<Any> {
+ return Sinks.many().multicast().directBestEffort()
+ }
+
+ @Bean
+ fun connectionCheckUpdateProducer(): Sinks.Many<ConnectionCheckResult> {
+ return Sinks.many().multicast().onBackpressureBuffer()
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @Bean
+ fun gPasConnectionCheckService(
+ restTemplate: RestTemplate,
+ gPasConfigProperties: GPasConfigProperties,
+ connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
+ ): ConnectionCheckService {
+ return GPasConnectionCheckService(
+ restTemplate,
+ gPasConfigProperties,
+ connectionCheckUpdateProducer,
+ )
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymizer"], havingValue = "GPAS")
+ @ConditionalOnMissingBean
+ @Bean
+ fun gPasConnectionCheckServiceOnDeprecatedProperty(
+ restTemplate: RestTemplate,
+ gPasConfigProperties: GPasConfigProperties,
+ connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
+ ): ConnectionCheckService {
+ return GPasConnectionCheckService(
+ restTemplate,
+ gPasConfigProperties,
+ connectionCheckUpdateProducer,
+ )
+ }
+
+ @Bean
+ fun jdbcConfiguration(): AbstractJdbcConfiguration {
+ return AppJdbcConfiguration()
+ }
+
+ @Conditional(GicsEnabledCondition::class)
+ @Bean
+ fun gicsConsentService(
+ gIcsConfigProperties: GIcsConfigProperties,
+ retryTemplate: RetryTemplate,
+ restTemplate: RestTemplate,
+ appFhirConfig: AppFhirConfig,
+ ): IConsentService {
+ return GicsConsentService(gIcsConfigProperties, retryTemplate, restTemplate, appFhirConfig)
+ }
+
+ @Conditional(GicsGetBroadConsentEnabledCondition::class)
+ @Bean
+ fun gicsGetBroadConsentService(
+ gIcsConfigProperties: GIcsConfigProperties,
+ retryTemplate: RetryTemplate,
+ restTemplate: RestTemplate,
+ appFhirConfig: AppFhirConfig,
+ ): IConsentService {
+ return GicsGetBroadConsentService(
+ gIcsConfigProperties,
+ retryTemplate,
+ restTemplate,
+ appFhirConfig,
+ )
+ }
+
+ @Conditional(GicsEnabledCondition::class)
+ @Bean
+ fun consentProcessor(
+ configProperties: AppConfigProperties,
+ gIcsConfigProperties: GIcsConfigProperties,
+ getObjectMapper: JsonMapper,
+ appFhirConfig: AppFhirConfig,
+ gicsConsentService: IConsentService,
+ ): ConsentProcessor {
+ return ConsentProcessor(
+ configProperties,
+ gIcsConfigProperties,
+ getObjectMapper,
+ appFhirConfig.fhirContext(),
+ gicsConsentService,
+ )
+ }
+
+ @Conditional(GicsEnabledCondition::class)
+ @Bean
+ fun gIcsConnectionCheckService(
+ restTemplate: RestTemplate,
+ gIcsConfigProperties: GIcsConfigProperties,
+ connectionCheckUpdateProducer: Sinks.Many<ConnectionCheckResult>,
+ ): ConnectionCheckService {
+ return GIcsConnectionCheckService(
+ restTemplate,
+ gIcsConfigProperties,
+ connectionCheckUpdateProducer,
+ )
+ }
- @Bean
- @ConditionalOnMissingBean
- fun iGetConsentService(): IConsentService {
- return MtbFileConsentService()
- }
+ @Bean
+ @ConditionalOnMissingBean
+ fun iGetConsentService(): IConsentService {
+ return MtbFileConsentService()
+ }
}
class GicsEnabledCondition :
AnyNestedCondition(ConfigurationCondition.ConfigurationPhase.REGISTER_BEAN) {
- @ConditionalOnProperty(name = ["app.consent.service"], havingValue = "gics")
- @ConditionalOnProperty(name = ["app.consent.gics.uri"])
- class OnGicsServiceSelected {
- // Just for Condition
- }
+ @ConditionalOnProperty(name = ["app.consent.service"], havingValue = "gics")
+ @ConditionalOnProperty(name = ["app.consent.gics.uri"])
+ class OnGicsServiceSelected {
+ // Just for Condition
+ }
}
class GicsGetBroadConsentEnabledCondition :
AnyNestedCondition(ConfigurationCondition.ConfigurationPhase.REGISTER_BEAN) {
- @ConditionalOnProperty(name = ["app.consent.service"], havingValue = "gics_get_bc")
- @ConditionalOnProperty(name = ["app.consent.gics.uri"])
- class OnGicsGetBroadConsentServiceSelected {
- // Just for Condition
- }
+ @ConditionalOnProperty(name = ["app.consent.service"], havingValue = "gics_get_bc")
+ @ConditionalOnProperty(name = ["app.consent.gics.uri"])
+ class OnGicsGetBroadConsentServiceSelected {
+ // Just for Condition
+ }
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppFhirConfig.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppFhirConfig.kt
index 052822e..a7e6378 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppFhirConfig.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppFhirConfig.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import ca.uhn.fhir.context.FhirContext
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppJdbcConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppJdbcConfiguration.kt
index 769faf3..a5bf1ae 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppJdbcConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppJdbcConfiguration.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import dev.dnpm.etl.processor.Fingerprint
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppKafkaConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppKafkaConfiguration.kt
index 24fc58c..aa3e6cb 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppKafkaConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppKafkaConfiguration.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,7 +20,6 @@
package dev.dnpm.etl.processor.config
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.consent.ConsentEvaluator
import dev.dnpm.etl.processor.input.KafkaInputListener
import dev.dnpm.etl.processor.monitoring.ConnectionCheckResult
@@ -43,6 +43,7 @@ import org.springframework.kafka.listener.ContainerProperties
import org.springframework.kafka.listener.KafkaMessageListenerContainer
import org.springframework.retry.support.RetryTemplate
import reactor.core.publisher.Sinks
+import tools.jackson.databind.json.JsonMapper
@Configuration
@EnableConfigurationProperties(value = [KafkaProperties::class])
@@ -57,10 +58,10 @@ class AppKafkaConfiguration {
kafkaTemplate: KafkaTemplate<String, String>,
kafkaProperties: KafkaProperties,
retryTemplate: RetryTemplate,
- objectMapper: ObjectMapper,
+ jsonMapper: JsonMapper,
): MtbFileSender {
logger.info("Selected 'KafkaMtbFileSender'")
- return KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
+ return KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, jsonMapper)
}
@Bean
@@ -77,8 +78,8 @@ class AppKafkaConfiguration {
@Bean
fun kafkaResponseProcessor(
applicationEventPublisher: ApplicationEventPublisher,
- objectMapper: ObjectMapper,
- ): KafkaResponseProcessor = KafkaResponseProcessor(applicationEventPublisher, objectMapper)
+ jsonMapper: JsonMapper,
+ ): KafkaResponseProcessor = KafkaResponseProcessor(applicationEventPublisher, jsonMapper)
@Bean
@ConditionalOnProperty(value = ["app.kafka.input-topic"])
@@ -99,9 +100,9 @@ class AppKafkaConfiguration {
@ConditionalOnProperty(value = ["app.kafka.input-topic"])
fun kafkaInputListener(
requestProcessor: RequestProcessor,
- objectMapper: ObjectMapper,
+ jsonMapper: JsonMapper,
consentEvaluator: ConsentEvaluator,
- ): KafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, objectMapper)
+ ): KafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, jsonMapper)
@Bean
fun kafkaConnectionCheckService(
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppRestConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppRestConfiguration.kt
index 565209e..d10a32f 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppRestConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppRestConfiguration.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppSecurityConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppSecurityConfiguration.kt
index 60b1a9c..b87a1bd 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppSecurityConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppSecurityConfiguration.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppWebConfig.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppWebConfig.kt
index 3aa50f2..7efa5c8 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppWebConfig.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppWebConfig.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import org.springframework.boot.convert.ApplicationConversionService
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AuditConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AuditConfiguration.kt
index 45763ee..1f392c0 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AuditConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AuditConfiguration.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import org.springframework.context.annotation.Bean
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/Jackson2Config.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/Jackson2Config.kt
new file mode 100644
index 0000000..27204d0
--- /dev/null
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/Jackson2Config.kt
@@ -0,0 +1,85 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor.config
+
+import ca.uhn.fhir.context.FhirContext
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.core.JsonGenerator
+import com.fasterxml.jackson.core.JsonParser
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
+import org.hl7.fhir.r4.model.Consent
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+
+/**
+ * @deprecated Use JacksonConfig instead
+ * @since 0.16
+ */
+@Deprecated("Use JacksonConfig instead")
+@Configuration
+class Jackson2Config {
+ companion object {
+ var fhirContext: FhirContext = FhirContext.forR4()
+
+ @JvmStatic fun fhirContext(): FhirContext = fhirContext
+ }
+
+ @Bean
+ fun objectMapper(): com.fasterxml.jackson.databind.ObjectMapper =
+ com.fasterxml.jackson.databind
+ .ObjectMapper()
+ .registerModule(Jackson2FhirResourceModule())
+ .disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .registerModule(JavaTimeModule())
+ .registerModule(Jdk8Module())
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+}
+
+class Jackson2FhirResourceModule : com.fasterxml.jackson.databind.module.SimpleModule() {
+ init {
+ addSerializer(Consent::class.java, Jackson2ConsentResourceSerializer())
+ addDeserializer(Consent::class.java, Jackson2ConsentResourceDeserializer())
+ }
+}
+
+class Jackson2ConsentResourceSerializer : com.fasterxml.jackson.databind.JsonSerializer<Consent>() {
+ override fun serialize(
+ value: Consent,
+ gen: JsonGenerator,
+ serializers: com.fasterxml.jackson.databind.SerializerProvider,
+ ) {
+ val json = Jackson2Config.fhirContext().newJsonParser().encodeResourceToString(value)
+ gen.writeRawValue(json)
+ }
+}
+
+class Jackson2ConsentResourceDeserializer : com.fasterxml.jackson.databind.JsonDeserializer<Consent>() {
+ override fun deserialize(
+ p: JsonParser?,
+ ctxt: com.fasterxml.jackson.databind.DeserializationContext?,
+ ): Consent {
+ val jsonNode = p?.readValueAsTree<com.fasterxml.jackson.databind.JsonNode>()
+ val json = jsonNode?.toString()
+
+ return Jackson2Config.fhirContext().newJsonParser().parseResource(json) as Consent
+ }
+}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/JacksonConfig.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/JacksonConfig.kt
index 847880d..94f08c7 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/JacksonConfig.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/JacksonConfig.kt
@@ -1,19 +1,38 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
import ca.uhn.fhir.context.FhirContext
import com.fasterxml.jackson.annotation.JsonInclude
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.core.JsonParser
-import com.fasterxml.jackson.databind.*
-import com.fasterxml.jackson.databind.module.SimpleModule
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import org.hl7.fhir.r4.model.Consent
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
+import tools.jackson.databind.*
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.databind.module.SimpleModule
+import tools.jackson.module.kotlin.KotlinModule
@Configuration
class JacksonConfig {
+
companion object {
var fhirContext: FhirContext = FhirContext.forR4()
@@ -21,36 +40,38 @@ class JacksonConfig {
}
@Bean
- fun objectMapper(): ObjectMapper =
- ObjectMapper()
- .registerModule(Jackson2FhirResourceModule())
- .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
- .registerModule(JavaTimeModule())
- .registerModule(Jdk8Module())
- .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ fun jsonMapper(): JsonMapper =
+ JsonMapper
+ .builder()
+ .addModule(JacksonFhirResourceModule())
+ .addModule(KotlinModule.Builder().build())
+ .changeDefaultPropertyInclusion {
+ it.withContentInclusion(JsonInclude.Include.NON_NULL)
+ it.withValueInclusion(JsonInclude.Include.NON_NULL)
+ }.build()
}
-class Jackson2FhirResourceModule : SimpleModule() {
+class JacksonFhirResourceModule : SimpleModule() {
init {
- addSerializer(Consent::class.java, Jackson2ConsentResourceSerializer())
- addDeserializer(Consent::class.java, Jackson2ConsentResourceDeserializer())
+ addSerializer(Consent::class.java, JacksonConsentResourceSerializer())
+ addDeserializer(Consent::class.java, JacksonConsentResourceDeserializer())
}
}
-class Jackson2ConsentResourceSerializer : JsonSerializer<Consent>() {
+class JacksonConsentResourceSerializer : ValueSerializer<Consent>() {
override fun serialize(
- value: Consent,
- gen: JsonGenerator,
- serializers: SerializerProvider,
+ value: Consent?,
+ gen: tools.jackson.core.JsonGenerator?,
+ ctxt: SerializationContext?,
) {
val json = JacksonConfig.fhirContext().newJsonParser().encodeResourceToString(value)
- gen.writeRawValue(json)
+ gen?.writeRawValue(json)
}
}
-class Jackson2ConsentResourceDeserializer : JsonDeserializer<Consent>() {
+class JacksonConsentResourceDeserializer : ValueDeserializer<Consent>() {
override fun deserialize(
- p: JsonParser?,
+ p: tools.jackson.core.JsonParser?,
ctxt: DeserializationContext?,
): Consent {
val jsonNode = p?.readValueAsTree<JsonNode>()
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt b/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt
index 58f647f..a8b8fdb 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/functions.kt b/src/main/kotlin/dev/dnpm/etl/processor/functions.kt
index aa4fc75..8326ad0 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/functions.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/functions.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2026 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
index 03cd03d..a126e07 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,7 +20,6 @@
package dev.dnpm.etl.processor.input
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientId
import dev.dnpm.etl.processor.RequestId
@@ -31,12 +31,13 @@ import org.apache.kafka.clients.consumer.ConsumerRecord
import org.slf4j.LoggerFactory
import org.springframework.http.MediaType
import org.springframework.kafka.listener.MessageListener
+import tools.jackson.databind.json.JsonMapper
import java.nio.charset.Charset
class KafkaInputListener(
private val requestProcessor: RequestProcessor,
private val consentEvaluator: ConsentEvaluator,
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
) : MessageListener<String, String> {
private val logger = LoggerFactory.getLogger(KafkaInputListener::class.java)
@@ -71,7 +72,7 @@ class KafkaInputListener(
private fun handleDnpmV2Message(record: ConsumerRecord<String, String>) {
try {
- val mtbFile = objectMapper.readValue(record.value(), Mtb::class.java)
+ val mtbFile = jsonMapper.readValue(record.value(), Mtb::class.java)
val patientId = PatientId(mtbFile.patient.id)
val firstRequestIdHeader = record.headers().headers("requestId")?.firstOrNull()
val requestId =
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
index c9825c7..47f0766 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckService.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckService.kt
index a88cf10..c9c73a2 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ReportService.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ReportService.kt
index c54aa7a..b9359fc 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ReportService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/ReportService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,64 +20,61 @@
package dev.dnpm.etl.processor.monitoring
-import com.fasterxml.jackson.annotation.JsonAlias
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.annotation.JsonValue
-import com.fasterxml.jackson.core.JsonParseException
-import com.fasterxml.jackson.databind.JsonMappingException
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.monitoring.ReportService.Issue
import dev.dnpm.etl.processor.monitoring.ReportService.Severity
+import tools.jackson.core.JacksonException
+import tools.jackson.databind.EnumNamingStrategies
+import tools.jackson.databind.annotation.EnumNaming
+import tools.jackson.databind.json.JsonMapper
import java.util.*
-class ReportService(private val objectMapper: ObjectMapper) {
+class ReportService(private val jsonMapper: JsonMapper) {
- fun deserialize(dataQualityReport: String?): List<Issue> {
- if (dataQualityReport.isNullOrBlank()) {
- return listOf()
+ fun deserialize(dataQualityReport: String?): List<Issue> {
+ if (dataQualityReport.isNullOrBlank()) {
+ return listOf()
+ }
+ return try {
+ jsonMapper.readValue(dataQualityReport, DataQualityReport::class.java).issues.sortedBy {
+ it.severity
+ }
+ } catch (_: JacksonException) {
+ val otherIssue =
+ Issue(Severity.ERROR, Optional.of("Not parsable data quality report '$dataQualityReport'"))
+ return listOf(otherIssue)
+ } catch (e: Exception) {
+ throw e
+ }
}
- return try {
- objectMapper.readValue(dataQualityReport, DataQualityReport::class.java).issues.sortedBy {
- it.severity
- }
- } catch (e: Exception) {
- val otherIssue =
- Issue(Severity.ERROR, "Not parsable data quality report '$dataQualityReport'")
- return when (e) {
- is JsonMappingException -> listOf(otherIssue)
- is JsonParseException -> listOf(otherIssue)
- else -> throw e
- }
- }
- }
- @JsonIgnoreProperties(ignoreUnknown = true)
- private data class DataQualityReport(
- @param:JsonProperty(value = "issues") val issues: List<Issue>
- )
+ private data class DataQualityReport(
+ val issues: List<Issue>
+ )
- @JsonIgnoreProperties(ignoreUnknown = true)
- data class Issue(
- @param:JsonProperty(value = "severity") val severity: Severity,
- @param:JsonProperty(value = "message") @param:JsonAlias("details") val message: String,
- @param:JsonProperty(value = "path") val path: Optional<String> = Optional.empty(),
- )
+ data class Issue(
+ val severity: Severity,
+ val message: Optional<String> = Optional.empty(),
+ val details: Optional<String> = Optional.empty(),
+ val path: Optional<String> = Optional.empty(),
+ ) {
+ fun getMessage() = message.orElse(details.orElse("No details available"))
+ }
- enum class Severity(@JsonValue val value: String) {
- FATAL("fatal"),
- ERROR("error"),
- WARNING("warning"),
- INFO("info"),
- }
+ @EnumNaming(EnumNamingStrategies.LowerCaseStrategy::class)
+ enum class Severity(val value: String) {
+ FATAL("fatal"),
+ ERROR("error"),
+ WARNING("warning"),
+ INFO("info"),
+ }
}
fun List<Issue>.asRequestStatus(): RequestStatus {
- val severity = this.minOfOrNull { it.severity }
- return when (severity) {
- Severity.FATAL,
- Severity.ERROR -> RequestStatus.ERROR
- Severity.WARNING -> RequestStatus.WARNING
- else -> RequestStatus.SUCCESS
- }
+ val severity = this.minOfOrNull { it.severity }
+ return when (severity) {
+ Severity.FATAL,
+ Severity.ERROR -> RequestStatus.ERROR
+ Severity.WARNING -> RequestStatus.WARNING
+ else -> RequestStatus.SUCCESS
+ }
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
index 8b2776a..a1f5c3d 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestStatus.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestStatus.kt
index a0cd4ad..f1bf304 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestStatus.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestStatus.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestType.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestType.kt
index ef7f1e3..9611232 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestType.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/RequestType.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/SubmissionType.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/SubmissionType.kt
index 351281e..4001b7e 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/SubmissionType.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/SubmissionType.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.monitoring
enum class SubmissionType(
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt
index bcd532f..8c20b7c 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,7 +20,6 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.config.KafkaProperties
import dev.dnpm.etl.processor.monitoring.RequestStatus
@@ -29,12 +29,13 @@ import org.apache.kafka.clients.producer.ProducerRecord
import org.slf4j.LoggerFactory
import org.springframework.kafka.core.KafkaTemplate
import org.springframework.retry.support.RetryTemplate
+import tools.jackson.databind.json.JsonMapper
class KafkaMtbFileSender(
private val kafkaTemplate: KafkaTemplate<String, String>,
private val kafkaProperties: KafkaProperties,
private val retryTemplate: RetryTemplate,
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
) : MtbFileSender {
private val logger = LoggerFactory.getLogger(KafkaMtbFileSender::class.java)
@@ -45,7 +46,7 @@ class KafkaMtbFileSender(
ProducerRecord(
kafkaProperties.outputTopic,
key(request),
- objectMapper.writeValueAsString(request.content),
+ jsonMapper.writeValueAsString(request.content),
)
record.headers().add("requestId", request.requestId.value.toByteArray())
record.headers().add("requestMethod", "POST".toByteArray())
@@ -82,7 +83,7 @@ class KafkaMtbFileSender(
ProducerRecord(
kafkaProperties.outputTopic,
key(request),
- objectMapper.writeValueAsString(
+ jsonMapper.writeValueAsString(
DnpmV2MtbFileRequest(request.requestId, dummyMtbFile),
),
)
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbFileSender.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbFileSender.kt
index c81b572..3d0a8dd 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbFileSender.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbFileSender.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt
index b228c4c..75401e6 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSender.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSender.kt
index 5aad133..89232bd 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSender.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSender.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSender.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSender.kt
index 0d8ed7b..7e25827 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSender.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSender.kt
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2025 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
index 90d867f..b3c80e2 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt
index 089736c..589a2d4 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.pseudonym
import dev.dnpm.etl.processor.config.AppFhirConfig
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt
index f1121b8..4daba3a 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.pseudonym
import jakarta.jws.WebMethod
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt
index 77ab87d..9eec9f3 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt
index d8969c1..6615b35 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/security/TokenService.kt b/src/main/kotlin/dev/dnpm/etl/processor/security/TokenService.kt
index fd75446..74f3127 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/security/TokenService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/security/TokenService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/security/UserRole.kt b/src/main/kotlin/dev/dnpm/etl/processor/security/UserRole.kt
index bfe966a..c67c89d 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/security/UserRole.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/security/UserRole.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (C) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -15,7 +16,6 @@
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
*/
package dev.dnpm.etl.processor.security
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/security/UserRoleService.kt b/src/main/kotlin/dev/dnpm/etl/processor/security/UserRoleService.kt
index bf46b84..0c1fe11 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/security/UserRoleService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/security/UserRoleService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt
index 4a9a6bd..a95420a 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt
@@ -1,9 +1,27 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.services
import ca.uhn.fhir.context.FhirContext
import com.fasterxml.jackson.core.JsonProcessingException
-import com.fasterxml.jackson.core.type.TypeReference
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.consent.ConsentDomain
@@ -11,10 +29,6 @@ import dev.dnpm.etl.processor.consent.IConsentService
import dev.dnpm.etl.processor.consent.MtbFileConsentService
import dev.dnpm.etl.processor.pseudonym.ensureMetaDataIsInitialized
import dev.pcvolkmer.mv64e.mtb.*
-import java.io.IOException
-import java.time.Clock
-import java.time.Instant
-import java.util.*
import org.apache.commons.lang3.NotImplementedException
import org.hl7.fhir.r4.model.*
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent
@@ -23,12 +37,17 @@ import org.hl7.fhir.r4.model.Consent.ProvisionComponent
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
+import tools.jackson.databind.json.JsonMapper
+import java.io.IOException
+import java.time.Clock
+import java.time.Instant
+import java.util.*
@Service
class ConsentProcessor(
private val appConfigProperties: AppConfigProperties,
private val gIcsConfigProperties: GIcsConfigProperties,
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
private val fhirContext: FhirContext,
private val consentService: IConsentService,
) {
@@ -119,9 +138,9 @@ class ConsentProcessor(
val asJsonString = fhirContext.newJsonParser().encodeResourceToString(resource)
try {
val mapOfJson: MvhMetadata.ResearchConsent? =
- objectMapper.readValue<MvhMetadata.ResearchConsent?>(
+ jsonMapper.readValue(
asJsonString,
- object : TypeReference<MvhMetadata.ResearchConsent?>() {},
+ MvhMetadata.ResearchConsent::class.java,
)
mtbFile.metadata.researchConsents.add(mapOfJson)
} catch (e: JsonProcessingException) {
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt
index f0eed7f..b94fbbc 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt
@@ -2,7 +2,7 @@
* This file is part of ETL-Processor
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
- * Copyright (c) 2023-2026 Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -20,7 +20,6 @@
package dev.dnpm.etl.processor.services
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.*
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.consent.TtpConsentStatus
@@ -41,6 +40,7 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
+import tools.jackson.databind.json.JsonMapper
import java.time.Instant
import java.util.*
@@ -50,7 +50,7 @@ class RequestProcessor(
private val transformationService: TransformationService,
private val sender: MtbFileSender,
private val requestService: RequestService,
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
private val applicationEventPublisher: ApplicationEventPublisher,
private val appConfigProperties: AppConfigProperties,
private val consentProcessor: ConsentProcessor?,
@@ -292,7 +292,7 @@ class RequestProcessor(
private fun <T> fingerprint(request: MtbFileRequest<T>): Fingerprint {
return when (request) {
- is DnpmV2MtbFileRequest -> fingerprint(objectMapper.writeValueAsString(request.content))
+ is DnpmV2MtbFileRequest -> fingerprint(jsonMapper.writeValueAsString(request.content))
}
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestService.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestService.kt
index eb57a6c..b967f2d 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/ResponseProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/ResponseProcessor.kt
index 3ecac71..947ec17 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/ResponseProcessor.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/ResponseProcessor.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt
index df8ac3d..755e6b3 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,18 +20,18 @@
package dev.dnpm.etl.processor.services
-import com.fasterxml.jackson.databind.ObjectMapper
import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.PathNotFoundException
import dev.pcvolkmer.mv64e.mtb.Mtb
+import tools.jackson.databind.json.JsonMapper
class TransformationService(
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
private val transformations: List<Transformation>,
) {
fun transform(mtbFile: Mtb): Mtb {
- val json = transform(objectMapper.writeValueAsString(mtbFile))
- return objectMapper.readValue(json, Mtb::class.java)
+ val json = transform(jsonMapper.writeValueAsString(mtbFile))
+ return jsonMapper.readValue(json, Mtb::class.java)
}
private fun transform(content: String): String {
@@ -61,7 +62,7 @@ class TransformationService(
newValue,
{ it.item(HashMap::class.java)[last] == existingValue },
)
- } catch (e: PathNotFoundException) {
+ } catch (_: PathNotFoundException) {
// Ignore
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessor.kt
index e70f1e7..41f7720 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessor.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessor.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,71 +20,70 @@
package dev.dnpm.etl.processor.services.kafka
-import com.fasterxml.jackson.annotation.JsonAlias
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.output.asRequestStatus
import dev.dnpm.etl.processor.services.ResponseEvent
-import java.time.Instant
-import java.util.*
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationEventPublisher
import org.springframework.kafka.listener.MessageListener
+import tools.jackson.databind.PropertyNamingStrategies
+import tools.jackson.databind.annotation.JsonNaming
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
class KafkaResponseProcessor(
private val eventPublisher: ApplicationEventPublisher,
- private val objectMapper: ObjectMapper,
+ private val jsonMapper: JsonMapper,
) : MessageListener<String, String> {
- private val logger = LoggerFactory.getLogger(KafkaResponseProcessor::class.java)
+ private val logger = LoggerFactory.getLogger(KafkaResponseProcessor::class.java)
- override fun onMessage(data: ConsumerRecord<String, String>) {
- try {
- Optional.of(objectMapper.readValue(data.value(), ResponseBody::class.java))
+ override fun onMessage(data: ConsumerRecord<String, String>) {
+ try {
+ Optional.of(jsonMapper.readValue(data.value(), ResponseBody::class.java))
} catch (e: Exception) {
- logger.error("Cannot process Kafka response", e)
- Optional.empty()
+ logger.error("Cannot process Kafka response", e)
+ Optional.empty()
}
- .ifPresentOrElse(
- { responseBody ->
- val event =
- ResponseEvent(
- RequestId(responseBody.requestId),
- Instant.ofEpochMilli(data.timestamp()),
- responseBody.statusCode.asRequestStatus(),
- when (responseBody.statusCode.asRequestStatus()) {
- RequestStatus.SUCCESS -> {
- Optional.empty()
- }
+ .ifPresentOrElse(
+ { responseBody ->
+ val event =
+ ResponseEvent(
+ RequestId(responseBody.requestId),
+ Instant.ofEpochMilli(data.timestamp()),
+ responseBody.statusCode.asRequestStatus(),
+ when (responseBody.statusCode.asRequestStatus()) {
+ RequestStatus.SUCCESS -> {
+ Optional.empty()
+ }
- RequestStatus.WARNING,
- RequestStatus.ERROR -> {
- Optional.of(objectMapper.writeValueAsString(responseBody.statusBody))
- }
+ RequestStatus.WARNING,
+ RequestStatus.ERROR -> {
+ Optional.of(jsonMapper.writeValueAsString(responseBody.statusBody))
+ }
- else -> {
- logger.error(
- "Kafka response: Unknown response code '{}'!",
- responseBody.statusCode,
- )
- Optional.empty()
- }
- },
- )
- eventPublisher.publishEvent(event)
- },
- { logger.error("No requestId in Kafka response") },
- )
- }
+ else -> {
+ logger.error(
+ "Kafka response: Unknown response code '{}'!",
+ responseBody.statusCode,
+ )
+ Optional.empty()
+ }
+ },
+ )
+ eventPublisher.publishEvent(event)
+ },
+ { logger.error("No requestId in Kafka response") },
+ )
+ }
- data class ResponseBody(
- @param:JsonProperty("request_id") @param:JsonAlias("requestId") val requestId: String,
- @param:JsonProperty("status_code") @param:JsonAlias("statusCode") val statusCode: Int,
- @param:JsonProperty("status_body")
- @param:JsonAlias("statusBody")
- val statusBody: Map<String, Any>,
- )
+ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
+ data class ResponseBody(
+ val requestId: String,
+ val statusCode: Int,
+ val statusBody: Map<String, Any>,
+ )
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/types.kt b/src/main/kotlin/dev/dnpm/etl/processor/types.kt
index 9244297..9abd25d 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/types.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/types.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/ApplicationControllerAdvice.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/ApplicationControllerAdvice.kt
index e81b348..508d12b 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/ApplicationControllerAdvice.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/ApplicationControllerAdvice.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/ConfigController.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/ConfigController.kt
index b77bdf9..5bd25b7 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/ConfigController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/ConfigController.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/HomeController.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/HomeController.kt
index 6622348..6347735 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/HomeController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/HomeController.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/LoginController.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/LoginController.kt
index 9b49f5a..c62553a 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/LoginController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/LoginController.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsController.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsController.kt
index 8dfe595..4cb99f1 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsController.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsRestController.kt b/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsRestController.kt
index 8843d8e..3ea9667 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsRestController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/web/StatisticsRestController.kt
@@ -1,7 +1,7 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
* Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
@@ -20,8 +20,6 @@
package dev.dnpm.etl.processor.web
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.annotation.JsonPropertyOrder
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.monitoring.RequestType
import dev.dnpm.etl.processor.services.RequestService
@@ -34,6 +32,8 @@ import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.Sinks
+import tools.jackson.databind.PropertyNamingStrategies
+import tools.jackson.databind.annotation.JsonNaming
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@@ -201,15 +201,13 @@ data class DateNameValues(
val nameValues: NameValues,
)
-@JsonPropertyOrder(value = ["error", "warning", "success", "no_consent", "duplication", "blocked_initial", "unknown"])
+@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class NameValues(
val error: Int = 0,
val warning: Int = 0,
val success: Int = 0,
- @field:JsonProperty("no_consent")
val noConsent: Int = 0,
val duplication: Int = 0,
- @field:JsonProperty("blocked_initial")
val blockedInitial: Int = 0,
val unknown: Int = 0,
)
diff --git a/src/main/resources/static/icon.svg b/src/main/resources/static/icon.svg
index 90c3a65..7b36666 100644
--- a/src/main/resources/static/icon.svg
+++ b/src/main/resources/static/icon.svg
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
<svg
width="256"
height="256"
diff --git a/src/main/resources/static/user.svg b/src/main/resources/static/user.svg
index 506d632..abec848 100644
--- a/src/main/resources/static/user.svg
+++ b/src/main/resources/static/user.svg
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="24" height="24" version="1.1" viewBox="0 0 6.35 6.35" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1.2 0 0 1.2 -108.01 -85.977)">
<rect x="90.01" y="71.647" width="5.2917" height="5.2917" rx=".96212" fill="#b3b3b3"/>
diff --git a/src/main/resources/templates/report.html b/src/main/resources/templates/report.html
index bad8ca2..bdc7457 100644
--- a/src/main/resources/templates/report.html
+++ b/src/main/resources/templates/report.html
@@ -34,7 +34,7 @@
<td th:if="${issue.severity.value == 'error'}" class="bg-red"><small>[[ ${issue.severity} ]]</small></td>
<td th:if="${issue.severity.value == 'fatal'}" class="bg-red"><small>[[ ${issue.severity} ]]</small></td>
<td>
- <div class="issue-message">[[ ${issue.message} ]]</div>
+ <div class="issue-message">[[ ${issue.getMessage()} ]]</div>
<div class="issue-path" th:if="${issue.path.isPresent()}">[[ ${issue.path.get()} ]]</div>
<div class="issue-path" th:if="${issue.path.isEmpty()}"><i>Keine Angabe</i></div>
</td>
diff --git a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
index 22f676b..1f9e698 100644
--- a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
+++ b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import static dev.dnpm.etl.processor.consent.GicsConsentService.IS_CONSENTED_ENDPOINT;
diff --git a/src/test/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentServiceTest.java b/src/test/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentServiceTest.java
index 46da158..e97a8d4 100644
--- a/src/test/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentServiceTest.java
+++ b/src/test/java/dev/dnpm/etl/processor/consent/GicsGetBroadConsentServiceTest.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/src/test/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluatorTest.java b/src/test/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluatorTest.java
index e63dddc..ebaf043 100644
--- a/src/test/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluatorTest.java
+++ b/src/test/java/dev/dnpm/etl/processor/consent/MiiBroadConsentEvaluatorTest.java
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
index 716529b..95ef0d4 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/FunctionsTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2026 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
new file mode 100644
index 0000000..b940537
--- /dev/null
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/Jackson3ConfigTest.kt
@@ -0,0 +1,92 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor.config
+
+import com.fasterxml.jackson.databind.node.ObjectNode
+import dev.pcvolkmer.mv64e.mtb.Mtb
+import dev.pcvolkmer.mv64e.mtb.MvhMetadata
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
+import java.util.*
+
+class Jackson3ConfigTest {
+
+ lateinit var jacksonConfig: JacksonConfig
+
+ @BeforeEach
+ fun setup() {
+ this.jacksonConfig = JacksonConfig()
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [
+ "mv64e-mtb-fake-patient.json",
+ "fake_broadConsent_mii_response_deny.json",
+ "fake_broadConsent_mii_response_permit.json",
+ ])
+ fun shouldSerializeJsonWithoutNulledOutFields(filename: String) {
+ val inputJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
+
+ val jsonNode = this.jacksonConfig.jsonMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(jsonNode)
+
+ assertThat(actual).doesNotContain("null")
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [
+ "fake_broadConsent_mii_response_deny.json",
+ "fake_broadConsent_mii_response_permit.json",
+ ])
+ fun shouldSerializeConsentWithoutWithoutDatesAsTimestamps(filename: String) {
+ val inputJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
+
+ val json = this.jacksonConfig.jsonMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(json)
+
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ }
+
+ @Test
+ fun shouldSerializeJsonWithBroadConsent() {
+ val inputMtbFileJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("mv64e-mtb-fake-patient.json"))?.readAllBytes()?.decodeToString()
+
+ val inputConsentJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("fake_broadConsent_mii_response_permit.json"))?.readAllBytes()?.decodeToString()
+
+ val mtb = this.jacksonConfig.jsonMapper().readValue<Mtb>(inputMtbFileJson, Mtb::class.java)
+ // Still use Jackson2 ObjectMapper since MTB DTO requires Jackson2 ObjectNode
+ val consentJsonNode = Jackson2Config().objectMapper().readTree(inputConsentJson)
+ mtb.metadata = MvhMetadata.builder().researchConsents(listOf(MvhMetadata.ResearchConsent.from(consentJsonNode as ObjectNode))).build()
+
+ val actual = this.jacksonConfig.jsonMapper().writeValueAsString(mtb)
+
+ assertThat(actual).doesNotContain("null")
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ assertThat(actual).contains("""{"entry":[{"fullUrl":"http://localhost:8080/ttp-fhir/fhir/gics/Consent/7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd"""")
+ }
+}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
index 9042d8c..e734c6f 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/config/JacksonConfigTest.kt
@@ -1,5 +1,28 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.config
+import com.fasterxml.jackson.databind.node.ObjectNode
+import dev.pcvolkmer.mv64e.mtb.Mtb
+import dev.pcvolkmer.mv64e.mtb.MvhMetadata
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -9,11 +32,11 @@ import java.util.*
class JacksonConfigTest {
- lateinit var jacksonConfig: JacksonConfig
+ lateinit var jacksonConfig: Jackson2Config
@BeforeEach
fun setup() {
- this.jacksonConfig = JacksonConfig()
+ this.jacksonConfig = Jackson2Config()
}
@ParameterizedTest
@@ -26,8 +49,8 @@ class JacksonConfigTest {
val inputJson =
Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream(filename))?.readAllBytes()?.decodeToString()
- val json = this.jacksonConfig.objectMapper().readTree(inputJson)
- val actual = this.jacksonConfig.objectMapper().writeValueAsString(json)
+ val jsonNode = this.jacksonConfig.objectMapper().readTree(inputJson)
+ val actual = this.jacksonConfig.objectMapper().writeValueAsString(jsonNode)
assertThat(actual).doesNotContain("null")
}
@@ -47,4 +70,23 @@ class JacksonConfigTest {
assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
}
+ @Test
+ fun shouldSerializeJsonWithBroadConsent() {
+ val inputMtbFileJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("mv64e-mtb-fake-patient.json"))?.readAllBytes()?.decodeToString()
+
+ val inputConsentJson =
+ Objects.requireNonNull(this.javaClass.classLoader.getResourceAsStream("fake_broadConsent_mii_response_permit.json"))?.readAllBytes()?.decodeToString()
+
+ val mtb = this.jacksonConfig.objectMapper().readValue<Mtb>(inputMtbFileJson, Mtb::class.java)
+ val consentJsonNode = this.jacksonConfig.objectMapper().readTree(inputConsentJson)
+ mtb.metadata = MvhMetadata.builder().researchConsents(listOf(MvhMetadata.ResearchConsent.from(consentJsonNode as ObjectNode))).build()
+
+ val actual = this.jacksonConfig.objectMapper().writeValueAsString(mtb)
+
+ assertThat(actual).doesNotContain("null")
+ assertThat(actual).contains(""""lastUpdated":"2025-08-15T11:13:59.143+02:00"""")
+ assertThat(actual).contains("""{"entry":[{"fullUrl":"http://localhost:8080/ttp-fhir/fhir/gics/Consent/7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd"""")
+ }
+
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
index 1140425..30e3823 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/consent/ConsentProcessorTest.kt
@@ -1,11 +1,29 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.consent
import ca.uhn.fhir.context.FhirContext
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.services.ConsentProcessor
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Consent
@@ -15,13 +33,15 @@ import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
+import tools.jackson.databind.json.JsonMapper
+import java.util.*
@ExtendWith(MockitoExtension::class)
class ConsentProcessorTest {
lateinit var consentProcessor: ConsentProcessor
- val objectMapper = ObjectMapper()
+ val jsonMapper = JsonMapper()
val fhirContext = FhirContext.forR4()
@BeforeEach
@@ -33,7 +53,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
consentService,
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
index 85a8b3e..284c552 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/consent/Dnpm21BasedConsentEvaluatorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
index b7bf436..192bf90 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
index 0d3f275..eeb6288 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -43,13 +44,14 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.firstValue
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
+import tools.jackson.databind.json.JsonMapper
import java.util.*
@ExtendWith(MockitoExtension::class)
class KafkaInputListenerTest {
private lateinit var requestProcessor: RequestProcessor
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var kafkaInputListener: KafkaInputListener
@@ -59,9 +61,9 @@ class KafkaInputListenerTest {
@Mock consentEvaluator: ConsentEvaluator,
) {
this.requestProcessor = requestProcessor
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
- this.kafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, objectMapper)
+ this.kafkaInputListener = KafkaInputListener(requestProcessor, consentEvaluator, jsonMapper)
}
@Test
@@ -88,7 +90,7 @@ class KafkaInputListenerTest {
.build()
kafkaInputListener.onMessage(
- ConsumerRecord("testtopic", 0, 0, "", this.objectMapper.writeValueAsString(mtbFile))
+ ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
@@ -113,7 +115,7 @@ class KafkaInputListenerTest {
.build()
kafkaInputListener.onMessage(
- ConsumerRecord("testtopic", 0, 0, "", this.objectMapper.writeValueAsString(mtbFile))
+ ConsumerRecord("testtopic", 0, 0, "", this.jsonMapper.writeValueAsString(mtbFile))
)
verify(requestProcessor, times(1)).processMtbFile(any<Mtb>())
}
@@ -153,7 +155,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -197,7 +199,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -248,7 +250,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
@@ -303,7 +305,7 @@ class KafkaInputListenerTest {
-1,
-1,
"",
- this.objectMapper.writeValueAsString(mtbFile),
+ this.jsonMapper.writeValueAsString(mtbFile),
headers,
Optional.empty(),
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
index c8e5804..9ee4b2b 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
index a380d2a..62ece6c 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ConnectionCheckServiceTest.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.monitoring
import dev.dnpm.etl.processor.config.GIcsConfigProperties
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
index 74d1138..83c2354 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/monitoring/ReportServiceTest.kt
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.monitoring
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -12,8 +32,8 @@ class ReportServiceTest {
@BeforeEach
fun setUp() {
- val jacksonConfig = JacksonConfig()
- service = ReportService(jacksonConfig.objectMapper())
+ val jackson3Config = JacksonConfig()
+ service = ReportService(jackson3Config.jsonMapper())
}
@Test
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
index ac14366..ee840a8 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,17 +20,12 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientPseudonym
import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.config.KafkaProperties
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.pcvolkmer.mv64e.mtb.*
-import java.time.Instant
-import java.util.*
-import java.util.concurrent.CompletableFuture.completedFuture
-import java.util.concurrent.ExecutionException
import org.apache.kafka.clients.producer.ProducerRecord
import org.apache.kafka.clients.producer.RecordMetadata
import org.apache.kafka.common.TopicPartition
@@ -47,6 +43,11 @@ import org.springframework.kafka.core.KafkaTemplate
import org.springframework.kafka.support.SendResult
import org.springframework.retry.policy.SimpleRetryPolicy
import org.springframework.retry.support.RetryTemplateBuilder
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
+import java.util.concurrent.CompletableFuture.completedFuture
+import java.util.concurrent.ExecutionException
@ExtendWith(MockitoExtension::class)
class KafkaMtbFileSenderTest {
@@ -58,18 +59,18 @@ class KafkaMtbFileSenderTest {
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(@Mock kafkaTemplate: KafkaTemplate<String, String>) {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper.builder().build()
this.kafkaTemplate = kafkaTemplate
this.kafkaMtbFileSender =
- KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
+ KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, jsonMapper)
}
@ParameterizedTest
@@ -94,7 +95,7 @@ class KafkaMtbFileSenderTest {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.kafkaMtbFileSender =
- KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
+ KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.jsonMapper)
doAnswer {
if (null != testData.exception) {
@@ -126,18 +127,18 @@ class KafkaMtbFileSenderTest {
private lateinit var kafkaMtbFileSender: KafkaMtbFileSender
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(@Mock kafkaTemplate: KafkaTemplate<String, String>) {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
- this.objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
this.kafkaTemplate = kafkaTemplate
this.kafkaMtbFileSender =
- KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, objectMapper)
+ KafkaMtbFileSender(kafkaTemplate, kafkaProperties, retryTemplate, jsonMapper)
}
@ParameterizedTest
@@ -179,7 +180,7 @@ class KafkaMtbFileSenderTest {
.isEqualTo("POST".toByteArray())
assertThat(captor.firstValue.value()).isNotNull
assertThat(captor.firstValue.value())
- .isEqualTo(objectMapper.writeValueAsString(dnmpV2kafkaRecordData(TEST_REQUEST_ID)))
+ .isEqualTo(jsonMapper.writeValueAsString(dnmpV2kafkaRecordData(TEST_REQUEST_ID)))
}
@Test
@@ -212,7 +213,7 @@ class KafkaMtbFileSenderTest {
val kafkaProperties = KafkaProperties("testtopic")
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.kafkaMtbFileSender =
- KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.objectMapper)
+ KafkaMtbFileSender(this.kafkaTemplate, kafkaProperties, retryTemplate, this.jsonMapper)
doAnswer {
if (null != testData.exception) {
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
index 2ab0218..d95ced0 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.output
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientPseudonym
import dev.dnpm.etl.processor.RequestId
@@ -30,8 +29,6 @@ import dev.dnpm.etl.processor.config.RestTargetProperties
import dev.dnpm.etl.processor.monitoring.ReportService
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.pcvolkmer.mv64e.mtb.*
-import java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
@@ -48,252 +45,255 @@ import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
import org.springframework.web.client.RestTemplate
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
class RestDipMtbFileSenderTest {
- @Nested
- inner class DnpmV2ContentRequest {
-
- private lateinit var mockRestServiceServer: MockRestServiceServer
-
- private lateinit var restMtbFileSender: RestMtbFileSender
-
- private var reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
-
- @BeforeEach
- fun setup() {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
-
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
-
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
- }
+ @Nested
+ inner class DnpmV2ContentRequest {
+
+ private lateinit var mockRestServiceServer: MockRestServiceServer
+
+ private lateinit var restMtbFileSender: RestMtbFileSender
+
+ private var reportService =
+ ReportService(JsonMapper())
+
+ @BeforeEach
+ fun setup() {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#mtbFileRequestWithResponseSource"
+ )
+ fun shouldReturnExpectedResponseForDnpmV2MtbFilePost(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
+ .andExpect(
+ header(
+ HttpHeaders.CONTENT_TYPE,
+ CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE,
+ )
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#mtbFileRequestWithResponseSource"
- )
- fun shouldReturnExpectedResponseForDnpmV2MtbFilePost(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer
- .expect(method(HttpMethod.POST))
- .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
- .andExpect(
- header(
- HttpHeaders.CONTENT_TYPE,
- CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE,
- )
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ val response = restMtbFileSender.send(DnpmV2MtbFileRequest(TEST_REQUEST_ID, dnpmV2MtbFile()))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
}
- }
-
- @Nested
- inner class DeleteRequest {
- private lateinit var mockRestServiceServer: MockRestServiceServer
-
- private lateinit var restMtbFileSender: RestMtbFileSender
-
- private var reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
-
- @BeforeEach
- fun setup() {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+ @Nested
+ inner class DeleteRequest {
+
+ private lateinit var mockRestServiceServer: MockRestServiceServer
+
+ private lateinit var restMtbFileSender: RestMtbFileSender
+
+ private var reportService =
+ ReportService(JsonMapper())
+
+ @BeforeEach
+ fun setup() {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
+ )
+ fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.DELETE))
+ .andExpect(
+ requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ @ParameterizedTest
+ @MethodSource(
+ "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
+ )
+ fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
+ val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties())
+ retryTemplate.setBackOffPolicy(NoBackOffPolicy())
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ this.restMtbFileSender =
+ RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
+
+ val expectedCount =
+ when (requestWithResponse.httpStatus) {
+ // OK - No Retry
+ HttpStatus.OK,
+ HttpStatus.CREATED,
+ HttpStatus.UNPROCESSABLE_ENTITY,
+ HttpStatus.BAD_REQUEST -> ExpectedCount.max(1)
+ // Request failed - Retry max 3 times
+ else -> ExpectedCount.max(3)
+ }
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
- }
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.DELETE))
+ .andExpect(
+ requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
+ )
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus)
+ .body(requestWithResponse.body)
+ .createResponse(it)
+ }
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
- )
- fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer
- .expect(method(HttpMethod.DELETE))
- .andExpect(
- requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
}
- @ParameterizedTest
- @MethodSource(
- "dev.dnpm.etl.processor.output.RestDipMtbFileSenderTest#deleteRequestWithResponseSource"
- )
- fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
- val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null)
- val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties())
- retryTemplate.setBackOffPolicy(NoBackOffPolicy())
-
- this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
- this.restMtbFileSender =
- RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate, reportService)
-
- val expectedCount =
- when (requestWithResponse.httpStatus) {
- // OK - No Retry
- HttpStatus.OK,
- HttpStatus.CREATED,
- HttpStatus.UNPROCESSABLE_ENTITY,
- HttpStatus.BAD_REQUEST -> ExpectedCount.max(1)
- // Request failed - Retry max 3 times
- else -> ExpectedCount.max(3)
- }
-
- this.mockRestServiceServer
- .expect(expectedCount, method(HttpMethod.DELETE))
- .andExpect(
- requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}")
- )
- .andRespond {
- withStatus(requestWithResponse.httpStatus)
- .body(requestWithResponse.body)
- .createResponse(it)
- }
-
- val response = restMtbFileSender.send(DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
- assertThat(response.status).isEqualTo(requestWithResponse.response.status)
- assertThat(response.body).isEqualTo(requestWithResponse.response.body)
- }
- }
-
- companion object {
- data class RequestWithResponse(
- val httpStatus: HttpStatus,
- val body: String,
- val response: MtbFileSender.Response,
- )
-
- val TEST_REQUEST_ID = RequestId("TestId")
- val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
-
- fun dnpmV2MtbFile(): Mtb {
- return Mtb().apply {
- this.patient =
- dev.pcvolkmer.mv64e.mtb.Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ companion object {
+ data class RequestWithResponse(
+ val httpStatus: HttpStatus,
+ val body: String,
+ val response: MtbFileSender.Response,
+ )
+
+ val TEST_REQUEST_ID = RequestId("TestId")
+ val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
+
+ fun dnpmV2MtbFile(): Mtb {
+ return Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "1"
+ this.patient = Reference().apply { this.id = "PID" }
+ this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
+ }
+ )
}
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "1"
- this.patient = Reference().apply { this.id = "PID" }
- this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
- }
+ }
+
+ private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
+
+ /**
+ * Synthetic http responses with related request status Also see:
+ * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun mtbFileRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(
+ HttpStatus.OK,
+ responseBodyWithMaxSeverity(ReportService.Severity.INFO),
+ MtbFileSender.Response(
+ RequestStatus.SUCCESS,
+ responseBodyWithMaxSeverity(ReportService.Severity.INFO),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.CREATED,
+ responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
+ MtbFileSender.Response(
+ RequestStatus.WARNING,
+ responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.BAD_REQUEST,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ MtbFileSender.Response(
+ RequestStatus.ERROR,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ ),
+ ),
+ RequestWithResponse(
+ HttpStatus.UNPROCESSABLE_ENTITY,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ MtbFileSender.Response(
+ RequestStatus.ERROR,
+ responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
+ ),
+ ),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
)
- }
- }
-
- private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
-
- /**
- * Synthetic http responses with related request status Also see:
- * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
- */
- @JvmStatic
- fun mtbFileRequestWithResponseSource(): Set<RequestWithResponse> {
- return setOf(
- RequestWithResponse(
- HttpStatus.OK,
- responseBodyWithMaxSeverity(ReportService.Severity.INFO),
- MtbFileSender.Response(
- RequestStatus.SUCCESS,
- responseBodyWithMaxSeverity(ReportService.Severity.INFO),
- ),
- ),
- RequestWithResponse(
- HttpStatus.CREATED,
- responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
- MtbFileSender.Response(
- RequestStatus.WARNING,
- responseBodyWithMaxSeverity(ReportService.Severity.WARNING),
- ),
- ),
- RequestWithResponse(
- HttpStatus.BAD_REQUEST,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- MtbFileSender.Response(
- RequestStatus.ERROR,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- ),
- ),
- RequestWithResponse(
- HttpStatus.UNPROCESSABLE_ENTITY,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- MtbFileSender.Response(
- RequestStatus.ERROR,
- responseBodyWithMaxSeverity(ReportService.Severity.ERROR),
- ),
- ),
- // Some more errors not mentioned in documentation
- RequestWithResponse(
- HttpStatus.NOT_FOUND,
- ERROR_RESPONSE_BODY,
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- RequestWithResponse(
- HttpStatus.INTERNAL_SERVER_ERROR,
- ERROR_RESPONSE_BODY,
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- )
- }
-
- /**
- * Synthetic http responses with related request status Also see:
- * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
- */
- @JvmStatic
- fun deleteRequestWithResponseSource(): Set<RequestWithResponse> {
- return setOf(
- RequestWithResponse(HttpStatus.OK, "", MtbFileSender.Response(RequestStatus.SUCCESS)),
- // Some more errors not mentioned in documentation
- RequestWithResponse(
- HttpStatus.NOT_FOUND,
- "what????",
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- RequestWithResponse(
- HttpStatus.INTERNAL_SERVER_ERROR,
- "what????",
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
- ),
- )
- }
+ }
+
+ /**
+ * Synthetic http responses with related request status Also see:
+ * https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun deleteRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(HttpStatus.OK, "", MtbFileSender.Response(RequestStatus.SUCCESS)),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY),
+ ),
+ )
+ }
- fun responseBodyWithMaxSeverity(severity: ReportService.Severity): String {
- return when (severity) {
- ReportService.Severity.INFO ->
- """
+ fun responseBodyWithMaxSeverity(severity: ReportService.Severity): String {
+ return when (severity) {
+ ReportService.Severity.INFO ->
+ """
{
"patient": "PID",
"issues": [
@@ -302,8 +302,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.WARNING ->
- """
+ ReportService.Severity.WARNING ->
+ """
{
"patient": "PID",
"issues": [
@@ -313,8 +313,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.ERROR ->
- """
+ ReportService.Severity.ERROR ->
+ """
{
"patient": "PID",
"issues": [
@@ -325,8 +325,8 @@ class RestDipMtbFileSenderTest {
}
"""
- ReportService.Severity.FATAL ->
- """
+ ReportService.Severity.FATAL ->
+ """
{
"patient": "PID",
"issues": [
@@ -337,7 +337,7 @@ class RestDipMtbFileSenderTest {
]
}
"""
- }
+ }
+ }
}
- }
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
index 84b081a..abc17c6 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2025-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -20,7 +21,6 @@
package dev.dnpm.etl.processor.pseudonym
import ca.uhn.fhir.context.FhirContext
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -28,8 +28,6 @@ import dev.dnpm.etl.processor.consent.MtbFileConsentService
import dev.dnpm.etl.processor.services.ConsentProcessor
import dev.dnpm.etl.processor.services.ConsentProcessorTest
import dev.pcvolkmer.mv64e.mtb.*
-import java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.hl7.fhir.r4.model.Bundle
import org.junit.jupiter.api.Nested
@@ -42,253 +40,256 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
+import tools.jackson.databind.json.JsonMapper
+import java.time.Instant
+import java.util.*
@ExtendWith(MockitoExtension::class)
class ExtensionsTest {
- fun getObjectMapper(): ObjectMapper {
- return JacksonConfig().objectMapper()
- }
+ fun getJsonMapper(): JsonMapper {
+ return JacksonConfig().jsonMapper()
+ }
- @Nested
- inner class UsingDnpmV2Datamodel {
+ @Nested
+ inner class UsingDnpmV2Datamodel {
- val FAKE_MTB_FILE_PATH = "mv64e-mtb-fake-patient.json"
- val CLEAN_PATIENT_ID = "644bae7a-56f6-4ee8-b02f-c532e65af5b1"
+ val FAKE_MTB_FILE_PATH = "mv64e-mtb-fake-patient.json"
+ val CLEAN_PATIENT_ID = "644bae7a-56f6-4ee8-b02f-c532e65af5b1"
- private fun fakeMtbFile(): Mtb {
- val mtbFile = ClassPathResource(FAKE_MTB_FILE_PATH).inputStream
- return getObjectMapper().readValue(mtbFile, Mtb::class.java)
- }
+ private fun fakeMtbFile(): Mtb {
+ val mtbFile = ClassPathResource(FAKE_MTB_FILE_PATH).inputStream
+ return getJsonMapper().readValue(mtbFile, Mtb::class.java)
+ }
- private fun Mtb.serialized(): String {
- return getObjectMapper().writeValueAsString(this)
- }
+ private fun Mtb.serialized(): String {
+ return getJsonMapper().writeValueAsString(this)
+ }
- @Test
- fun shouldNotContainCleanPatientId(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
+ @Test
+ fun shouldNotContainCleanPatientId(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- val mtbFile = fakeMtbFile()
- mtbFile.ensureMetaDataIsInitialized()
- addConsentData(mtbFile)
+ val mtbFile = fakeMtbFile()
+ mtbFile.ensureMetaDataIsInitialized()
+ addConsentData(mtbFile)
- mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.pseudonymizeWith(pseudonymizeService)
- assertThat(mtbFile.patient.id).isEqualTo("PSEUDO-ID")
- assertThat(mtbFile.serialized()).doesNotContain(CLEAN_PATIENT_ID)
- }
+ assertThat(mtbFile.patient.id).isEqualTo("PSEUDO-ID")
+ assertThat(mtbFile.serialized()).doesNotContain(CLEAN_PATIENT_ID)
+ }
- private fun addConsentData(mtbFile: Mtb) {
- val gIcsConfigProperties = GIcsConfigProperties("", "", "")
- val appConfigProperties = AppConfigProperties(emptyList())
-
- val bundle = Bundle()
- val dummyConsent = ConsentProcessorTest.getDummyGenomDeConsent()
- dummyConsent.patient.reference = "Patient/$CLEAN_PATIENT_ID"
- bundle.addEntry().resource = dummyConsent
-
- ConsentProcessor(
- appConfigProperties,
- gIcsConfigProperties,
- JacksonConfig().objectMapper(),
- FhirContext.forR4(),
- MtbFileConsentService(),
- )
- .embedBroadConsentResources(mtbFile, bundle)
- }
+ private fun addConsentData(mtbFile: Mtb) {
+ val gIcsConfigProperties = GIcsConfigProperties("", "", "")
+ val appConfigProperties = AppConfigProperties(emptyList())
+
+ val bundle = Bundle()
+ val dummyConsent = ConsentProcessorTest.getDummyGenomDeConsent()
+ dummyConsent.patient.reference = "Patient/$CLEAN_PATIENT_ID"
+ bundle.addEntry().resource = dummyConsent
+
+ ConsentProcessor(
+ appConfigProperties,
+ gIcsConfigProperties,
+ JacksonConfig().jsonMapper(),
+ FhirContext.forR4(),
+ MtbFileConsentService(),
+ )
+ .embedBroadConsentResources(mtbFile, bundle)
+ }
- @Test
- fun shouldNotThrowExceptionOnNullValues(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ @Test
+ fun shouldNotThrowExceptionOnNullValues(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "1"
+ this.patient = Reference().apply { this.id = "PID" }
+ this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
+ }
+ )
}
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "1"
- this.patient = Reference().apply { this.id = "PID" }
- this.period = PeriodDate().apply { this.start = Date.from(Instant.now()) }
- }
- )
- }
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
- assertThat(mtbFile.episodesOfCare).hasSize(1)
- assertThat(mtbFile.episodesOfCare.map { it.id }).isNotNull
- }
+ assertThat(mtbFile.episodesOfCare).hasSize(1)
+ assertThat(mtbFile.episodesOfCare.map { it.id }).isNotNull
+ }
- @Test
- fun shouldNotContainAnyUuidAfterRehashingOfIds(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
+ @Test
+ fun shouldNotContainAnyUuidAfterRehashingOfIds(@Mock pseudonymizeService: PseudonymizeService) {
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
+ }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
- val mtbFile = fakeMtbFile()
+ val mtbFile = fakeMtbFile()
- /** replace hex values with random long, so our test does not match false positives */
- mtbFile.ngsReports.forEach { report ->
- report.results.simpleVariants.forEach { simpleVariant ->
- simpleVariant.externalIds.forEach { extIdValue ->
- extIdValue.value = Math.random().toLong().toString()
- }
- }
- }
- mtbFile.ngsReports.forEach { report ->
- report.results.rnaFusions.forEach { simpleVariant ->
- simpleVariant.externalIds.forEach { extIdValue ->
- extIdValue.value = Math.random().toLong().toString()
- }
- simpleVariant.fusionPartner3Prime?.transcriptId?.value = Math.random().toLong().toString()
- simpleVariant.fusionPartner5Prime?.transcriptId?.value = Math.random().toLong().toString()
- simpleVariant.externalIds?.forEach { it?.value = Math.random().toLong().toString() }
+ /** replace hex values with random long, so our test does not match false positives */
+ mtbFile.ngsReports.forEach { report ->
+ report.results.simpleVariants.forEach { simpleVariant ->
+ simpleVariant.externalIds.forEach { extIdValue ->
+ extIdValue.value = Math.random().toLong().toString()
+ }
+ }
+ }
+ mtbFile.ngsReports.forEach { report ->
+ report.results.rnaFusions.forEach { simpleVariant ->
+ simpleVariant.externalIds.forEach { extIdValue ->
+ extIdValue.value = Math.random().toLong().toString()
+ }
+ simpleVariant.fusionPartner3Prime?.transcriptId?.value = Math.random().toLong().toString()
+ simpleVariant.fusionPartner5Prime?.transcriptId?.value = Math.random().toLong().toString()
+ simpleVariant.externalIds?.forEach { it?.value = Math.random().toLong().toString() }
+ }
+ }
+
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
+
+ val pattern =
+ "\"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\"".toRegex().toPattern()
+ val input = mtbFile.serialized()
+ val matcher = pattern.matcher(input)
+
+ assertThrows<IllegalStateException> {
+ matcher.find()
+ val posSt = "check at pos: " + matcher.start().toString() + ", " + matcher.end()
+ println(posSt + " with " + matcher.group())
+ }
+ .also { assertThat(it.message).isEqualTo("No match found") }
}
- }
-
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
-
- val pattern =
- "\"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\"".toRegex().toPattern()
- val input = mtbFile.serialized()
- val matcher = pattern.matcher(input)
-
- assertThrows<IllegalStateException> {
- matcher.find()
- val posSt = "check at pos: " + matcher.start().toString() + ", " + matcher.end()
- println(posSt + " with " + matcher.group())
- }
- .also { assertThat(it.message).isEqualTo("No match found") }
}
- }
- @Test
- fun shouldUseSameAnonymIdForDiagnosisAndDiagnosisReferences(
- @Mock pseudonymizeService: PseudonymizeService
- ) {
+ @Test
+ fun shouldUseSameAnonymIdForDiagnosisAndDiagnosisReferences(
+ @Mock pseudonymizeService: PseudonymizeService
+ ) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
- }
- this.diagnoses = listOf(MtbDiagnosis().apply { this.id = "Diagnosis-1" })
- this.episodesOfCare =
- listOf(
- MtbEpisodeOfCare().apply {
- this.id = "Episode-1"
- this.diagnoses = listOf(Reference().apply { this.id = "Diagnosis-1" })
- }
- )
- this.guidelineTherapies =
- listOf(
- MtbSystemicTherapy().apply {
- this.id = "Systemic-Therapy-1"
- this.reason = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
- this.guidelineProcedures =
- listOf(
- OncoProcedure().apply {
- this.id = "Onco-Procedure-1"
- this.reason = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
- this.specimens =
- listOf(
- TumorSpecimen().apply {
- this.id = "Specimen-1"
- this.diagnosis = Reference().apply { this.id = "Diagnosis-1" }
- }
- )
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
}
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.diagnoses = listOf(MtbDiagnosis().apply { this.id = "Diagnosis-1" })
+ this.episodesOfCare =
+ listOf(
+ MtbEpisodeOfCare().apply {
+ this.id = "Episode-1"
+ this.diagnoses = listOf(Reference().apply { this.id = "Diagnosis-1" })
+ }
+ )
+ this.guidelineTherapies =
+ listOf(
+ MtbSystemicTherapy().apply {
+ this.id = "Systemic-Therapy-1"
+ this.reason = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ this.guidelineProcedures =
+ listOf(
+ OncoProcedure().apply {
+ this.id = "Onco-Procedure-1"
+ this.reason = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ this.specimens =
+ listOf(
+ TumorSpecimen().apply {
+ this.id = "Specimen-1"
+ this.diagnosis = Reference().apply { this.id = "Diagnosis-1" }
+ }
+ )
+ }
+
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
+
+ assertThat(mtbFile.diagnoses.first().id)
+ .isEqualTo(mtbFile.episodesOfCare.first().diagnoses.first().id)
+ assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.guidelineTherapies.first().reason.id)
+ assertThat(mtbFile.diagnoses.first().id)
+ .isEqualTo(mtbFile.guidelineProcedures.first().reason.id)
+ assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.specimens.first().diagnosis.id)
+ }
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
-
- assertThat(mtbFile.diagnoses.first().id)
- .isEqualTo(mtbFile.episodesOfCare.first().diagnoses.first().id)
- assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.guidelineTherapies.first().reason.id)
- assertThat(mtbFile.diagnoses.first().id)
- .isEqualTo(mtbFile.guidelineProcedures.first().reason.id)
- assertThat(mtbFile.diagnoses.first().id).isEqualTo(mtbFile.specimens.first().diagnosis.id)
- }
-
- @Test
- fun shouldNotThrowAnyExceptionOnMissingMsiId(@Mock pseudonymizeService: PseudonymizeService) {
+ @Test
+ fun shouldNotThrowAnyExceptionOnMissingMsiId(@Mock pseudonymizeService: PseudonymizeService) {
- doAnswer {
- it.arguments[0]
- "PSEUDO-ID"
- }
- .whenever(pseudonymizeService)
- .patientPseudonym(anyValueClass())
-
- doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
-
- val mtbFile =
- Mtb().apply {
- this.patient =
- Patient().apply {
- this.id = "PID"
- this.birthDate = Date.from(Instant.now())
- this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
- }
- this.msiFindings =
- listOf(
- null,
- Msi.builder().id("1").build(),
- Msi.builder().build(),
- Msi.builder().specimen(null).build(),
- Msi.builder().specimen(Reference.builder().build()).build(),
- )
+ doAnswer {
+ it.arguments[0]
+ "PSEUDO-ID"
}
-
- mtbFile.pseudonymizeWith(pseudonymizeService)
- mtbFile.anonymizeContentWith(pseudonymizeService)
-
- assertThat(mtbFile.msiFindings).isNotNull
- assertThat(mtbFile.msiFindings[1])
- .satisfiesAnyOf(
- { assertThat(it.id).isNull() },
- { assertThat(it.id).isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098") },
- )
- }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "TESTDOMAIN" }.whenever(pseudonymizeService).prefix()
+
+ val mtbFile =
+ Mtb().apply {
+ this.patient =
+ Patient().apply {
+ this.id = "PID"
+ this.birthDate = Date.from(Instant.now())
+ this.gender = GenderCoding().apply { this.code = GenderCodingCode.MALE }
+ }
+ this.msiFindings =
+ listOf(
+ null,
+ Msi.builder().id("1").build(),
+ Msi.builder().build(),
+ Msi.builder().specimen(null).build(),
+ Msi.builder().specimen(Reference.builder().build()).build(),
+ )
+ }
+
+ mtbFile.pseudonymizeWith(pseudonymizeService)
+ mtbFile.anonymizeContentWith(pseudonymizeService)
+
+ assertThat(mtbFile.msiFindings).isNotNull
+ assertThat(mtbFile.msiFindings[1])
+ .satisfiesAnyOf(
+ { assertThat(it.id).isNull() },
+ { assertThat(it.id).isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098") },
+ )
+ }
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
index 7da0247..7c6d6c9 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
index e9a1650..18e0bb5 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
index 7743069..2a5a481 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2024-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
index 331a816..a85d555 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
@@ -1,7 +1,26 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package dev.dnpm.etl.processor.services
import ca.uhn.fhir.context.FhirContext
-import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.config.GIcsConfigProperties
import dev.dnpm.etl.processor.config.JacksonConfig
@@ -29,6 +48,7 @@ import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
+import tools.jackson.databind.json.JsonMapper
import java.io.IOException
import java.io.InputStream
import java.time.Instant
@@ -40,7 +60,7 @@ class ConsentProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var gicsConsentService: GicsConsentService
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var gIcsConfigProperties: GIcsConfigProperties
private lateinit var fhirContext: FhirContext
private lateinit var consentProcessor: ConsentProcessor
@@ -52,7 +72,7 @@ class ConsentProcessorTest {
this.gIcsConfigProperties = GIcsConfigProperties(uri = "https://gics.example.com", genomDeConsentDomainName = "GenomDE_MV")
val jacksonConfig = JacksonConfig()
- this.objectMapper = jacksonConfig.objectMapper()
+ this.jsonMapper = jacksonConfig.jsonMapper()
this.fhirContext = JacksonConfig.fhirContext()
this.gicsConsentService = gicsConsentService
this.appConfigProperties = AppConfigProperties(emptyList())
@@ -60,7 +80,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
gicsConsentService,
)
@@ -94,7 +114,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
MtbFileConsentService(),
)
@@ -220,7 +240,7 @@ class ConsentProcessorTest {
ConsentProcessor(
appConfigProperties,
gIcsConfigProperties,
- objectMapper,
+ jsonMapper,
fhirContext,
gicsConsentService,
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
index 4308fed..e9c3107 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ReportServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.services
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.monitoring.ReportService
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.monitoring.asRequestStatus
@@ -30,6 +29,8 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.module.kotlin.KotlinModule
class ReportServiceTest {
private lateinit var reportService: ReportService
@@ -37,7 +38,7 @@ class ReportServiceTest {
@BeforeEach
fun setup() {
this.reportService =
- ReportService(ObjectMapper().registerModule(KotlinModule.Builder().build()))
+ ReportService(JsonMapper.builder().addModule(KotlinModule.Builder().build()).build())
}
@Test
@@ -59,13 +60,34 @@ class ReportServiceTest {
assertThat(actual).hasSize(4)
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.FATAL)
- assertThat(actual[0].message).isEqualTo("Fatal Message")
+ assertThat(actual[0].getMessage()).isEqualTo("Fatal Message")
assertThat(actual[1].severity).isEqualTo(ReportService.Severity.ERROR)
- assertThat(actual[1].message).isEqualTo("Error Message")
+ assertThat(actual[1].getMessage()).isEqualTo("Error Message")
assertThat(actual[2].severity).isEqualTo(ReportService.Severity.WARNING)
- assertThat(actual[2].message).isEqualTo("Warning Message")
+ assertThat(actual[2].getMessage()).isEqualTo("Warning Message")
assertThat(actual[3].severity).isEqualTo(ReportService.Severity.INFO)
- assertThat(actual[3].message).isEqualTo("Info Message")
+ assertThat(actual[3].getMessage()).isEqualTo("Info Message")
+
+ assertThat(actual.asRequestStatus()).isEqualTo(RequestStatus.ERROR)
+ }
+
+ @Test
+ fun shouldParseDataQualityReportWithMissingPathError() {
+ val json =
+ """
+ {
+ "patient": "4711",
+ "issues": [
+ { "severity": "error", "details": "/specimens(0)/type/code: error.path.missing" }
+ ]
+ }
+ """.trimIndent()
+
+ val actual = this.reportService.deserialize(json)
+
+ assertThat(actual).hasSize(1)
+ assertThat(actual[0].severity).isEqualTo(ReportService.Severity.ERROR)
+ assertThat(actual[0].getMessage()).isEqualTo("/specimens(0)/type/code: error.path.missing")
assertThat(actual.asRequestStatus()).isEqualTo(RequestStatus.ERROR)
}
@@ -88,7 +110,7 @@ class ReportServiceTest {
assertThat(actual).hasSize(1)
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.ERROR)
- assertThat(actual[0].message).isEqualTo("Not parsable data quality report '$invalidResponse'")
+ assertThat(actual[0].getMessage()).isEqualTo("Not parsable data quality report '$invalidResponse'")
}
companion object {
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
index b51aed2..5a89c03 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -34,6 +35,7 @@ import dev.dnpm.etl.processor.output.RestMtbFileSender
import dev.dnpm.etl.processor.pseudonym.PseudonymizeService
import dev.pcvolkmer.mv64e.mtb.*
import org.assertj.core.api.Assertions.assertThat
+import org.hl7.fhir.r4.model.Consent
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
@@ -46,6 +48,7 @@ import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.whenever
import org.springframework.context.ApplicationEventPublisher
+import tools.jackson.databind.json.JsonMapper
import java.time.Instant
import java.util.*
@@ -60,6 +63,7 @@ class RequestProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var consentProcessor: ConsentProcessor
private lateinit var requestProcessor: RequestProcessor
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(
@@ -77,8 +81,7 @@ class RequestProcessorTest {
this.applicationEventPublisher = applicationEventPublisher
this.appConfigProperties = AppConfigProperties()
this.consentProcessor = consentProcessor
-
- val objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
requestProcessor =
RequestProcessor(
@@ -86,7 +89,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- objectMapper,
+ jsonMapper,
applicationEventPublisher,
appConfigProperties,
consentProcessor,
@@ -101,7 +104,7 @@ class RequestProcessorTest {
randomRequestId(),
PatientPseudonym("TEST_12345678901"),
PatientId("P1"),
- Fingerprint("6vkiti5bk6ikwifpajpt7cygmd3dvw54d6lwfhzlynb3pqtzferq"),
+ Fingerprint("syehahte4oyqd5m2rbd5imnth4rx6md32g2msb7sztnayxoc4kaq"),
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
@@ -158,7 +161,7 @@ class RequestProcessorTest {
randomRequestId(),
PatientPseudonym("TEST_12345678901"),
PatientId("P1"),
- Fingerprint("4gcjwtjjtcczybsljxepdfpkaeusvd7g3vogfqpmphyffyzfx7dq"),
+ Fingerprint("me6ockoru4boi4ypghfia5myfqtuffwlbszwhtop2rtltb3ycjva"),
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
@@ -413,7 +416,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -637,7 +640,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -681,6 +684,7 @@ class RequestProcessorTest {
private lateinit var appConfigProperties: AppConfigProperties
private lateinit var consentProcessor: ConsentProcessor
private lateinit var requestProcessor: RequestProcessor
+ private lateinit var jsonMapper: JsonMapper
@BeforeEach
fun setup(
@@ -698,8 +702,7 @@ class RequestProcessorTest {
this.applicationEventPublisher = applicationEventPublisher
this.appConfigProperties = AppConfigProperties()
this.consentProcessor = consentProcessor
-
- val objectMapper = ObjectMapper()
+ this.jsonMapper = JsonMapper()
requestProcessor =
RequestProcessor(
@@ -707,7 +710,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- objectMapper,
+ jsonMapper,
applicationEventPublisher,
appConfigProperties,
consentProcessor,
@@ -779,7 +782,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -883,7 +886,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -994,7 +997,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
@@ -1092,7 +1095,7 @@ class RequestProcessorTest {
transformationService,
sender,
requestService,
- ObjectMapper(),
+ jsonMapper,
applicationEventPublisher,
AppConfigProperties(postInitialSubmissionBlock = true),
consentProcessor,
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
index 9b103ba..54b4dce 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
index 3b09cc7..441f3a9 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
index 3af5097..66e45f8 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/TransformationServiceTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -24,11 +25,11 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
import dev.dnpm.etl.processor.config.JacksonConfig
import dev.pcvolkmer.mv64e.mtb.*
-import java.time.Instant
-import java.util.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
+import java.time.Instant
+import java.util.*
class TransformationServiceTest {
@@ -38,7 +39,7 @@ class TransformationServiceTest {
fun setup() {
this.service =
TransformationService(
- JacksonConfig().objectMapper(),
+ JacksonConfig().jsonMapper(),
listOf(
Transformation.of("diagnoses[*].code.version") from "2013" to "2014",
),
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
index 8d5024a..96c9a82 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/kafka/KafkaResponseProcessorTest.kt
@@ -1,7 +1,8 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -19,8 +20,6 @@
package dev.dnpm.etl.processor.services.kafka
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.dnpm.etl.processor.services.ResponseEvent
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.junit.jupiter.api.BeforeEach
@@ -36,11 +35,13 @@ import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.springframework.context.ApplicationEventPublisher
import org.springframework.http.HttpStatus
+import tools.jackson.databind.json.JsonMapper
+import tools.jackson.module.kotlin.KotlinModule
@ExtendWith(MockitoExtension::class)
class KafkaResponseProcessorTest {
private lateinit var eventPublisher: ApplicationEventPublisher
- private lateinit var objectMapper: ObjectMapper
+ private lateinit var jsonMapper: JsonMapper
private lateinit var kafkaResponseProcessor: KafkaResponseProcessor
@@ -57,7 +58,7 @@ class KafkaResponseProcessorTest {
if (statusBody == null) {
""
} else {
- this.objectMapper.writeValueAsString(
+ this.jsonMapper.writeValueAsString(
KafkaResponseProcessor.ResponseBody(requestId, statusCode, statusBody),
)
},
@@ -68,9 +69,9 @@ class KafkaResponseProcessorTest {
@Mock eventPublisher: ApplicationEventPublisher,
) {
this.eventPublisher = eventPublisher
- this.objectMapper = ObjectMapper().registerModule(KotlinModule.Builder().build())
+ this.jsonMapper = JsonMapper.builder().addModule(KotlinModule.Builder().build()).build()
- this.kafkaResponseProcessor = KafkaResponseProcessor(eventPublisher, objectMapper)
+ this.kafkaResponseProcessor = KafkaResponseProcessor(eventPublisher, jsonMapper)
}
@Test