diff --git a/codex-process-data-transfer/pom.xml b/codex-process-data-transfer/pom.xml
index 364a6523..efd17551 100644
--- a/codex-process-data-transfer/pom.xml
+++ b/codex-process-data-transfer/pom.xml
@@ -65,6 +65,17 @@
mockito-core
test
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
+
+ org.springframework
+ spring-test
+ 6.0.11
+ test
+
org.apache.logging.log4j
log4j-slf4j2-impl
@@ -102,7 +113,7 @@
false
-
+
@@ -263,4 +274,4 @@
-
\ No newline at end of file
+
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java
index c6bd6309..0a6cc660 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/ConstantsDataTransfer.java
@@ -43,6 +43,7 @@ public interface ConstantsDataTransfer
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_EXPORT_TO = "export-to";
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DATA_REFERENCE = "data-reference";
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_DRY_RUN = "dry-run";
+ String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID = "study-id";
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_ENCRYPTED_BUNDLE_SIZE = "encrypted-bundle-size";
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_LOCAL_VALIDATION_SUCCESSFUL = "local-validation-successful";
String CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_ENCRYPTED_BUNDLE_RESOURCES_COUNT = "encrypted-bundle-resources-count";
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java
index 85965d8c..f6b76bfa 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/DataTransferProcessPluginDefinition.java
@@ -5,14 +5,7 @@
import java.util.List;
import java.util.Map;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ProcessPluginDeploymentConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ReceiveConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.SendConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TransferDataConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TransferDataSerializerConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TranslateConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.TriggerConfig;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ValidationConfig;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.*;
import dev.dsf.bpe.v1.ProcessPluginDefinition;
public class DataTransferProcessPluginDefinition implements ProcessPluginDefinition
@@ -49,7 +42,7 @@ public List> getSpringConfigurations()
{
return List.of(TransferDataConfig.class, TransferDataSerializerConfig.class, ValidationConfig.class,
TriggerConfig.class, SendConfig.class, TranslateConfig.class, ReceiveConfig.class,
- ProcessPluginDeploymentConfig.class);
+ ReceiveDataStoreConfig.class, ProcessPluginDeploymentConfig.class);
}
@Override
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/DataStoreClientFactory.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/DataStoreClientFactory.java
index a2ebd6cb..5dfdb2ad 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/DataStoreClientFactory.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/DataStoreClientFactory.java
@@ -9,6 +9,7 @@
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.util.Map;
import java.util.UUID;
import org.bouncycastle.pkcs.PKCSException;
@@ -20,6 +21,7 @@
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.DataStoreFhirClient;
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.DataStoreFhirClientStub;
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.DataLogger;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config.ReceiveDataStoreConfig;
import de.rwh.utils.crypto.CertificateHelper;
import de.rwh.utils.crypto.io.CertificateReader;
import de.rwh.utils.crypto.io.PemIo;
@@ -27,6 +29,7 @@
public class DataStoreClientFactory
{
private static final Logger logger = LoggerFactory.getLogger(DataStoreClientFactory.class);
+ private static final String DEFAULT_DATA_STORE = "default";
private static final class DataStoreClientStub implements DataStoreClient
{
@@ -91,10 +94,7 @@ public boolean shouldUseChainedParameterNotLogicalReference()
private final int socketTimeout;
private final int connectionRequestTimeout;
- private final String dataStoreServerBase;
- private final String dataStoreServerBasicAuthUsername;
- private final String dataStoreServerBasicAuthPassword;
- private final String dataStoreServerBearerToken;
+ private final Map dataStoreConnectionMap;
private final String proxyUrl;
private final String proxyUsername;
@@ -112,7 +112,8 @@ public boolean shouldUseChainedParameterNotLogicalReference()
public DataStoreClientFactory(Path trustStorePath, Path certificatePath, Path privateKeyPath,
char[] privateKeyPassword, int connectTimeout, int socketTimeout, int connectionRequestTimeout,
String dataStoreServerBase, String dataStoreServerBasicAuthUsername,
- String dataStoreServerBasicAuthPassword, String dataStoreServerBearerToken, String proxyUrl,
+ String dataStoreServerBasicAuthPassword, String dataStoreServerBearerToken,
+ Map dataStoreConnectionMap, String proxyUrl,
String proxyUsername, String proxyPassword, boolean hapiClientVerbose, FhirContext fhirContext,
Path searchBundleOverride, Class dataStoreFhirClientClass,
boolean useChainedParameterNotLogicalReference, DataLogger dataLogger)
@@ -126,10 +127,11 @@ public DataStoreClientFactory(Path trustStorePath, Path certificatePath, Path pr
this.socketTimeout = socketTimeout;
this.connectionRequestTimeout = connectionRequestTimeout;
- this.dataStoreServerBase = dataStoreServerBase;
- this.dataStoreServerBasicAuthUsername = dataStoreServerBasicAuthUsername;
- this.dataStoreServerBasicAuthPassword = dataStoreServerBasicAuthPassword;
- this.dataStoreServerBearerToken = dataStoreServerBearerToken;
+ this.dataStoreConnectionMap = dataStoreConnectionMap;
+ this.dataStoreConnectionMap.put(DEFAULT_DATA_STORE,
+ new ReceiveDataStoreConfig.DataStoreConnectionValues(dataStoreServerBase,
+ dataStoreServerBasicAuthUsername, dataStoreServerBasicAuthPassword,
+ dataStoreServerBearerToken));
this.proxyUrl = proxyUrl;
this.proxyUsername = proxyUsername;
@@ -146,21 +148,25 @@ public DataStoreClientFactory(Path trustStorePath, Path certificatePath, Path pr
public String getServerBase()
{
- return dataStoreServerBase;
+ return dataStoreConnectionMap.get(DEFAULT_DATA_STORE).getBaseUrl();
}
public void testConnection()
{
try
{
- logger.info(
- "Testing connection to Data Store FHIR server with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {},"
- + " basicAuthUsername: {}, basicAuthPassword: {}, bearerToken: {}, serverBase: {}, proxy: values from 'DEV_DSF_PROXY'... config}",
- trustStorePath, certificatePath, privateKeyPath, privateKeyPassword != null ? "***" : "null",
- dataStoreServerBasicAuthUsername, dataStoreServerBasicAuthPassword != null ? "***" : "null",
- dataStoreServerBearerToken != null ? "***" : "null", dataStoreServerBase);
-
- getDataStoreClient().testConnection();
+ for (String client : dataStoreConnectionMap.keySet())
+ {
+ final ReceiveDataStoreConfig.DataStoreConnectionValues value = dataStoreConnectionMap.get(client);
+ logger.info(
+ "Testing connection to Data Store FHIR server with {trustStorePath: {}, certificatePath: {}, privateKeyPath: {}, privateKeyPassword: {},"
+ + " basicAuthUsername: {}, basicAuthPassword: {}, bearerToken: {}, serverBase: {}, proxy: values from 'DEV_DSF_PROXY'... config}",
+ trustStorePath, certificatePath, privateKeyPath, privateKeyPassword != null ? "***" : "null",
+ value.getBaseUrl(), value.getPassword() != null ? "***" : "null",
+ value.getBearerToken() != null ? "***" : "null", value.getUsername());
+
+ getDataStoreClient(client).testConnection();
+ }
}
catch (Exception e)
{
@@ -170,18 +176,29 @@ public void testConnection()
public DataStoreClient getDataStoreClient()
{
- if (configured())
- return createDataStoreClient();
+ return getDataStoreClient(DEFAULT_DATA_STORE);
+ }
+
+ public DataStoreClient getDataStoreClient(String client)
+ {
+ if (configured(client))
+ return createDataStoreClient(client);
else
return new DataStoreClientStub(fhirContext, dataLogger);
}
- private boolean configured()
+ private boolean configured(String client)
{
- return dataStoreServerBase != null && !dataStoreServerBase.isBlank();
+ return dataStoreConnectionMap.get(client).getBaseUrl() != null
+ && !dataStoreConnectionMap.get(client).getBaseUrl().isBlank();
}
protected DataStoreClient createDataStoreClient()
+ {
+ return createDataStoreClient(DEFAULT_DATA_STORE);
+ }
+
+ protected DataStoreClient createDataStoreClient(String dataStore)
{
KeyStore trustStore = null;
char[] keyStorePassword = null;
@@ -200,9 +217,11 @@ protected DataStoreClient createDataStoreClient()
keyStore = readKeyStore(certificatePath, privateKeyPath, privateKeyPassword, keyStorePassword);
}
+ final ReceiveDataStoreConfig.DataStoreConnectionValues dataStoreConfig = dataStoreConnectionMap.get(dataStore);
+
return new DataStoreClientImpl(trustStore, keyStore, keyStorePassword, connectTimeout, socketTimeout,
- connectionRequestTimeout, dataStoreServerBasicAuthUsername, dataStoreServerBasicAuthPassword,
- dataStoreServerBearerToken, dataStoreServerBase, proxyUrl, proxyUsername, proxyPassword,
+ connectionRequestTimeout, dataStoreConfig.getUsername(), dataStoreConfig.getPassword(),
+ dataStoreConfig.getBearerToken(), dataStoreConfig.getBaseUrl(), proxyUrl, proxyUsername, proxyPassword,
hapiClientVerbose, fhirContext, searchBundleOverride, dataStoreFhirClientClass,
useChainedParameterNotLogicalReference, dataLogger);
}
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java
index 064396d0..a86d6e52 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodex.java
@@ -1,14 +1,14 @@
package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive;
-import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_BUNDLE;
-import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS;
-import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_INSERT_INTO_CRR_FHIR_REPOSITORY_FAILED;
+import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.*;
import java.util.Objects;
+import java.util.Optional;
import org.camunda.bpm.engine.delegate.BpmnError;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,6 +18,7 @@
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.ContinueStatus;
import dev.dsf.bpe.v1.ProcessPluginApi;
import dev.dsf.bpe.v1.activity.AbstractServiceDelegate;
+import dev.dsf.bpe.v1.service.TaskHelper;
import dev.dsf.bpe.v1.variables.Variables;
public class InsertDataIntoCodex extends AbstractServiceDelegate
@@ -49,14 +50,21 @@ protected void doExecute(DelegateExecution execution, Variables variables) throw
{
Bundle bundle = variables.getResource(BPMN_EXECUTION_VARIABLE_BUNDLE);
+ String studyId = getStudyId(variables.getStartTask());
+ if (studyId == null || studyId.isEmpty())
+ {
+ logger.error("Unable to receive, {} is empty", CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID);
+ throw new IllegalArgumentException(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID + " is empty");
+ }
+
try
{
try
{
- logger.info("Executing bundle against FHIR store ...");
+ logger.info("Executing bundle against FHIR store '{}'", studyId);
dataLogger.logData("Received bundle", bundle);
- dataClientFactory.getDataStoreClient().getFhirClient().storeBundle(bundle);
+ dataClientFactory.getDataStoreClient(studyId).getFhirClient().storeBundle(bundle);
execution.setVariable(BPMN_EXECUTION_VARIABLE_CONTINUE_STATUS, ContinueStatus.SUCCESS);
}
@@ -69,9 +77,18 @@ protected void doExecute(DelegateExecution execution, Variables variables) throw
}
catch (Exception e)
{
- logger.warn("Unable to insert data into CRR: {} - {}", e.getClass().getName(), e.getMessage());
+ logger.warn("Unable to insert data into '{}': {} - {}", studyId, e.getClass().getName(), e.getMessage());
throw new BpmnError(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_ERROR_VALUE_INSERT_INTO_CRR_FHIR_REPOSITORY_FAILED,
- "Unable to insert data into CRR");
+ "Unable to insert data into '" + studyId + "'");
}
}
+
+ private String getStudyId(Task task)
+ {
+ TaskHelper taskHelper = this.api.getTaskHelper();
+ Optional studyId = taskHelper.getFirstInputParameterStringValue(task,
+ CODESYSTEM_NUM_CODEX_DATA_TRANSFER, CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID);
+
+ return studyId.orElse("");
+ }
}
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java
index 7f1311ec..af3b508e 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveConfig.java
@@ -9,15 +9,7 @@
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcess;
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcessWithError;
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.message.ContinueTranslateProcessWithValidationError;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DecryptData;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DeleteValidationErrorForDts;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.DownloadDataFromDts;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.EncryptValidationError;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.InsertDataIntoCodex;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogError;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogSuccess;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.LogValidationError;
-import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.StoreValidationErrorForDts;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive.*;
import dev.dsf.bpe.v1.ProcessPluginApi;
@Configuration
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfig.java
new file mode 100644
index 00000000..25cf555d
--- /dev/null
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfig.java
@@ -0,0 +1,110 @@
+package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import jakarta.annotation.PostConstruct;
+
+@Configuration
+@PropertySource(ignoreResourceNotFound = true, value = "file:process/rdp-application.properties")
+public class ReceiveDataStoreConfig
+{
+ private static final Logger logger = LoggerFactory.getLogger(ReceiveDataStoreConfig.class);
+ public static final String INVALID_CONFIG_MESSAGE = "Invalid Client Config map";
+ public static final String VALID_CONFIG_MESSAGE = "Client Config found: {}";
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Value("${dataStores:#{null}}")
+ private String dataStoresProperty;
+ private Map dataStoreConnectionConfigs = new HashMap<>();
+
+ @PostConstruct
+ protected void convertClientMap()
+ {
+ if (dataStoresProperty == null || dataStoresProperty.isEmpty())
+ {
+ return;
+ }
+
+ try
+ {
+ dataStoreConnectionConfigs = objectMapper.readValue(dataStoresProperty,
+ new TypeReference>()
+ {
+ });
+
+ logger.info(VALID_CONFIG_MESSAGE, dataStoreConnectionConfigs.keySet());
+ }
+ catch (JsonProcessingException e)
+ {
+ logger.error(INVALID_CONFIG_MESSAGE);
+ throw new IllegalArgumentException(INVALID_CONFIG_MESSAGE, e);
+ }
+ }
+
+ @Bean
+ public Map getDataStoreConnectionConfigs()
+ {
+ return dataStoreConnectionConfigs;
+ }
+
+ public static class DataStoreConnectionValues
+ {
+ private String baseUrl;
+ private String username;
+ private String password;
+ private String bearerToken;
+
+ public DataStoreConnectionValues()
+ {
+ }
+
+ public DataStoreConnectionValues(String baseUrl, String username, String password, String bearerToken)
+ {
+ this.baseUrl = baseUrl;
+ this.username = username;
+ this.password = password;
+ this.bearerToken = bearerToken;
+ }
+
+ public String getBaseUrl()
+ {
+ return baseUrl;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public String getBearerToken()
+ {
+ return bearerToken;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "RdpClientConfigValues{" + "baseUrl='" + baseUrl + '\'' + ", Username='" + username + '\'' + '}';
+ }
+ }
+}
diff --git a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java
index 6d6266e3..7e014613 100644
--- a/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java
+++ b/codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/TransferDataConfig.java
@@ -29,6 +29,9 @@ public class TransferDataConfig
@Autowired
private ProcessPluginApi api;
+ @Autowired
+ private ReceiveDataStoreConfig receiveDataStoreConfig;
+
@ProcessDocumentation(description = "PEM encoded file with trusted certificates to validate the server-certificate of the data FHIR server", processNames = {
"wwwnetzwerk-universitaetsmedizinde_dataSend",
"wwwnetzwerk-universitaetsmedizinde_dataReceive" }, recommendation = "Use docker secret file to configure", example = "/run/secrets/data_fhir_server_ca.pem")
@@ -318,9 +321,9 @@ public DataStoreClientFactory dataStoreClientFactory()
return new DataStoreClientFactory(trustStorePath, certificatePath, privateKeyPath,
fhirStorePrivateKeyPassword, fhirStoreConnectTimeout, fhirStoreSocketTimeout,
fhirStoreConnectionRequestTimeout, fhirStoreBaseUrl, fhirStoreUsername, fhirStorePassword,
- fhirStoreBearerToken, proxyUrl, proxyUsername, proxyPassword, fhirStoreHapiClientVerbose,
- api.getFhirContext(), searchBundleOverride,
- (Class) Class.forName(fhirStoreClientClass),
+ fhirStoreBearerToken, receiveDataStoreConfig.getDataStoreConnectionConfigs(), proxyUrl,
+ proxyUsername, proxyPassword, fhirStoreHapiClientVerbose, api.getFhirContext(),
+ searchBundleOverride, (Class) Class.forName(fhirStoreClientClass),
fhirStoreUseChainedParameterNotLogicalReference, dataLogger());
}
catch (ClassNotFoundException e)
diff --git a/codex-process-data-transfer/src/main/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml b/codex-process-data-transfer/src/main/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
index f011a571..40d12aa0 100644
--- a/codex-process-data-transfer/src/main/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
+++ b/codex-process-data-transfer/src/main/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
@@ -51,7 +51,7 @@
-
@@ -62,7 +62,7 @@
-
@@ -73,8 +73,8 @@
-
@@ -85,4 +85,14 @@
-
\ No newline at end of file
+
+
diff --git a/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodexTest.java b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodexTest.java
new file mode 100644
index 00000000..1c4ab7a2
--- /dev/null
+++ b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/service/receive/InsertDataIntoCodexTest.java
@@ -0,0 +1,95 @@
+package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.service.receive;
+
+import static de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.ConstantsDataTransfer.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.hl7.fhir.r4.model.*;
+import org.junit.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.DataStoreClient;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.DataStoreClientFactory;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.client.fhir.DataStoreFhirClient;
+import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.logging.DataLogger;
+import dev.dsf.bpe.v1.ProcessPluginApi;
+import dev.dsf.bpe.v1.service.TaskHelper;
+import dev.dsf.bpe.v1.variables.Variables;
+
+@ExtendWith(MockitoExtension.class)
+@RunWith(MockitoJUnitRunner.class)
+public class InsertDataIntoCodexTest
+{
+
+ @Test
+ public void testDoExecuteWithStudyId() throws Exception
+ {
+ ProcessPluginApi api = mock(ProcessPluginApi.class);
+ DataStoreClientFactory dataStoreClientFactory = mock(DataStoreClientFactory.class);
+ DataLogger dataLogger = mock(DataLogger.class);
+ InsertDataIntoCodex insertDataIntoCodex = new InsertDataIntoCodex(api, dataStoreClientFactory, dataLogger);
+
+ Variables variables = mock(Variables.class);
+ DelegateExecution execution = mock(DelegateExecution.class);
+ Bundle bundle = new Bundle();
+ when(api.getVariables(execution)).thenReturn(variables);
+ when(variables.getResource(BPMN_EXECUTION_VARIABLE_BUNDLE)).thenReturn(bundle);
+
+ Task task = createTask();
+ when(variables.getStartTask()).thenReturn(task);
+ TaskHelper taskHelper = mock(TaskHelper.class);
+ when(api.getTaskHelper()).thenReturn(taskHelper);
+
+ when(taskHelper.getFirstInputParameterStringValue(task, CODESYSTEM_NUM_CODEX_DATA_TRANSFER,
+ CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID)).thenReturn(Optional.of("dataStore"));
+
+ DataStoreClient dataStoreClient = mock(DataStoreClient.class);
+ DataStoreFhirClient fhirClient = mock(DataStoreFhirClient.class);
+ when(dataStoreClientFactory.getDataStoreClient("dataStore")).thenReturn(dataStoreClient);
+ when(dataStoreClient.getFhirClient()).thenReturn(fhirClient);
+
+ insertDataIntoCodex.execute(execution);
+
+ verify(dataStoreClientFactory, times(1)).getDataStoreClient("dataStore");
+ }
+
+ @Test
+ public void testDoExecuteWithoutStudyId() throws Exception
+ {
+ ProcessPluginApi api = mock(ProcessPluginApi.class);
+ DataStoreClientFactory dataStoreClientFactory = mock(DataStoreClientFactory.class);
+ DataLogger dataLogger = mock(DataLogger.class);
+ InsertDataIntoCodex insertDataIntoCodex = new InsertDataIntoCodex(api, dataStoreClientFactory, dataLogger);
+
+ Variables variables = mock(Variables.class);
+ DelegateExecution execution = mock(DelegateExecution.class);
+ Bundle bundle = new Bundle();
+ when(variables.getResource(BPMN_EXECUTION_VARIABLE_BUNDLE)).thenReturn(bundle);
+
+ Task task = createTask();
+ when(variables.getStartTask()).thenReturn(task);
+ TaskHelper taskHelper = mock(TaskHelper.class);
+ when(api.getTaskHelper()).thenReturn(taskHelper);
+
+ when(taskHelper.getFirstInputParameterStringValue(task, CODESYSTEM_NUM_CODEX_DATA_TRANSFER,
+ CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID)).thenReturn(Optional.of(""));
+
+ assertThrows(IllegalArgumentException.class, () -> insertDataIntoCodex.doExecute(execution, variables));
+ verify(dataStoreClientFactory, never());
+ }
+
+ private Task createTask()
+ {
+ Task task = new Task();
+ Coding code = new Coding();
+ code.setSystem(CODESYSTEM_NUM_CODEX_DATA_TRANSFER_VALUE_STUDY_ID);
+ task.addInput(new Task.ParameterComponent(new CodeableConcept(code), new StringType("study_id")));
+ return task;
+ }
+}
diff --git a/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfigTest.java b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfigTest.java
new file mode 100644
index 00000000..ec659502
--- /dev/null
+++ b/codex-process-data-transfer/src/test/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ReceiveDataStoreConfigTest.java
@@ -0,0 +1,80 @@
+package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.spring.config;
+
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
+import java.util.Properties;
+
+import org.junit.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+
+import junit.framework.TestCase;
+
+@ExtendWith(MockitoExtension.class)
+@RunWith(MockitoJUnitRunner.class)
+public class ReceiveDataStoreConfigTest extends TestCase
+{
+
+ public static final String VALID_PROPERTIES = "applicationProperties/valid-application.properties";
+ public static final String INVALID_PROPERTIES = "applicationProperties/invalid-application.properties";
+
+ @InjectMocks
+ private ReceiveDataStoreConfig receiveDataStoreConfig;
+
+ @Spy
+ private ObjectMapper objectMapper = JsonMapper.builder().serializationInclusion(JsonInclude.Include.NON_NULL)
+ .serializationInclusion(JsonInclude.Include.NON_EMPTY).disable(MapperFeature.AUTO_DETECT_CREATORS)
+ .disable(MapperFeature.AUTO_DETECT_FIELDS).disable(MapperFeature.AUTO_DETECT_SETTERS).build();
+
+ @Test
+ public void testConvertClientMapValidMap() throws IOException
+ {
+ String fileContent = readPropertyFile(VALID_PROPERTIES);
+
+ receiveDataStoreConfig.convertClientMap();
+ verify(objectMapper, times(1)).readValue(eq(fileContent), any(TypeReference.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testConvertClientMapInvalidMap() throws IOException
+ {
+ String fileContent = readPropertyFile(INVALID_PROPERTIES);
+
+ receiveDataStoreConfig.convertClientMap();
+ verify(objectMapper, times(1)).readValue(eq(fileContent), any(TypeReference.class));
+ }
+
+ @Test
+ public void testConvertClientMapWithoutMap() throws IOException
+ {
+ receiveDataStoreConfig.convertClientMap();
+ verify(objectMapper, never()).readValue(anyString(), any(TypeReference.class));
+ }
+
+ private String readPropertyFile(String resourcePath) throws IOException
+ {
+ Properties props = new Properties();
+
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ InputStream propsStream = Objects.requireNonNull(classLoader.getResourceAsStream(resourcePath));
+ props.load(propsStream);
+ propsStream.close();
+ String dataStores = (String) props.get("dataStores");
+ ReflectionTestUtils.setField(receiveDataStoreConfig, "dataStoresProperty", dataStores);
+ return dataStores;
+ }
+}
diff --git a/codex-process-data-transfer/src/test/resources/applicationProperties/invalid-application.properties b/codex-process-data-transfer/src/test/resources/applicationProperties/invalid-application.properties
new file mode 100644
index 00000000..049b6ca1
--- /dev/null
+++ b/codex-process-data-transfer/src/test/resources/applicationProperties/invalid-application.properties
@@ -0,0 +1,3 @@
+dataStores={\
+ "invalid"\
+}
diff --git a/codex-process-data-transfer/src/test/resources/applicationProperties/valid-application.properties b/codex-process-data-transfer/src/test/resources/applicationProperties/valid-application.properties
new file mode 100644
index 00000000..7980cec2
--- /dev/null
+++ b/codex-process-data-transfer/src/test/resources/applicationProperties/valid-application.properties
@@ -0,0 +1,8 @@
+dataStores={\
+ "validDataStore": {\
+ "baseUrl": "http://fhir-store:8080/fhir",\
+ "username": "user",\
+ "password": "strongPassword1",\
+ "bearerToken": "valid123"\
+ }\
+}
diff --git a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithAbsoluteReference.xml b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithAbsoluteReference.xml
index 325c15e3..16121807 100644
--- a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithAbsoluteReference.xml
+++ b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithAbsoluteReference.xml
@@ -1,8 +1,8 @@
-
+
-
+
@@ -44,8 +44,8 @@
-
@@ -56,8 +56,8 @@
-
-
\ No newline at end of file
+
diff --git a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
index 6f57fd86..0cde2d33 100644
--- a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
+++ b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataSendWithIdentifierReference.xml
@@ -1,8 +1,8 @@
-
+
-
+
@@ -32,7 +32,7 @@
@@ -49,8 +49,8 @@
-
@@ -61,8 +61,8 @@
-
-
\ No newline at end of file
+
+
diff --git a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataTrigger.xml b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataTrigger.xml
index 9255df41..8cf13dc7 100644
--- a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataTrigger.xml
+++ b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStartDataTrigger.xml
@@ -1,8 +1,8 @@
-
+
-
+
@@ -31,7 +31,7 @@
-
-
\ No newline at end of file
+
diff --git a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStopDataTrigger.xml b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStopDataTrigger.xml
index a2311792..8dce74be 100644
--- a/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStopDataTrigger.xml
+++ b/codex-process-data-transfer/src/test/resources/fhir/Task/TaskStopDataTrigger.xml
@@ -1,8 +1,8 @@
-
+
-
+
diff --git a/codex-processes-ap1-docker-test-setup/README.md b/codex-processes-ap1-docker-test-setup/README.md
index 2b177e28..96301f94 100644
--- a/codex-processes-ap1-docker-test-setup/README.md
+++ b/codex-processes-ap1-docker-test-setup/README.md
@@ -9,53 +9,58 @@ mvn clean package
Add entries to your hosts file
```
127.0.0.1 dic
-127.0.0.1 gth
+127.0.0.1 dts
127.0.0.1 crr
```
-*Start docker-compose commands from sub-folder:* `codex-processes-ap1/codex-processes-ap1-docker-test-setup`
+*Start docker compose commands from sub-folder:* `codex-processes-ap1/codex-processes-ap1-docker-test-setup`
Console 1: Start DIC HAPI FHIR Server or DIC blaze FHIR Server
```sh
-docker-compose up dic-fhir-store-hapi
-docker-compose up dic-fhir-store-blaze
+docker compose up dic-fhir-store-hapi
+docker compose up dic-fhir-store-blaze
```
Access at http://localhost:8080/fhir/
Console 2: Start CRR fhir-bridge server
```sh
-docker-compose up crr-fhir-bridge
+docker compose up crr-fhir-bridge
```
Access at http://localhost:8888/fhir-bridge/fhir/
Console 3: Start DIC DSF FHIR Server and wait till started
```sh
-docker-compose up -d dic-fhir && docker-compose logs -f dic-fhir
+docker compose up -d dic-fhir && docker compose logs -f dic-fhir
```
Console 3: Disconnect from log output (Ctrl-C) if server started
Console 3: Start DIC DSF BPE Server
```sh
-docker-compose up -d dic-bpe && docker-compose logs -f dic-fhir dic-bpe
+docker compose up -d dic-bpe && docker compose logs -f dic-fhir dic-bpe
````
Console 4: Start GTH DSF FHIR Server and wait till started
```sh
-docker-compose up -d gth-fhir && docker-compose logs -f gth-fhir
+docker compose up -d dts-fhir && docker compose logs -f dts-fhir
```
Console 4: Disconnect from log output (Ctrl-C) if server started
Console 4: Start GTH DSF BPE Server
```sh
-docker-compose up -d gth-bpe && docker-compose logs -f gth-fhir gth-bpe
+docker compose up -d dts-bpe && docker compose logs -f dts-fhir dts-bpe
````
-Console 5: Start CRR DSF FHIR Server and wait till started
+Console 5: Start CRR HAPI FHIR Server
```sh
-docker-compose up -d crr-fhir && docker-compose logs -f crr-fhir
+docker compose up crr-fhir-store-hapi
```
-Console 5: Dicconnect from log output (Ctrl-C) if server started
-Console 5: Start CRR DSF BPE Server
+
+Console 6: Start CRR DSF FHIR Server and wait till started
+```sh
+docker compose up -d crr-fhir && docker compose logs -f crr-fhir
+```
+Console 6: Dicconnect from log output (Ctrl-C) if server started
+Console 6: Start CRR DSF BPE Server
```sh
-docker-compose up -d crr-bpe && docker-compose logs -f crr-fhir crr-bpe
+docker compose up -d crr-bpe && docker compose logs -f crr-fhir crr-bpe
````
org.apache.commons
@@ -131,7 +131,7 @@
crypto-utils
3.8.0
-
+
org.slf4j
slf4j-api
@@ -157,6 +157,12 @@
mockito-core
4.8.0
+
+ org.mockito
+ mockito-junit-jupiter
+ 5.12.0
+ test
+
org.apache.logging.log4j
log4j-slf4j2-impl
@@ -197,7 +203,7 @@
org.apache.maven.plugins
- maven-shade-plugin
+ maven-shade-plugin
3.5.1
@@ -268,8 +274,8 @@
-
github
@@ -343,4 +349,4 @@
-
\ No newline at end of file
+