From 0e0adee648dd140868d726fa29e1222ef64678ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 14:44:49 +0200 Subject: [PATCH 01/68] Exclude MANIFEST.MF from jackson as it conflicts with the MANIFEST.MF from ping pong --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 64a30eb0..b3da062b 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,9 @@ ** + + META-INF/MANIFEST.MF + From daa6cdba8e15d34d6e5c7647b485824b82bc7c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 15:50:52 +0200 Subject: [PATCH 02/68] Initial move to DSF API v2 dependencies --- pom.xml | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index b3da062b..8755d468 100644 --- a/pom.xml +++ b/pom.xml @@ -13,8 +13,8 @@ 17 17 - 1.9.0 - 6.2.12 + 2.1.0 + 7.0.8 ../dsf @@ -39,13 +39,13 @@ dev.dsf - dsf-bpe-process-api-v1 + dsf-bpe-process-api-v2 ${dsf.version} provided org.springframework - spring-web + spring-context ${spring.version} provided @@ -71,13 +71,6 @@ - - dev.dsf - dsf-bpe-process-api-v1 - ${dsf.version} - test - test-jar - dev.dsf dsf-fhir-validation @@ -200,19 +193,19 @@ dev.dsf - dsf-tools-documentation-generator + dsf-maven-plugin ${dsf.version} - generate + generate-config-doc - - dev.dsf.bpe - + + dev.dsf.bpe.spring.config + From 29581ccac0e4e916d2a71c40649d6e7c7c064e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 15:52:12 +0200 Subject: [PATCH 03/68] ProcessPluginDeploymentStateListener is now called ProcessPluginDeploymentListener and FhirWebserviceClient is now DsfClient --- ...PongProcessPluginDeploymentStateListener.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java b/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java index fa22f28d..12b1c91a 100644 --- a/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java +++ b/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java @@ -22,12 +22,12 @@ import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.ProcessPluginDeploymentStateListener; -import dev.dsf.fhir.client.FhirWebserviceClient; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.ProcessPluginDeploymentListener; +import dev.dsf.bpe.v2.client.dsf.DsfClient; public class PingPongProcessPluginDeploymentStateListener - implements ProcessPluginDeploymentStateListener, InitializingBean + implements ProcessPluginDeploymentListener, InitializingBean { private final ProcessPluginApi api; @@ -65,7 +65,7 @@ public void onProcessesDeployed(List activeProcesses) private void updateDraftTaskResources() { - FhirWebserviceClient client = api.getFhirWebserviceClientProvider().getLocalWebserviceClient(); + DsfClient client = api.getDsfClientProvider().getLocal(); String pingProcessPrefix = "http://dsf.dev/bpe/Process/ping/" + RESOURCE_VERSION; String pingAutostartProcessPrefix = "http://dsf.dev/bpe/Process/pingAutostart/" + RESOURCE_VERSION; @@ -134,13 +134,13 @@ private void updateOlderResourcesIfCurrentIsNewestR private Bundle search(Class type, String url) { - return api.getFhirWebserviceClientProvider().getLocalWebserviceClient().search(type, + return api.getDsfClientProvider().getLocal().search(type, Map.of("url", List.of(url))); } private Bundle searchTask(String identifier) { - return api.getFhirWebserviceClientProvider().getLocalWebserviceClient().search(Task.class, + return api.getDsfClientProvider().getLocal().search(Task.class, Map.of("identifier", List.of(identifier), "status", List.of("draft"))); } @@ -230,7 +230,7 @@ private void overrideDifferentialForOlderExtensionStructureDefinitions( private void updateResources(List resources) { - resources.forEach(m -> api.getFhirWebserviceClientProvider().getLocalWebserviceClient().update(m)); + resources.forEach(m -> api.getDsfClientProvider().getLocal().update(m)); } private record MinorMajorVersion(int major, int minor) From 20f93234303f525249813e0ff37d5ca0f108d9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 15:53:38 +0200 Subject: [PATCH 04/68] No longer needs to implement InitializingBean as the API v2 version of the ExecutionListener interface provides the ProcessPluginApi instance in the notify method --- .../listener/SetCorrelationKeyListener.java | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/listener/SetCorrelationKeyListener.java b/src/main/java/dev/dsf/bpe/listener/SetCorrelationKeyListener.java index 3672cb3d..4bff3d4b 100644 --- a/src/main/java/dev/dsf/bpe/listener/SetCorrelationKeyListener.java +++ b/src/main/java/dev/dsf/bpe/listener/SetCorrelationKeyListener.java @@ -1,41 +1,24 @@ package dev.dsf.bpe.listener; -import java.util.Objects; - -import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.camunda.bpm.engine.delegate.ExecutionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.constants.BpmnExecutionVariables; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ExecutionListener; +import dev.dsf.bpe.v2.constants.BpmnExecutionVariables; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class SetCorrelationKeyListener implements ExecutionListener, InitializingBean +public class SetCorrelationKeyListener implements ExecutionListener { private static final Logger logger = LoggerFactory.getLogger(SetCorrelationKeyListener.class); - private final ProcessPluginApi api; - - public SetCorrelationKeyListener(ProcessPluginApi api) - { - this.api = api; - } - - @Override - public void afterPropertiesSet() throws Exception - { - Objects.requireNonNull(api, "api"); - } @Override - public void notify(DelegateExecution execution) throws Exception + public void notify(ProcessPluginApi processPluginApi, Variables variables) throws Exception { - logger.debug("Setting correlation key for subprocess instance {}", execution.getProcessInstanceId()); - Variables variables = api.getVariables(execution); + logger.debug("Setting correlation key for subprocess instance {}", variables.getActivityInstanceId()); Target target = variables.getTarget(); - execution.setVariableLocal(BpmnExecutionVariables.CORRELATION_KEY, target.getCorrelationKey()); + variables.setStringLocal(BpmnExecutionVariables.CORRELATION_KEY, target.getCorrelationKey()); } } From ca3f6443f36b137fdcb1cb63d17c5b71b3ed69af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 15:54:22 +0200 Subject: [PATCH 05/68] Only need to update imports --- src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java b/src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java index 57d380cf..b47bb942 100644 --- a/src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java +++ b/src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java @@ -10,8 +10,8 @@ import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.variables.Target; public class AggregateErrorMailService implements InitializingBean { From 4b63e32ceaac607d5708f71d4e8f7640e2ca24d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 16:38:06 +0200 Subject: [PATCH 06/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling method replaced by error handler implementation - Provide TaskSender instead of overriding sendTask method --- .../dsf/bpe/message/CleanupPongMessage.java | 128 ++++++++++-------- 1 file changed, 73 insertions(+), 55 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java index eb148c12..a9c6bb55 100644 --- a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java @@ -1,9 +1,10 @@ package dev.dsf.bpe.message; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Stream; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,89 +15,106 @@ import dev.dsf.bpe.util.task.SendTaskErrorConverter; import dev.dsf.bpe.util.task.input.generator.DownloadedBytesGenerator; import dev.dsf.bpe.util.task.input.generator.DownloadedDurationGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractTaskMessageSend; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.process_error.ProcessErrorValueImpl; - -public class CleanupPongMessage extends AbstractTaskMessageSend +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.task.DefaultTaskSender; +import dev.dsf.bpe.v2.activity.task.TaskSender; +import dev.dsf.bpe.v2.activity.values.SendTaskValues; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.MessageSendTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; + +public class CleanupPongMessage implements MessageSendTask { private static final Logger logger = LoggerFactory.getLogger(CleanupPongMessage.class); - public CleanupPongMessage(ProcessPluginApi api) - { - super(api); - } - @Override - protected Stream getAdditionalInputParameters(DelegateExecution execution, - Variables variables) + public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, + SendTaskValues sendTaskValues, Target target) { - Target target = variables.getTarget(); String correlationKey = target.getCorrelationKey(); Long downloadedBytes = variables.getLong(ExecutionVariables.downloadedBytes.correlatedValue(correlationKey)); - Duration downloadedDuration = (Duration) variables + Duration downloadedDuration = variables .getVariable(ExecutionVariables.downloadedDuration.correlatedValue(correlationKey)); - Stream downloadedBytesParameter = downloadedBytes != null - ? Stream.of(DownloadedBytesGenerator.create(downloadedBytes)) - : Stream.empty(); - Stream downloadedDurationParameter = downloadedDuration != null - ? Stream.of(DownloadedDurationGenerator.create(downloadedDuration)) - : Stream.empty(); + List additionalInputParameters = new ArrayList<>(); - return Stream.of(downloadedBytesParameter, downloadedDurationParameter).flatMap(s -> s); - } + if (downloadedBytes != null) + additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes)); - @Override - protected void handleSendTaskError(DelegateExecution execution, Variables variables, Exception exception, - String errorMessage) - { - Target target = variables.getTarget(); - SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter - .convertLocal(exception, false, ConstantsPing.PROCESS_NAME_PING); + if (downloadedDuration != null) + additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration)); - execution.setVariableLocal(ExecutionVariables.error.name(), new ProcessErrorValueImpl(errorAndStatus.error())); - execution.setVariableLocal(ExecutionVariables.statusCode.name(), CodeSystem.DsfPing.Code.ERROR.getValue()); - - logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), - errorAndStatus.error().concept().getDisplay()); + return additionalInputParameters; } @Override - protected void sendTask(DelegateExecution execution, Variables variables, Target target, - String instantiatesCanonical, String messageName, String businessKey, String profile, - Stream additionalInputParameters) + public MessageSendTaskErrorHandler getErrorHandler() { - Target newTarget = new Target() + return new MessageSendTaskErrorHandler() { @Override - public String getOrganizationIdentifierValue() + public ErrorBoundaryEvent handleErrorBoundaryEvent(ProcessPluginApi processPluginApi, Variables variables, + ErrorBoundaryEvent errorBoundaryEvent) { - return target.getOrganizationIdentifierValue(); + return errorBoundaryEvent; } @Override - public String getEndpointIdentifierValue() + public Exception handleException(ProcessPluginApi processPluginApi, Variables variables, + SendTaskValues sendTaskValues, Exception e) { - return target.getEndpointIdentifierValue(); - } + Target target = variables.getTarget(); + SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter + .convertLocal(e, false, ConstantsPing.PROCESS_NAME_PING); - @Override - public String getEndpointUrl() - { - return target.getEndpointUrl(); + variables.setJsonVariableLocal(ExecutionVariables.error.name(),errorAndStatus.error()); + variables.setStringLocal(ExecutionVariables.statusCode.name(), CodeSystem.DsfPing.Code.ERROR.getValue()); + + logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), + errorAndStatus.error().concept().getDisplay()); + + return e; } + }; + } + @Override + public TaskSender getTaskSender(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) + { + return new DefaultTaskSender(api, variables, sendTaskValues, this.getBusinessKeyStrategy()) { @Override - public String getCorrelationKey() + protected Target getTarget() { - return null; + Target oldTarget = super.getTarget(); + return new Target() + { + @Override + public String getOrganizationIdentifierValue() + { + return oldTarget.getOrganizationIdentifierValue(); + } + + @Override + public String getEndpointIdentifierValue() + { + return oldTarget.getEndpointIdentifierValue(); + } + + @Override + public String getEndpointUrl() + { + return oldTarget.getEndpointUrl(); + } + + @Override + public String getCorrelationKey() + { + return null; + } + }; } }; - - super.sendTask(execution, variables, newTarget, instantiatesCanonical, messageName, businessKey, profile, - additionalInputParameters); } } From d2a74f2001de32b6f9373e98d7dbbbb17b5dc296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 17:23:03 +0200 Subject: [PATCH 07/68] Error has to be absorbed (return null) in order for the process to not be killed --- src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java index a9c6bb55..7cc1fef5 100644 --- a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java @@ -75,7 +75,7 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), errorAndStatus.error().concept().getDisplay()); - return e; + return null; } }; } From d400ffaed88e6ea06e280fdbd49482bb353f7280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 23 Jun 2026 18:16:39 +0200 Subject: [PATCH 08/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling method replaced by error handler implementation - Provide TaskSender instead of overriding sendTask method --- .../dev/dsf/bpe/message/SendPingMessage.java | 125 +++++++++--------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java index df30bce4..fe35e111 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java @@ -1,14 +1,14 @@ package dev.dsf.bpe.message; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Stream; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResourceType; import org.hl7.fhir.r4.model.Task; -import org.hl7.fhir.r4.model.Task.ParameterComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,88 +19,95 @@ import dev.dsf.bpe.util.task.SendTaskErrorConverter; import dev.dsf.bpe.util.task.input.generator.DownloadResourceReferenceGenerator; import dev.dsf.bpe.util.task.input.generator.DownloadResourceSizeGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractTaskMessageSend; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueImpl; -import dev.dsf.bpe.variables.process_error.ProcessErrorValueImpl; -import dev.dsf.fhir.client.FhirWebserviceClient; - -public class SendPingMessage extends AbstractTaskMessageSend +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.task.DefaultTaskSender; +import dev.dsf.bpe.v2.activity.task.TaskSender; +import dev.dsf.bpe.v2.activity.values.SendTaskValues; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.MessageSendTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; + +public class SendPingMessage implements MessageSendTask { private static final Logger logger = LoggerFactory.getLogger(SendPingMessage.class); - private IdType taskId; - - public SendPingMessage(ProcessPluginApi api) - { - super(api); - } @Override - protected Stream getAdditionalInputParameters(DelegateExecution execution, Variables variables) + public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, + SendTaskValues sendTaskValues, Target target) { String downloadResourceReference = variables.getString(ExecutionVariables.downloadResourceReference.name()); long downloadResourceSizeBytes = variables.getLong(ExecutionVariables.downloadResourceSizeBytes.name()); - Stream downloadResourceReferenceStream = downloadResourceReference == null ? Stream.empty() - : Stream.of(DownloadResourceReferenceGenerator.create(downloadResourceReference)); - Stream downloadResourceSizeBytesStream = Stream - .of(DownloadResourceSizeGenerator.create(downloadResourceSizeBytes)); - ParameterComponent endpointIdentifierComponent = api.getTaskHelper().createInput( - new Reference().setIdentifier(getLocalEndpointIdentifier()).setType(ResourceType.Endpoint.name()), - CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue()); + List additionalInputParameters = new ArrayList<>(); + + if (downloadResourceReference != null) + additionalInputParameters.add(DownloadResourceReferenceGenerator.create(downloadResourceReference)); + + additionalInputParameters.add(DownloadResourceSizeGenerator.create(downloadResourceSizeBytes)); + + Task.ParameterComponent endpointIdentifierComponent = api.getTaskHelper().createInput( + new Reference().setIdentifier(getLocalEndpointIdentifier(api)).setType(ResourceType.Endpoint.name()), + CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue(), api.getProcessPluginDefinition().getResourceVersion()); endpointIdentifierComponent.getType().getCodingFirstRep() .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); - Stream endpointIdentifierStream = Stream.of(endpointIdentifierComponent); - return Stream.concat(endpointIdentifierStream, - Stream.concat(downloadResourceReferenceStream, downloadResourceSizeBytesStream)); - } + additionalInputParameters.add(endpointIdentifierComponent); - @Override - protected void sendTask(DelegateExecution execution, Variables variables, Target target, - String instantiatesCanonical, String messageName, String businessKey, String profile, - Stream additionalInputParameters) - { - super.sendTask(execution, variables, target, instantiatesCanonical, messageName, businessKey, profile, - additionalInputParameters); - if (taskId != null) - { - execution.setVariableLocal(ExecutionVariables.pingTaskId.name(), taskId.getIdPart()); - } + return additionalInputParameters; } @Override - protected IdType doSend(FhirWebserviceClient client, Task task) + public TaskSender getTaskSender(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) { - taskId = super.doSend(client, task); - return taskId; + return new DefaultTaskSender(api, variables, sendTaskValues, getBusinessKeyStrategy()) { + @Override + protected IdType doSend(Task task, String targetEndpointUrl) + { + IdType taskId = super.doSend(task, targetEndpointUrl); + if (taskId != null) + { + variables.setStringLocal(ExecutionVariables.pingTaskId.name(), taskId.getIdPart()); + } + return taskId; + } + }; } @Override - protected void handleSendTaskError(DelegateExecution execution, Variables variables, Exception exception, - String errorMessage) + public MessageSendTaskErrorHandler getErrorHandler() { - Target target = variables.getTarget(); - SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter - .convertLocal(exception, true, ConstantsPing.PROCESS_NAME_PING); + return new MessageSendTaskErrorHandler() + { + @Override + public ErrorBoundaryEvent handleErrorBoundaryEvent(ProcessPluginApi processPluginApi, Variables variables, + ErrorBoundaryEvent errorBoundaryEvent) + { + return errorBoundaryEvent; + } - execution.setVariableLocal(ExecutionVariables.error.name(), new ProcessErrorValueImpl(errorAndStatus.error())); - execution.setVariableLocal(ExecutionVariables.statusCode.name(), - new CodeValueImpl(errorAndStatus.statusCode())); + @Override + public Exception handleException(ProcessPluginApi processPluginApi, Variables variables, + SendTaskValues sendTaskValues, Exception e) + { + Target target = variables.getTarget(); + SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter + .convertLocal(e, true, ConstantsPing.PROCESS_NAME_PING); - logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), - errorAndStatus.error().concept().getDisplay()); - } + variables.setJsonVariableLocal(ExecutionVariables.error.name(), errorAndStatus.error()); + variables.setJsonVariableLocal(ExecutionVariables.statusCode.name(), + errorAndStatus.statusCode()); - @Override - protected void addErrorMessage(Task task, String errorMessage) - { - // error message part of status extension + logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), + errorAndStatus.error().concept().getDisplay()); + + return null; + } + }; } - private Identifier getLocalEndpointIdentifier() + private Identifier getLocalEndpointIdentifier(ProcessPluginApi api) { return api.getEndpointProvider().getLocalEndpointIdentifier() .orElseThrow(() -> new IllegalStateException("Local endpoint identifier unknown")); From 3ce3b2dc5e96be0b58a9907816a473e9a248e389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 11:53:52 +0200 Subject: [PATCH 09/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling method replaced by error handler implementation - doExecute renamed to execute --- .../dev/dsf/bpe/message/SendPongMessage.java | 108 ++++++++++-------- 1 file changed, 61 insertions(+), 47 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendPongMessage.java b/src/main/java/dev/dsf/bpe/message/SendPongMessage.java index 7aed532e..5b62925e 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPongMessage.java @@ -1,9 +1,9 @@ package dev.dsf.bpe.message; import java.time.Duration; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.List; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,82 +19,96 @@ import dev.dsf.bpe.util.task.input.generator.DownloadedDurationGenerator; import dev.dsf.bpe.util.task.input.generator.ErrorInputComponentGenerator; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractTaskMessageSend; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.values.SendTaskValues; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.MessageSendTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class SendPongMessage extends AbstractTaskMessageSend +public class SendPongMessage implements MessageSendTask { private static final Logger logger = LoggerFactory.getLogger(SendPongMessage.class); - public SendPongMessage(ProcessPluginApi api) - { - super(api); - } - @Override - protected Stream getAdditionalInputParameters(DelegateExecution execution, - Variables variables) + public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, + SendTaskValues sendTaskValues, Target target) { - ProcessErrors errorListRemote = ErrorListUtils.getErrorListRemote(execution); + ProcessErrors errorListRemote = ErrorListUtils.getErrorListRemote(variables); long downloadResourceSizeBytes = variables.getLong(ExecutionVariables.downloadResourceSizeBytes.name()); if (downloadResourceSizeBytes >= 0) { Long downloadedBytes = variables.getLong(ExecutionVariables.downloadedBytes.name()); - Duration downloadedDuration = (Duration) variables + Duration downloadedDuration = variables .getVariable(ExecutionVariables.downloadedDuration.name()); String downloadResourceReference = variables.getString(ExecutionVariables.downloadResourceReference.name()); - Stream downloadedBytesParameter = downloadedBytes != null - ? Stream.of(DownloadedBytesGenerator.create(downloadedBytes)) - : Stream.empty(); - Stream downloadedDurationParameter = downloadedDuration != null - ? Stream.of(DownloadedDurationGenerator.create(downloadedDuration)) - : Stream.empty(); - Stream downloadedResourceReferenceParameter = downloadResourceReference != null - ? Stream.of(DownloadResourceReferenceGenerator.create(downloadResourceReference)) - : Stream.empty(); - - return Stream - .of(downloadedBytesParameter, downloadedDurationParameter, downloadedResourceReferenceParameter, - ErrorInputComponentGenerator.create(errorListRemote.getEntries()).stream()) - .flatMap(stream -> stream); + ArrayList additionalInputParameters = new ArrayList<>(); + + if (downloadedBytes != null) + additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes)); + + if (downloadedDuration != null) + additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration)); + + if (downloadResourceReference != null) + additionalInputParameters.add(DownloadResourceReferenceGenerator.create(downloadResourceReference)); + + additionalInputParameters.addAll(ErrorInputComponentGenerator.create(errorListRemote.getEntries())); + + return additionalInputParameters; } else { - return ErrorInputComponentGenerator.create(errorListRemote.getEntries()).stream(); + return ErrorInputComponentGenerator.create(errorListRemote.getEntries()); } } @Override - protected void doExecute(DelegateExecution execution, Variables variables) throws Exception + public void execute(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) + throws ErrorBoundaryEvent, Exception { Target target = variables.getTarget(); Task mainTask = variables.getStartTask(); - variables.setVariable(ExecutionVariables.statusCode.name(), - new CodeValueImpl(CodeSystem.DsfPingStatus.Code.PONG_SENT)); + variables.setJsonVariable(ExecutionVariables.statusCode.name(), + CodeSystem.DsfPingStatus.Code.PONG_SENT); PingStatusGenerator.updatePongStatusOutput(mainTask, target); variables.updateTask(mainTask); - super.doExecute(execution, variables); + MessageSendTask.super.execute(api, variables, sendTaskValues); } @Override - protected void handleSendTaskError(DelegateExecution execution, Variables variables, Exception exception, - String errorMessage) + public MessageSendTaskErrorHandler getErrorHandler() { - Target target = variables.getTarget(); - Task startTask = variables.getStartTask(); + return new MessageSendTaskErrorHandler() + { + @Override + public ErrorBoundaryEvent handleErrorBoundaryEvent(ProcessPluginApi processPluginApi, Variables variables, + ErrorBoundaryEvent errorBoundaryEvent) + { + return errorBoundaryEvent; + } + + @Override + public Exception handleException(ProcessPluginApi processPluginApi, Variables variables, + SendTaskValues sendTaskValues, Exception e) + { + Target target = variables.getTarget(); + Task startTask = variables.getStartTask(); + + SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter + .convertLocal(e, true, ConstantsPing.PROCESS_NAME_PONG); - SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter - .convertLocal(exception, true, ConstantsPing.PROCESS_NAME_PONG); + ErrorListUtils.add(errorAndStatus.error(), variables); + variables.setJsonVariable(ExecutionVariables.statusCode.name(), errorAndStatus.statusCode()); + variables.updateTask(startTask); - ErrorListUtils.add(errorAndStatus.error(), execution); - variables.setVariable(ExecutionVariables.statusCode.name(), new CodeValueImpl(errorAndStatus.statusCode())); - variables.updateTask(startTask); + logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), + errorAndStatus.error().concept().getDisplay()); - logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), - errorAndStatus.error().concept().getDisplay()); + return null; + } + }; } } From a4660ec2215a6f4d055dab2538d869289fadb74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 12:03:21 +0200 Subject: [PATCH 10/68] API v2 changes: - interface instead of superclass -> no constructor needed - getAdditionalInputParameters now return list - override getBusinessKeyStrategy to always send a new business key instead of setting it manually --- .../dev/dsf/bpe/message/SendStartPing.java | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendStartPing.java b/src/main/java/dev/dsf/bpe/message/SendStartPing.java index 9640c1cc..ae02aa8a 100644 --- a/src/main/java/dev/dsf/bpe/message/SendStartPing.java +++ b/src/main/java/dev/dsf/bpe/message/SendStartPing.java @@ -1,52 +1,49 @@ package dev.dsf.bpe.message; -import java.util.UUID; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.List; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.hl7.fhir.r4.model.Task.ParameterComponent; import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractTaskMessageSend; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; - -public class SendStartPing extends AbstractTaskMessageSend +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.task.BusinessKeyStrategies; +import dev.dsf.bpe.v2.activity.task.BusinessKeyStrategy; +import dev.dsf.bpe.v2.activity.values.SendTaskValues; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; + +public class SendStartPing implements MessageSendTask { - public SendStartPing(ProcessPluginApi api) - { - super(api); - } - @Override - protected Stream getAdditionalInputParameters(DelegateExecution execution, Variables variables) + public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, + SendTaskValues sendTaskValues, Target target) { - return Stream.concat( - variables.getStartTask().getInput().stream().filter(Task.ParameterComponent::hasType) - .filter(i -> i.getType().getCoding().stream() - .anyMatch(c -> CodeSystem.DsfPing.URL.equals(c.getSystem()) - && CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue().equals(c.getCode()))), - variables.getStartTask().getInput().stream().filter(this::isDownloadResourceSizeParameter)); + List additionalInputParameters = new ArrayList<>(); + + variables.getStartTask().getInput().stream().filter(Task.ParameterComponent::hasType) + .filter(i -> i.getType().getCoding().stream().anyMatch(c -> CodeSystem.DsfPing.URL.equals(c.getSystem()) + && CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue().equals(c.getCode()))) + .forEach(additionalInputParameters::add); + + variables.getStartTask().getInput().stream().filter(this::isDownloadResourceSizeParameter) + .forEach(additionalInputParameters::add); + + return additionalInputParameters; } private boolean isDownloadResourceSizeParameter(ParameterComponent parameterComponent) { - return parameterComponent.getType().getCoding().stream() - .anyMatch(t -> CodeSystem.DsfPing.URL.equals(t.getSystem()) + return parameterComponent.getType().getCoding().stream().anyMatch( + t -> CodeSystem.DsfPing.URL.equals(t.getSystem()) && CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES.getValue().equals(t.getCode())); } @Override - protected void sendTask(DelegateExecution execution, Variables variables, Target target, - String instantiatesCanonical, String messageName, String businessKey, String profile, - Stream additionalInputParameters) + public BusinessKeyStrategy getBusinessKeyStrategy() { - // different business-key for every start-ping execution - businessKey = UUID.randomUUID().toString(); - - super.sendTask(execution, variables, target, instantiatesCanonical, messageName, businessKey, profile, - additionalInputParameters); + return BusinessKeyStrategies.NEW; } } From 734690193a9dd24e8836b71504daf403584f548e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 14:07:44 +0200 Subject: [PATCH 11/68] API v2 changes: - interface instead of superclass -> no constructor needed - no longer subclass of AbstractService as the process should fail if there is an exception in this service --- .../autostart/SetTargetAndConfigureTimer.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/autostart/SetTargetAndConfigureTimer.java b/src/main/java/dev/dsf/bpe/service/autostart/SetTargetAndConfigureTimer.java index 7e6a27a4..3db01064 100644 --- a/src/main/java/dev/dsf/bpe/service/autostart/SetTargetAndConfigureTimer.java +++ b/src/main/java/dev/dsf/bpe/service/autostart/SetTargetAndConfigureTimer.java @@ -1,30 +1,24 @@ package dev.dsf.bpe.service.autostart; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SetTargetAndConfigureTimer extends AbstractService +public class SetTargetAndConfigureTimer implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SetTargetAndConfigureTimer.class); - public SetTargetAndConfigureTimer(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { - String timerInterval = getTimerInterval(variables); + String timerInterval = getTimerInterval(api, variables); logger.debug("Setting variable '{}' to {}", ExecutionVariables.timerInterval.name(), timerInterval); variables.setString(ExecutionVariables.timerInterval.name(), timerInterval); @@ -34,7 +28,7 @@ protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables api.getEndpointProvider().getLocalEndpointAddress())); } - private String getTimerInterval(Variables variables) + private String getTimerInterval(ProcessPluginApi api, Variables variables) { return api.getTaskHelper() .getFirstInputParameterStringValue(variables.getStartTask(), CodeSystem.DsfPing.URL, From 2774789a3b6c15f38cb44ead34f462846dd63ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 14:46:21 +0200 Subject: [PATCH 12/68] Error handling previously done in AbstractService will now be done in each service task implementation by an error handler class. --- .../dev/dsf/bpe/service/AbstractService.java | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 src/main/java/dev/dsf/bpe/service/AbstractService.java diff --git a/src/main/java/dev/dsf/bpe/service/AbstractService.java b/src/main/java/dev/dsf/bpe/service/AbstractService.java deleted file mode 100644 index 1afeb6d3..00000000 --- a/src/main/java/dev/dsf/bpe/service/AbstractService.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.dsf.bpe.service; - -import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractServiceDelegate; -import dev.dsf.bpe.v1.variables.Variables; - -public abstract class AbstractService extends AbstractServiceDelegate -{ - private static final Logger logger = LoggerFactory.getLogger(AbstractService.class); - - public AbstractService(ProcessPluginApi api) - { - super(api); - } - - @Override - protected void doExecute(DelegateExecution execution, Variables variables) throws Exception - { - try - { - doExecuteWithErrorHandling(execution, variables); - } - catch (Exception e) - { - handleException(execution, variables, e); - } - } - - abstract protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) - throws Exception; - - protected void handleException(DelegateExecution execution, Variables variables, Exception exception) - throws Exception - { - logger.error("Unexpected error while executing service", exception); - throw exception; - } -} From 0a8f352eea35db636831f5cb5b9404f827d8b900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 16:47:47 +0200 Subject: [PATCH 13/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling moved to overridden getErrorHandler method - Convert exception to error boundary event and just return the boundary event in the error boundary event handler to cause the engine to move on with the error boundary event flow --- .../bpe/service/ping/CheckPingTaskStatus.java | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java index 36ed301e..68639823 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java +++ b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java @@ -1,7 +1,7 @@ package dev.dsf.bpe.service.ping; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; +import java.time.Duration; + import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,26 +10,24 @@ import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueImpl; -import dev.dsf.fhir.client.FhirWebserviceClient; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.client.dsf.DelayStrategy; +import dev.dsf.bpe.v2.client.dsf.DsfClient; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.ServiceTaskErrorHandler; +import dev.dsf.bpe.v2.error.impl.DefaultServiceTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; import jakarta.ws.rs.WebApplicationException; -public class CheckPingTaskStatus extends AbstractService +public class CheckPingTaskStatus implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(CheckPingTaskStatus.class); - public CheckPingTaskStatus(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Checking status of ping task..."); @@ -45,10 +43,10 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V { if (taskId != null) { - FhirWebserviceClient fhirWebserviceClient = api.getFhirWebserviceClientProvider() - .getWebserviceClient(target.getEndpointUrl()); + DsfClient dsfClient = api.getDsfClientProvider() + .getByEndpointUrl(target.getEndpointUrl()); - Task pingTask = fhirWebserviceClient.withRetry(3, 1000).read(Task.class, taskId); + Task pingTask = dsfClient.withRetry(3, DelayStrategy.constant(Duration.ofSeconds(1))).read(Task.class, taskId); ProcessError error = switch (pingTask.getStatus()) { case COMPLETED -> new ProcessError(ConstantsPing.PROCESS_NAME_PING, @@ -62,18 +60,18 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V default -> new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.RESPONSE_MESSAGE_TIMEOUT_STATUS_UNEXPECTED, null); }; - ErrorListUtils.add(error, delegateExecution, correlationKey); + ErrorListUtils.add(error, variables, correlationKey); } } catch (WebApplicationException e) { ProcessError error = getProcessError(e); - ErrorListUtils.add(error, delegateExecution, correlationKey); + ErrorListUtils.add(error, variables, correlationKey); } finally { - variables.setVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), - new CodeValueImpl(CodeSystem.DsfPingStatus.Code.PONG_MISSING)); + variables.setJsonVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), + CodeSystem.DsfPingStatus.Code.PONG_MISSING); } logger.debug("Saved '{}' to process execution for correlation key '{}'", @@ -113,14 +111,20 @@ private static ProcessError getProcessError(WebApplicationException e) } @Override - protected void handleException(DelegateExecution execution, Variables variables, Exception exception) - throws Exception + public ServiceTaskErrorHandler getErrorHandler() { - logger.error("Unexpected error while checking status of ping task.", exception); - String correlationKey = variables.getTarget().getCorrelationKey(); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - execution, correlationKey); - throw new BpmnError(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR); + return new DefaultServiceTaskErrorHandler() + { + @Override + public Exception handleException(ProcessPluginApi processPluginApi, Variables variables, Exception e) + { + logger.error("Unexpected error while checking status of ping task.", e); + String correlationKey = variables.getTarget().getCorrelationKey(); + ErrorListUtils.add( + new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), + variables, correlationKey); + throw new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + } + }; } } From b46b290bfa49a682b15fa32390c501807b81372e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 16:51:09 +0200 Subject: [PATCH 14/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling moved to overridden getErrorHandler method - Convert exception to error boundary event and just return the boundary event in the error boundary event handler to cause the engine to move on with the error boundary event flow --- ...adResourceAndMeasureSpeedInSubProcess.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java index dbcde996..01085e8b 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java +++ b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java @@ -1,7 +1,5 @@ package dev.dsf.bpe.service.ping; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,25 +8,22 @@ import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.BinaryResourceDownloader; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.duration.DurationValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.ServiceTaskErrorHandler; +import dev.dsf.bpe.v2.error.impl.DefaultServiceTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class DownloadResourceAndMeasureSpeedInSubProcess extends AbstractService +public class DownloadResourceAndMeasureSpeedInSubProcess implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(DownloadResourceAndMeasureSpeedInSubProcess.class); - public DownloadResourceAndMeasureSpeedInSubProcess(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Starting resource download to measure speed..."); @@ -44,12 +39,12 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V { variables.setLong(ExecutionVariables.downloadedBytes.correlatedValue(correlationKey), downloadResult.getDownloadedBytes()); - variables.setVariable(ExecutionVariables.downloadedDuration.correlatedValue(correlationKey), - new DurationValueImpl(downloadResult.getDownloadedDuration())); + variables.setJsonVariable(ExecutionVariables.downloadedDuration.correlatedValue(correlationKey), + downloadResult.getDownloadedDuration()); } else { - delegateExecution.setVariableLocal(ExecutionVariables.resourceDownloadError.name(), + variables.setJsonVariableLocal(ExecutionVariables.resourceDownloadError.name(), downloadResult.getErrorTuple().errorLocal()); } @@ -57,14 +52,19 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V } @Override - protected void handleException(DelegateExecution execution, Variables variables, Exception exception) - throws Exception + public ServiceTaskErrorHandler getErrorHandler() { - logger.error("Unexpected error while downloading resource and measuring speed.", exception); - String correlationKey = variables.getTarget().getCorrelationKey(); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - execution, correlationKey); - throw new BpmnError(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR); + return new DefaultServiceTaskErrorHandler() { + @Override + public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) + { + logger.error("Unexpected error while downloading resource and measuring speed.", exception); + String correlationKey = variables.getTarget().getCorrelationKey(); + ErrorListUtils.add( + new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), + variables, correlationKey); + throw new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + } + }; } } From 9613e9f06e3c2ccbeeffff68228824b0a902ba86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 16:53:58 +0200 Subject: [PATCH 15/68] API v2 changes: - interface instead of superclass -> no constructor needed - doExecute now named execute --- .../dsf/bpe/service/ping/LogAndSaveError.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java index 71571b87..22a63004 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java @@ -1,36 +1,30 @@ package dev.dsf.bpe.service.ping; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class LogAndSaveError extends AbstractService +public class LogAndSaveError implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveError.class); - public LogAndSaveError(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { Target target = variables.getTarget(); - ProcessError error = (ProcessError) delegateExecution + ProcessError error = variables .getVariableLocal(ExecutionVariables.resourceDownloadError.name()); - ErrorListUtils.add(error, delegateExecution, target.getCorrelationKey()); + ErrorListUtils.add(error, variables, target.getCorrelationKey()); logger.info("Error while trying to download resource from {}: {}", target.getEndpointUrl(), error.concept().getDisplay()); From d5bf662fc8fc161628c4fc2fbc0e94f3d2c1f0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 16:59:25 +0200 Subject: [PATCH 16/68] API v2 changes: - interface instead of superclass -> no constructor needed - doExecute now named execute --- .../bpe/service/ping/LogAndSaveSendError.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java index d6235223..b32bdb16 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java @@ -2,40 +2,33 @@ import java.util.Objects; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class LogAndSaveSendError extends AbstractService +public class LogAndSaveSendError implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveSendError.class); - public LogAndSaveSendError(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { String correlationKey = variables.getTarget().getCorrelationKey(); - ProcessError error = (ProcessError) execution.getVariableLocal(ExecutionVariables.error.name()); - CodeSystem.DsfPingStatus.Code status = (CodeSystem.DsfPingStatus.Code) execution + ProcessError error = variables.getVariableLocal(ExecutionVariables.error.name()); + CodeSystem.DsfPingStatus.Code status = variables .getVariableLocal(ExecutionVariables.statusCode.name()); Objects.requireNonNull(status, "status"); - ErrorListUtils.add(error, execution, correlationKey); - variables.setVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), new CodeValueImpl(status)); + ErrorListUtils.add(error, variables, correlationKey); + variables.setJsonVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), status); logger.debug("Saved error when trying to send ping message. Error message: {}", error.concept().getDisplay()); } } From 77d5bede9ea04f50f77ff7b709ce4e7193729c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 17:18:35 +0200 Subject: [PATCH 17/68] API v2 changes: - interface instead of superclass -> no constructor needed - doExecute now named execute --- .../ping/LogAndSaveUploadErrorPing.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java index c4177ef2..3f66ed3a 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java @@ -1,41 +1,41 @@ package dev.dsf.bpe.service.ping; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; - -public class LogAndSaveUploadErrorPing extends AbstractService +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.ServiceTaskErrorHandler; +import dev.dsf.bpe.v2.error.impl.DefaultServiceTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Variables; + +public class LogAndSaveUploadErrorPing implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveUploadErrorPing.class); - public LogAndSaveUploadErrorPing(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { - ProcessError error = (ProcessError) variables.getVariable(ExecutionVariables.resourceUploadError.name()); + ProcessError error = variables.getVariable(ExecutionVariables.resourceUploadError.name()); - ErrorListUtils.add(error, execution); + ErrorListUtils.add(error, variables); logger.info("Error while storing binary resource for download: {}", error.concept().getDisplay()); } @Override - protected void handleException(DelegateExecution execution, Variables variables, Exception exception) - throws Exception + public ServiceTaskErrorHandler getErrorHandler() { - logger.error("Unexpected error while storing binary resource for download.", exception); - throw exception; + return new DefaultServiceTaskErrorHandler() { + @Override + public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) + { + return super.handleException(api, variables, exception); + } + }; } } From 3d64569bc42d40b20bb93d0afc5db8b5c5678545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 17:40:25 +0200 Subject: [PATCH 18/68] API v2 changes: - interface instead of superclass -> no constructor needed - doExecute now named execute - no more variables.removeVariable() -> instead set variable value to null and make sure checks in BPMN expressions don't break e.g. if they rely on execution.hasVariable() --- .../dev/dsf/bpe/service/ping/SavePong.java | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java index d2a70eb3..4e3faf92 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java @@ -4,8 +4,6 @@ import java.util.List; import java.util.Optional; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.DecimalType; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; @@ -16,30 +14,24 @@ import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; import dev.dsf.bpe.ProcessErrors; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueImpl; -import dev.dsf.bpe.variables.duration.DurationValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class SavePong extends AbstractService +public class SavePong implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SavePong.class); - public SavePong(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { Target target = variables.getTarget(); logger.debug("Pong received from {}. Saving pong information...", target.getEndpointUrl()); String correlationKey = target.getCorrelationKey(); - delegateExecution.removeVariable("statusCode"); + variables.setJsonVariable("statusCode", null); Task pong = variables.getLatestTask(); @@ -48,8 +40,8 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V CodeSystem.DsfPing.Code.DOWNLOADED_DURATION_MILLIS.getValue(), org.hl7.fhir.r4.model.Duration.class); optDownloadedDuration.ifPresent( - duration -> variables.setVariable(ExecutionVariables.uploadedDuration.correlatedValue(correlationKey), - new DurationValueImpl(Duration.ofMillis(duration.getValue().longValue())))); + duration -> variables.setJsonVariable(ExecutionVariables.uploadedDuration.correlatedValue(correlationKey), + Duration.ofMillis(duration.getValue().longValue()))); Optional optDownloadedBytes = api.getTaskHelper().getFirstInputParameterValue(pong, CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.DOWNLOADED_BYTES.getValue(), DecimalType.class); @@ -59,9 +51,9 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V ProcessErrors errorList = new ProcessErrors(parseInputs(pong)); - ErrorListUtils.addAll(errorList, delegateExecution, correlationKey); - variables.setVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), - new CodeValueImpl(CodeSystem.DsfPingStatus.Code.PONG_RECEIVED)); + ErrorListUtils.addAll(errorList, variables, correlationKey); + variables.setJsonVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey), + CodeSystem.DsfPingStatus.Code.PONG_RECEIVED); logger.debug("Saved pong information."); } From a133de130dcf3fb0ba4f909ba1a45e5c8e1b0f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 17:50:02 +0200 Subject: [PATCH 19/68] ErrorBoundaryEvent should be returned, not thrown --- src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java | 2 +- .../ping/DownloadResourceAndMeasureSpeedInSubProcess.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java index 68639823..88b854af 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java +++ b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java @@ -123,7 +123,7 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va ErrorListUtils.add( new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), variables, correlationKey); - throw new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); } }; } diff --git a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java index 01085e8b..e467a277 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java +++ b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java @@ -63,7 +63,7 @@ public Exception handleException(ProcessPluginApi api, Variables variables, Exce ErrorListUtils.add( new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), variables, correlationKey); - throw new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); } }; } From b5784d6c233646c3308258f36f2115d0743fe272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 17:51:58 +0200 Subject: [PATCH 20/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling moved to overridden getErrorHandler method - Reintroduce spring web dependency as SelectPingTargets uses UriComponents and UriComponentsBuilder --- pom.xml | 2 +- .../bpe/service/ping/SelectPingTargets.java | 78 +++++++++---------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 8755d468..e4ccd457 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ org.springframework - spring-context + spring-web ${spring.version} provided diff --git a/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java b/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java index 50ea5a2b..df1b9879 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java @@ -12,8 +12,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -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.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Endpoint; @@ -24,38 +22,35 @@ import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.constants.NamingSystems.EndpointIdentifier; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; - -public class SelectPingTargets extends AbstractService implements InitializingBean +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.constants.NamingSystems.EndpointIdentifier; +import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.error.ServiceTaskErrorHandler; +import dev.dsf.bpe.v2.error.impl.DefaultServiceTaskErrorHandler; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; + +public class SelectPingTargets implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SelectPingTargets.class); private static final Pattern endpointResouceTypes = Pattern.compile( "Endpoint|HealthcareService|ImagingStudy|InsurancePlan|Location|Organization|OrganizationAffiliation|PractitionerRole"); - public SelectPingTargets(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { - Stream targetEndpoints = getTargetEndpointsSearchParameter(variables) - .map(uriComponents -> searchForEndpoints(uriComponents)).orElse(allEndpoints()) - .filter(isLocalEndpoint().negate()); + Stream targetEndpoints = getTargetEndpointsSearchParameter(api, variables) + .map(uriComponents -> searchForEndpoints(api, uriComponents)).orElse(allEndpoints(api)) + .filter(isLocalEndpoint(api).negate()); List remoteOrganizations = api.getOrganizationProvider().getRemoteOrganizations(); Map organizationIdentifierByOrganizationId = remoteOrganizations.stream().collect( @@ -78,17 +73,22 @@ protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables } @Override - protected void handleException(DelegateExecution execution, Variables variables, Exception exception) - throws Exception + public ServiceTaskErrorHandler getErrorHandler() { - logger.error("Unexpected error while selecting ping targets.", exception); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - execution); - throw new BpmnError(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR); + return new DefaultServiceTaskErrorHandler() { + @Override + public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) + { + logger.error("Unexpected error while selecting ping targets.", exception); + ErrorListUtils.add( + new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), + variables); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + } + }; } - private Optional getTargetEndpointsSearchParameter(Variables variables) + private Optional getTargetEndpointsSearchParameter(ProcessPluginApi api, Variables variables) { Task mainTask = variables.getStartTask(); return api.getTaskHelper() @@ -97,12 +97,12 @@ private Optional getTargetEndpointsSearchParameter(Variables vari .map(requestUrl -> UriComponentsBuilder.fromUriString(requestUrl).build()); } - private Stream searchForEndpoints(UriComponents searchParameters) + private Stream searchForEndpoints(ProcessPluginApi api, UriComponents searchParameters) { - return searchForEndpoints(searchParameters, 1, 0); + return searchForEndpoints(api, searchParameters, 1, 0); } - private Stream searchForEndpoints(UriComponents searchParameters, int page, int currentTotal) + private Stream searchForEndpoints(ProcessPluginApi api, UriComponents searchParameters, int page, int currentTotal) { if (searchParameters.getPathSegments().isEmpty()) return Stream.empty(); @@ -115,12 +115,12 @@ private Stream searchForEndpoints(UriComponents searchParameters, int queryParameters.putAll(searchParameters.getQueryParams()); queryParameters.put("_page", Collections.singletonList(String.valueOf(page))); - Bundle searchResult = api.getFhirWebserviceClientProvider().getLocalWebserviceClient() + Bundle searchResult = api.getDsfClientProvider().getLocal() .searchWithStrictHandling(resourceType.get(), queryParameters); if (searchResult.getTotal() > currentTotal + searchResult.getEntry().size()) return Stream.concat(toEndpoints(searchResult), - searchForEndpoints(searchParameters, page + 1, currentTotal + searchResult.getEntry().size())); + searchForEndpoints(api, searchParameters, page + 1, currentTotal + searchResult.getEntry().size())); else return toEndpoints(searchResult); } @@ -146,19 +146,19 @@ private Optional> getResourceType(UriComponents search } } - private Stream allEndpoints() + private Stream allEndpoints(ProcessPluginApi api) { - return allEndpoints(1, 0); + return allEndpoints(api, 1, 0); } - private Predicate isLocalEndpoint() + private Predicate isLocalEndpoint(ProcessPluginApi api) { return e -> Objects.equals(api.getEndpointProvider().getLocalEndpointAddress(), e.getAddress()); } - private Stream allEndpoints(int page, int currentTotal) + private Stream allEndpoints(ProcessPluginApi api, int page, int currentTotal) { - Bundle searchResult = api.getFhirWebserviceClientProvider().getLocalWebserviceClient().searchWithStrictHandling( + Bundle searchResult = api.getDsfClientProvider().getLocal().searchWithStrictHandling( Endpoint.class, Map.of("status", Collections.singletonList("active"), "identifier", Collections.singletonList("http://dsf.dev/sid/endpoint-identifier|"), "_page", @@ -166,7 +166,7 @@ private Stream allEndpoints(int page, int currentTotal) if (searchResult.getTotal() > currentTotal + searchResult.getEntry().size()) return Stream.concat(toEndpoints(searchResult), - allEndpoints(page + 1, currentTotal + searchResult.getEntry().size())); + allEndpoints(api, page + 1, currentTotal + searchResult.getEntry().size())); else return toEndpoints(searchResult); } From 465f15c5ad322c95261fcd9acee78f267533ca20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 18:09:04 +0200 Subject: [PATCH 21/68] API v2 changes: - interface instead of superclass -> no constructor needed - Error handling moved to overridden getErrorHandler method - doExecute renamed to execute --- .../service/ping/SetPongTimeoutDuration.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/SetPongTimeoutDuration.java b/src/main/java/dev/dsf/bpe/service/ping/SetPongTimeoutDuration.java index 05e2951c..f672478d 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SetPongTimeoutDuration.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SetPongTimeoutDuration.java @@ -4,28 +4,23 @@ import java.time.format.DateTimeParseException; import java.util.Optional; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SetPongTimeoutDuration extends AbstractService +public class SetPongTimeoutDuration implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SetPongTimeoutDuration.class); - public SetPongTimeoutDuration(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws Exception + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Setting pong timer duration..."); Task startTask = variables.getStartTask(); From 55aecf9aed6ea678a8875b666bac88667c1a4404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 24 Jun 2026 18:14:24 +0200 Subject: [PATCH 22/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../dsf/bpe/service/ping/StoreResults.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java b/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java index d49ee395..f15fb0df 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java +++ b/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java @@ -9,8 +9,6 @@ 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.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,22 +21,22 @@ import dev.dsf.bpe.mail.AggregateErrorMailService; import dev.dsf.bpe.util.ErrorListUtils; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractServiceDelegate; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Targets; -import dev.dsf.bpe.v1.variables.Variables; - -public class StoreResults extends AbstractServiceDelegate implements InitializingBean +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Targets; +import dev.dsf.bpe.v2.variables.Variables; + +public class StoreResults implements ServiceTask, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(StoreResults.class); private final AggregateErrorMailService errorMailService; - private CodeSystem.DsfPingUnits.Code networkSpeedUnit; + private final CodeSystem.DsfPingUnits.Code networkSpeedUnit; - public StoreResults(ProcessPluginApi api, AggregateErrorMailService errorMailService, + public StoreResults(AggregateErrorMailService errorMailService, CodeSystem.DsfPingUnits.Code networkSpeedUnit) { - super(api); this.networkSpeedUnit = networkSpeedUnit; this.errorMailService = errorMailService; } @@ -46,13 +44,11 @@ public StoreResults(ProcessPluginApi api, AggregateErrorMailService errorMailSer @Override public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Objects.requireNonNull(errorMailService, "errorMailService"); } @Override - protected void doExecute(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Storing results for process started with Task {}", variables.getStartTask().getIdElement().getValue()); @@ -60,13 +56,13 @@ protected void doExecute(DelegateExecution execution, Variables variables) throw Targets targets = variables.getTargets(); Map> errorsPerTarget = new HashMap<>(); - ProcessError.toTaskOutput(ErrorListUtils.getErrorList(execution).getEntries()).forEach(task::addOutput); + ProcessError.toTaskOutput(ErrorListUtils.getErrorList(variables).getEntries()).forEach(task::addOutput); targets.getEntries().stream().sorted(Comparator.comparing(Target::getEndpointIdentifierValue)).forEach(target -> { String correlationKey = target.getCorrelationKey(); - ProcessErrors errors = ErrorListUtils.getErrorList(execution, correlationKey); + ProcessErrors errors = ErrorListUtils.getErrorList(variables, correlationKey); CodeSystem.DsfPingStatus.Code statusCode = (CodeSystem.DsfPingStatus.Code) variables .getVariable(ExecutionVariables.statusCode.correlatedValue(correlationKey)); long downloadResourceSizeBytes = variables.getLong(ExecutionVariables.downloadResourceSizeBytes.name()); From c3ef65dd31c3a2607cdea07a6ebd4c629ad31d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 11:07:03 +0200 Subject: [PATCH 23/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../pong/DownloadResourceAndMeasureSpeed.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/DownloadResourceAndMeasureSpeed.java b/src/main/java/dev/dsf/bpe/service/pong/DownloadResourceAndMeasureSpeed.java index a8670f99..3ee0ed61 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/DownloadResourceAndMeasureSpeed.java +++ b/src/main/java/dev/dsf/bpe/service/pong/DownloadResourceAndMeasureSpeed.java @@ -1,30 +1,23 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.BinaryResourceDownloader; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.duration.DurationValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class DownloadResourceAndMeasureSpeed extends AbstractService +public class DownloadResourceAndMeasureSpeed implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(DownloadResourceAndMeasureSpeed.class); - public DownloadResourceAndMeasureSpeed(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Starting resource download to measure speed..."); @@ -36,14 +29,14 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V if (downloadResult.getErrorTuple() == null) { variables.setLong(ExecutionVariables.downloadedBytes.name(), downloadResult.getDownloadedBytes()); - variables.setVariable(ExecutionVariables.downloadedDuration.name(), - new DurationValueImpl(downloadResult.getDownloadedDuration())); + variables.setJsonVariable(ExecutionVariables.downloadedDuration.name(), + downloadResult.getDownloadedDuration()); } else { - delegateExecution.setVariable(ExecutionVariables.resourceDownloadError.name(), + variables.setJsonVariable(ExecutionVariables.resourceDownloadError.name(), downloadResult.getErrorTuple().errorLocal()); - delegateExecution.setVariable(ExecutionVariables.resourceDownloadErrorRemote.name(), + variables.setJsonVariable(ExecutionVariables.resourceDownloadErrorRemote.name(), downloadResult.getErrorTuple().errorRemote()); } logger.debug("Completed resource download and measured speed."); From aba0dd1f42882145ebe03fd5a340c877f7ff0040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:16:39 +0200 Subject: [PATCH 24/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../pong/EstimateCleanupTimerDuration.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/EstimateCleanupTimerDuration.java b/src/main/java/dev/dsf/bpe/service/pong/EstimateCleanupTimerDuration.java index b89b198a..de6a343d 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/EstimateCleanupTimerDuration.java +++ b/src/main/java/dev/dsf/bpe/service/pong/EstimateCleanupTimerDuration.java @@ -3,27 +3,21 @@ import java.time.Duration; import java.util.Optional; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class EstimateCleanupTimerDuration extends AbstractService +public class EstimateCleanupTimerDuration implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(EstimateCleanupTimerDuration.class); - public EstimateCleanupTimerDuration(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Estimating cleanup timer duration..."); final long minTimerDurationMillis = 20000; From ff2f4046e04beeb12cae5027d615e9d340c9092b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:17:52 +0200 Subject: [PATCH 25/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../service/pong/LogAndSaveAndStoreError.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java index 263aad20..ae91d123 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java +++ b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java @@ -1,45 +1,39 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class LogAndSaveAndStoreError extends AbstractService +public class LogAndSaveAndStoreError implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveAndStoreError.class); - public LogAndSaveAndStoreError(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { Target target = variables.getTarget(); Task startTask = variables.getStartTask(); - ProcessError error = (ProcessError) delegateExecution + ProcessError error = variables .getVariable(ExecutionVariables.resourceDownloadError.name()); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); - ProcessError errorRemote = (ProcessError) delegateExecution + ProcessError errorRemote = variables .getVariable(ExecutionVariables.resourceDownloadErrorRemote.name()); - ErrorListUtils.addRemote(errorRemote, delegateExecution); + ErrorListUtils.addRemote(errorRemote, variables); PingStatusGenerator.updatePongStatusOutput(startTask, - ErrorListUtils.getErrorList(delegateExecution).getEntries()); + ErrorListUtils.getErrorList(variables).getEntries()); variables.updateTask(startTask); logger.info("Error while trying to download resource from {}: {}", target.getEndpointUrl(), From c5557014535be2b389c9defcb5208ca82936af1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:18:39 +0200 Subject: [PATCH 26/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../pong/LogAndSaveUploadErrorPong.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java index 60484a97..301f9e07 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java +++ b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java @@ -1,35 +1,29 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class LogAndSaveUploadErrorPong extends AbstractService +public class LogAndSaveUploadErrorPong implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveUploadErrorPong.class); - public LogAndSaveUploadErrorPong(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { - ProcessError error = (ProcessError) variables.getVariable(ExecutionVariables.resourceUploadError.name()); - ErrorListUtils.add(error, execution); + ProcessError error = variables.getVariable(ExecutionVariables.resourceUploadError.name()); + ErrorListUtils.add(error, variables); - ProcessError errorRemote = (ProcessError) variables + ProcessError errorRemote = variables .getVariable(ExecutionVariables.resourceUploadErrorRemote.name()); - ErrorListUtils.addRemote(errorRemote, execution); + ErrorListUtils.addRemote(errorRemote, variables); logger.info("Error while storing binary resource for download: {}", error.concept().getDisplay()); } From f6bea5a6b9854764f3378e6eff7186b7a85e38b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:33:57 +0200 Subject: [PATCH 27/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../dev/dsf/bpe/service/pong/LogPing.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/LogPing.java b/src/main/java/dev/dsf/bpe/service/pong/LogPing.java index 0e18158c..72e93ea5 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/LogPing.java +++ b/src/main/java/dev/dsf/bpe/service/pong/LogPing.java @@ -1,7 +1,5 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Task; @@ -9,29 +7,25 @@ import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class LogPing extends AbstractService +public class LogPing implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogPing.class); - public LogPing(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { Task task = variables.getLatestTask(); logger.info("PING from {} (endpoint: {})", task.getRequester().getIdentifier().getValue(), - getEndpointIdentifierValue(task)); + getEndpointIdentifierValue(api, task)); } - private String getEndpointIdentifierValue(Task task) + private String getEndpointIdentifierValue(ProcessPluginApi api, Task task) { return api.getTaskHelper() .getFirstInputParameterValue(task, CodeSystem.DsfPing.URL, From 73b2676d704f910f189d03938c69754b9873fd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:34:50 +0200 Subject: [PATCH 28/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../bpe/service/pong/SaveTimeoutError.java | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/SaveTimeoutError.java b/src/main/java/dev/dsf/bpe/service/pong/SaveTimeoutError.java index 3a8d0731..b65aa92f 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/SaveTimeoutError.java +++ b/src/main/java/dev/dsf/bpe/service/pong/SaveTimeoutError.java @@ -1,36 +1,30 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SaveTimeoutError extends AbstractService +public class SaveTimeoutError implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SaveTimeoutError.class); - public SaveTimeoutError(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Storing timeout error..."); ProcessError error = new ProcessError(ConstantsPing.PROCESS_NAME_PONG, CodeSystem.DsfPingError.Concept.CLEANUP_MESSAGE_TIMEOUT, null); - ErrorListUtils.add(error, execution); + ErrorListUtils.add(error, variables); logger.debug("Stored timeout error: {}", error.concept().getDisplay()); } From e4be718f280125f33cb4385842a356adeba020a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:53:24 +0200 Subject: [PATCH 29/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute - BpmnMessage.URL -> BpmnMessage.SYSTEM --- .../bpe/service/pong/SelectPongTarget.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java index fa45ac62..13976f18 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java +++ b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java @@ -1,36 +1,29 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.constants.CodeSystems.BpmnMessage; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SelectPongTarget extends AbstractService implements InitializingBean +public class SelectPongTarget implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SelectPongTarget.class); - public SelectPongTarget(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Selecting pong targets..."); Task task = variables.getStartTask(); String correlationKey = api.getTaskHelper() - .getFirstInputParameterStringValue(task, BpmnMessage.URL, BpmnMessage.Codes.CORRELATION_KEY).get(); + .getFirstInputParameterStringValue(task, BpmnMessage.SYSTEM, BpmnMessage.Codes.CORRELATION_KEY).get(); String targetOrganizationIdentifierValue = task.getRequester().getIdentifier().getValue(); String targetEndpointIdentifierValue = variables.getString(ExecutionVariables.targetEndpointIdentifier.name()); @@ -40,7 +33,7 @@ protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables logger.warn( "Pong response target (organization {}, endpoint {}) not found locally or not active, not sending pong", targetOrganizationIdentifierValue, targetEndpointIdentifierValue); - return new BpmnError("target_not_allowed"); + return new ErrorBoundaryEvent("target_not_allowed", null ); }); variables.setTarget(variables.createTarget(targetOrganizationIdentifierValue, targetEndpointIdentifierValue, From f93a2e6392eaddf6a8255a57245c60e157dcb886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 13:55:46 +0200 Subject: [PATCH 30/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../service/pong/SetEndpointIdentifier.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/SetEndpointIdentifier.java b/src/main/java/dev/dsf/bpe/service/pong/SetEndpointIdentifier.java index de6956b6..02ed0f68 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/SetEndpointIdentifier.java +++ b/src/main/java/dev/dsf/bpe/service/pong/SetEndpointIdentifier.java @@ -1,7 +1,5 @@ package dev.dsf.bpe.service.pong; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Task; @@ -10,32 +8,28 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SetEndpointIdentifier extends AbstractService +public class SetEndpointIdentifier implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SetEndpointIdentifier.class); - public SetEndpointIdentifier(ProcessPluginApi api) - { - super(api); - } - @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Setting endpoint identifier..."); Task task = variables.getStartTask(); - String endpointIdentifierValue = getEndpointIdentifierValue(task); + String endpointIdentifierValue = getEndpointIdentifierValue(api, task); variables.setString(ExecutionVariables.targetEndpointIdentifier.name(), endpointIdentifierValue); logger.debug("Set endpoint identifier to " + endpointIdentifierValue); } - private String getEndpointIdentifierValue(Task task) + private String getEndpointIdentifierValue(ProcessPluginApi api, Task task) { return api.getTaskHelper() .getFirstInputParameterValue(task, CodeSystem.DsfPing.URL, From cecfad7d62a81638e2e3bce76b22248b50668c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 25 Jun 2026 14:57:58 +0200 Subject: [PATCH 31/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../bpe/service/pong/StoreDownloadSpeed.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java b/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java index 303cbeaa..a616a993 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java @@ -4,38 +4,36 @@ import java.time.Duration; import java.util.Objects; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class StoreDownloadSpeed extends AbstractService +public class StoreDownloadSpeed implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(StoreDownloadSpeed.class); private CodeSystem.DsfPingUnits.Code networkSpeedUnit; - public StoreDownloadSpeed(ProcessPluginApi api, CodeSystem.DsfPingUnits.Code networkSpeedUnit) + public StoreDownloadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit) { - super(api); this.networkSpeedUnit = networkSpeedUnit; } @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { Task startTask = variables.getStartTask(); logger.debug("Storing download speed..."); long downloadedBytes = variables.getLong(ExecutionVariables.downloadedBytes.name()); - Duration downloadedDuration = (Duration) variables.getVariable(ExecutionVariables.downloadedDuration.name()); + Duration downloadedDuration = variables.getVariable(ExecutionVariables.downloadedDuration.name()); BigDecimal downloadSpeed = null; if (downloadedDuration != null) From 8c3cdf84174287ba21fefb731796c1b85c8e61ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 08:52:52 +0200 Subject: [PATCH 32/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../dev/dsf/bpe/service/pong/StoreErrors.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java b/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java index 571c6881..52b55f67 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java @@ -3,54 +3,50 @@ import java.util.Map; import java.util.Objects; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessErrors; import dev.dsf.bpe.mail.AggregateErrorMailService; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.ErrorListUtils; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Target; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Target; +import dev.dsf.bpe.v2.variables.Variables; -public class StoreErrors extends AbstractService +public class StoreErrors implements ServiceTask, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(StoreErrors.class); private final AggregateErrorMailService errorMailService; - public StoreErrors(ProcessPluginApi api, AggregateErrorMailService errorMailService) + public StoreErrors(AggregateErrorMailService errorMailService) { - super(api); - this.errorMailService = errorMailService; } @Override public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Objects.requireNonNull(errorMailService, "errorMailService"); } @Override - protected void doExecuteWithErrorHandling(DelegateExecution execution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception { Task startTask = variables.getStartTask(); logger.debug("Storing errors..."); - ProcessErrors errors = ErrorListUtils.getErrorList(execution); + ProcessErrors errors = ErrorListUtils.getErrorList(variables); PingStatusGenerator.updatePongStatusOutput(startTask, errors.getEntries()); - CodeSystem.DsfPingStatus.Code status = (CodeSystem.DsfPingStatus.Code) variables + CodeSystem.DsfPingStatus.Code status = variables .getVariable(ExecutionVariables.statusCode.name()); PingStatusGenerator.updatePongStatusOutput(startTask, status); From 43535371e161a0188e95b05f71ec52e50d844703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 08:54:25 +0200 Subject: [PATCH 33/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../bpe/service/pong/StoreUploadSpeed.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java b/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java index 6eb70acb..5a471e2b 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java @@ -5,8 +5,6 @@ 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.DecimalType; import org.hl7.fhir.r4.model.PrimitiveType; import org.hl7.fhir.r4.model.Task; @@ -14,31 +12,31 @@ import org.slf4j.LoggerFactory; import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.service.AbstractService; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class StoreUploadSpeed extends AbstractService +public class StoreUploadSpeed implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(StoreUploadSpeed.class); private CodeSystem.DsfPingUnits.Code networkSpeedUnit; - public StoreUploadSpeed(ProcessPluginApi api, CodeSystem.DsfPingUnits.Code networkSpeedUnit) + public StoreUploadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit) { - super(api); this.networkSpeedUnit = networkSpeedUnit; } @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { Task startTask = variables.getStartTask(); Task cleanup = variables.getLatestTask(); logger.debug("Storing upload speed..."); - Optional uploadedBytesTaskInput = getUploadedBytes(cleanup); - Optional uploadedDurationTaskInput = getUploadedDuration(cleanup); + Optional uploadedBytesTaskInput = getUploadedBytes(api, cleanup); + Optional uploadedDurationTaskInput = getUploadedDuration(api, cleanup); long uploadedBytes = uploadedBytesTaskInput.map(PrimitiveType::getValue).orElse(BigDecimal.valueOf(0)) .longValue(); Duration uploadedDuration = uploadedDurationTaskInput @@ -66,13 +64,13 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V logger.debug("Stored upload speed: " + uploadSpeed + " " + networkSpeedUnit); } - private Optional getUploadedBytes(Task task) + private Optional getUploadedBytes(ProcessPluginApi api, Task task) { return api.getTaskHelper().getFirstInputParameterValue(task, CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.DOWNLOADED_BYTES.getValue(), DecimalType.class); } - private Optional getUploadedDuration(Task task) + private Optional getUploadedDuration(ProcessPluginApi api, Task task) { return api.getTaskHelper().getFirstInputParameterValue(task, CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.DOWNLOADED_DURATION_MILLIS.getValue(), org.hl7.fhir.r4.model.Duration.class); From b5bb449d354d57a87b43a5c939ee8c2ffc257112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 14:29:21 +0200 Subject: [PATCH 34/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute - field injections aren't declared as expressions anymore --- .../java/dev/dsf/bpe/service/Cleanup.java | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/Cleanup.java b/src/main/java/dev/dsf/bpe/service/Cleanup.java index 424b7eb7..76b596de 100644 --- a/src/main/java/dev/dsf/bpe/service/Cleanup.java +++ b/src/main/java/dev/dsf/bpe/service/Cleanup.java @@ -5,50 +5,42 @@ import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpHostConnectException; -import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.camunda.bpm.engine.delegate.Expression; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; import dev.dsf.bpe.util.ErrorListUtils; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.activity.AbstractServiceDelegate; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.WebApplicationException; -public class Cleanup extends AbstractServiceDelegate implements InitializingBean +public class Cleanup implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(Cleanup.class); - private Expression process; + private String process; - public Cleanup(ProcessPluginApi api) - { - super(api); - } - - public void doExecute(DelegateExecution delegateExecution, Variables variables) + @Override + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Cleaning up..."); - String process = (String) this.process.getValue(delegateExecution); - String downloadResourceId = new IdType(variables.getString(ExecutionVariables.downloadResourceReference.name())) .getIdPart(); if (downloadResourceId != null) { try { - api.getFhirWebserviceClientProvider().getLocalWebserviceClient().delete(Binary.class, + api.getDsfClientProvider().getLocal().delete(Binary.class, downloadResourceId); - api.getFhirWebserviceClientProvider().getLocalWebserviceClient().deletePermanently(Binary.class, + api.getDsfClientProvider().getLocal().deletePermanently(Binary.class, downloadResourceId); logger.debug("Deleted Binary resource with ID {}", downloadResourceId); } @@ -57,32 +49,32 @@ public void doExecute(DelegateExecution delegateExecution, Variables variables) if (e.getCause() instanceof SocketTimeoutException timeoutException) { ProcessError error = toProcessError(timeoutException, process); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); logger.error(e.getCause().getMessage()); } else if (e.getCause() instanceof ConnectTimeoutException) { ProcessError error = toProcessErrorConnectTimeout(process); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); logger.error(e.getCause().getMessage()); } else if (e.getCause() instanceof HttpHostConnectException) { ProcessError error = toProcessErrorLocalHttpHostConnect(process); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); logger.error(e.getCause().getMessage()); } else { ProcessError error = new ProcessError(process, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); logger.error("Unexpected error: {}", e.getCause().getMessage()); } } catch (WebApplicationException e) { ProcessError error = toProcessError(e, process); - ErrorListUtils.add(error, delegateExecution); + ErrorListUtils.add(error, variables); } } else @@ -153,7 +145,7 @@ private ProcessError toProcessError(WebApplicationException e, String process) }; } - public void setProcess(Expression process) + public void setProcess(String process) { this.process = process; } From d35e72956014024da17ba92dfc048c4fdcd8b41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 16:39:16 +0200 Subject: [PATCH 35/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute - field injections aren't declared as expressions anymore --- .../bpe/service/GenerateAndStoreResource.java | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java b/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java index 0b7429bd..e2aef6d6 100644 --- a/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java +++ b/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java @@ -5,47 +5,37 @@ import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpHostConnectException; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.camunda.bpm.engine.delegate.Expression; import org.hl7.fhir.r4.model.IdType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; -import dev.dsf.bpe.variables.process_error.ProcessErrorValueImpl; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.WebApplicationException; -public class GenerateAndStoreResource extends AbstractService implements InitializingBean +public class GenerateAndStoreResource implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(GenerateAndStoreResource.class); private final long maxUploadSizeBytes; - private Expression process; + private String process; - public GenerateAndStoreResource(ProcessPluginApi api, long maxUploadSizeBytes) + public GenerateAndStoreResource(long maxUploadSizeBytes) { - super(api); this.maxUploadSizeBytes = maxUploadSizeBytes; } @Override - public void afterPropertiesSet() throws Exception - { - super.afterPropertiesSet(); - } - - public void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Generating resource..."); long downloadResourceSizeBytes = getDownloadResourceSize(variables); - String process = (String) this.process.getValue(delegateExecution); RandomByteInputStream resourceContent; if (downloadResourceSizeBytes > maxUploadSizeBytes) { @@ -65,7 +55,7 @@ public void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Vari try { - IdType downloadResource = storeBinary(resourceContent); + IdType downloadResource = storeBinary(api, resourceContent); String reference = downloadResource.toVersionless().getValueAsString(); @@ -138,11 +128,10 @@ public void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Vari break; } - variables.setVariable(ExecutionVariables.resourceUploadError.name(), new ProcessErrorValueImpl(error)); + variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - new ProcessErrorValueImpl(errorRemote)); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), errorRemote); } } catch (ProcessingException e) @@ -152,11 +141,11 @@ public void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Vari ProcessError error = toProcessErrorLocal(socketTimeoutException, process); ProcessError errorRemote = toProcessErrorRemote(socketTimeoutException, process); - variables.setVariable(ExecutionVariables.resourceUploadError.name(), new ProcessErrorValueImpl(error)); + variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - new ProcessErrorValueImpl(errorRemote)); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), + errorRemote); } } else if (e.getCause() instanceof ConnectTimeoutException) @@ -164,11 +153,11 @@ else if (e.getCause() instanceof ConnectTimeoutException) ProcessError error = toProcessErrorLocalConnectTimeout(process); ProcessError errorRemote = toProcessErrorRemoteConnectTimeout(process); - variables.setVariable(ExecutionVariables.resourceUploadError.name(), new ProcessErrorValueImpl(error)); + variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - new ProcessErrorValueImpl(errorRemote)); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), + errorRemote); } } else if (e.getCause() instanceof HttpHostConnectException) @@ -176,11 +165,11 @@ else if (e.getCause() instanceof HttpHostConnectException) ProcessError error = toProcessErrorLocalHttpHostConnect(process); ProcessError errorRemote = toProcessErrorRemoteHttpHostConnect(process); - variables.setVariable(ExecutionVariables.resourceUploadError.name(), new ProcessErrorValueImpl(error)); + variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - new ProcessErrorValueImpl(errorRemote)); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), + errorRemote); } } else @@ -188,11 +177,11 @@ else if (e.getCause() instanceof HttpHostConnectException) ProcessError error = new ProcessError(process, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null); ProcessError errorRemote = new ProcessError(process, CodeSystem.DsfPingError.Concept.REMOTE_UNKNOWN, null); - variables.setVariable(ExecutionVariables.resourceUploadError.name(), new ProcessErrorValueImpl(error)); + variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - new ProcessErrorValueImpl(errorRemote)); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), + errorRemote); } logger.error("Unexpected error: {}", e.getMessage()); } @@ -277,14 +266,14 @@ private void setDownloadResourceSizeBytes(Variables variables, long resourceSize variables.setLong(ExecutionVariables.downloadResourceSizeBytes.name(), resourceSizeBytes); } - private IdType storeBinary(RandomByteInputStream downloadResourceContent) + private IdType storeBinary(ProcessPluginApi api, RandomByteInputStream downloadResourceContent) { - return api.getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().createBinary( + return api.getDsfClientProvider().getLocal().withMinimalReturn().createBinary( downloadResourceContent, ConstantsPing.DOWNLOAD_RESOURCE_MIME_TYPE, api.getOrganizationProvider().getLocalOrganization().get().getIdElement().getValue()); } - public void setProcess(Expression process) + public void setProcess(String process) { this.process = process; } From 890f6a2ad11a34d2c9e137bcd6082c11c4b2a063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 16:41:34 +0200 Subject: [PATCH 36/68] API v2 changes: - interface instead of superclass -> no api in constructor needed - doExecute renamed to execute --- .../bpe/service/SetDownloadResourceSize.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/SetDownloadResourceSize.java b/src/main/java/dev/dsf/bpe/service/SetDownloadResourceSize.java index e3bc7fe7..49a6797b 100644 --- a/src/main/java/dev/dsf/bpe/service/SetDownloadResourceSize.java +++ b/src/main/java/dev/dsf/bpe/service/SetDownloadResourceSize.java @@ -2,8 +2,6 @@ import java.util.Optional; -import org.camunda.bpm.engine.delegate.BpmnError; -import org.camunda.bpm.engine.delegate.DelegateExecution; import org.hl7.fhir.r4.model.DecimalType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,17 +9,18 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ServiceTask; +import dev.dsf.bpe.v2.error.ErrorBoundaryEvent; +import dev.dsf.bpe.v2.variables.Variables; -public class SetDownloadResourceSize extends AbstractService +public class SetDownloadResourceSize implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(SetDownloadResourceSize.class); private final long maxDownloadResourceSizeBytes; - public SetDownloadResourceSize(ProcessPluginApi api, long maxDownloadResourceSizeBytes) + public SetDownloadResourceSize(long maxDownloadResourceSizeBytes) { - super(api); if (maxDownloadResourceSizeBytes < 0) { this.maxDownloadResourceSizeBytes = 0L; @@ -33,11 +32,11 @@ public SetDownloadResourceSize(ProcessPluginApi api, long maxDownloadResourceSiz } @Override - protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, Variables variables) throws BpmnError + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Setting download resource size..."); - long downloadResourceSizeBytes = getDownloadResourceSizeBytes(variables); + long downloadResourceSizeBytes = getDownloadResourceSizeBytes(api, variables); variables.setLong(ExecutionVariables.downloadResourceSizeBytes.name(), downloadResourceSizeBytes); logger.debug("Set download resource size to " + downloadResourceSizeBytes); @@ -47,7 +46,7 @@ protected void doExecuteWithErrorHandling(DelegateExecution delegateExecution, V logger.debug("Set maximum download resource size to " + maxDownloadResourceSizeBytes); } - private long getDownloadResourceSizeBytes(Variables variables) + private long getDownloadResourceSizeBytes(ProcessPluginApi api, Variables variables) { Optional downloadResourceSizeType = api.getTaskHelper().getFirstInputParameterValue( variables.getStartTask(), CodeSystem.DsfPing.URL, From abaa4920ff7e60caae7f5e0d82a38bd60b8c51c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 16:42:27 +0200 Subject: [PATCH 37/68] Updated import statements --- .../bpe/util/task/output/generator/PingStatusGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java b/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java index 46395923..4b0f89d8 100644 --- a/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java @@ -19,9 +19,9 @@ import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.PingProcessPluginDefinition; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.v1.constants.NamingSystems.EndpointIdentifier; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; -import dev.dsf.bpe.v1.variables.Target; +import dev.dsf.bpe.v2.constants.NamingSystems.EndpointIdentifier; +import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; +import dev.dsf.bpe.v2.variables.Target; public final class PingStatusGenerator { From 71ef6dda8137e2e76ca2c9338807575cb5f84fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 16:58:47 +0200 Subject: [PATCH 38/68] API v2 changes: - updated import statements - FhirWebserviceClient -> DsfClient --- .../java/dev/dsf/bpe/util/BinaryResourceDownloader.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java b/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java index 01a82a1b..e554e6c3 100644 --- a/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java +++ b/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java @@ -19,8 +19,8 @@ import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.variables.Variables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.variables.Variables; import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.WebApplicationException; @@ -63,8 +63,8 @@ public DownloadResult download(Variables variables, ProcessPluginApi api, Task t String webserviceUrl = downloadResourceReferenceIdType.getBaseUrl(); try { - InputStream binaryResourceInputStream = api.getFhirWebserviceClientProvider() - .getWebserviceClient(webserviceUrl) + InputStream binaryResourceInputStream = api.getDsfClientProvider() + .getByEndpointUrl(webserviceUrl) .readBinary(downloadResourceReferenceId, ConstantsPing.DOWNLOAD_RESOURCE_MIME_TYPE); try (binaryResourceInputStream) From d805c28b448967b1da57a856d1b8b239a4c20f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 17:00:01 +0200 Subject: [PATCH 39/68] API v2 changes: - Variables replaces DelegateExecution --- .../java/dev/dsf/bpe/util/ErrorListUtils.java | 100 +++++++++--------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/util/ErrorListUtils.java b/src/main/java/dev/dsf/bpe/util/ErrorListUtils.java index 0df63dc7..edc47a8e 100644 --- a/src/main/java/dev/dsf/bpe/util/ErrorListUtils.java +++ b/src/main/java/dev/dsf/bpe/util/ErrorListUtils.java @@ -1,168 +1,166 @@ package dev.dsf.bpe.util; -import org.camunda.bpm.engine.delegate.DelegateExecution; - import dev.dsf.bpe.ExecutionVariables; import dev.dsf.bpe.ProcessError; import dev.dsf.bpe.ProcessErrors; -import dev.dsf.bpe.variables.process_errors.ProcessErrorsValueImpl; +import dev.dsf.bpe.v2.variables.Variables; public class ErrorListUtils { - public static void addAll(ProcessErrors errors, DelegateExecution execution) + public static void addAll(ProcessErrors errors, Variables variables) { - ProcessErrors errorList = getErrorList(execution); + ProcessErrors errorList = getErrorList(variables); if (errors != null) { errorList.addAll(errors); - saveErrorList(errorList, execution, null); + saveErrorList(errorList, variables, null); } } - public static void addAll(ProcessErrors errors, DelegateExecution execution, String correlationKey) + public static void addAll(ProcessErrors errors, Variables variables, String correlationKey) { - ProcessErrors errorList = correlationKey != null ? getErrorList(execution, correlationKey) - : getErrorList(execution); + ProcessErrors errorList = correlationKey != null ? getErrorList(variables, correlationKey) + : getErrorList(variables); if (errors != null) { errorList.addAll(errors); - saveErrorList(errorList, execution, correlationKey); + saveErrorList(errorList, variables, correlationKey); } } - public static void addAllRemote(ProcessErrors errors, DelegateExecution execution) + public static void addAllRemote(ProcessErrors errors, Variables variables) { - ProcessErrors errorList = getErrorListRemote(execution); + ProcessErrors errorList = getErrorListRemote(variables); if (errors != null) { errorList.addAll(errors); - saveErrorListRemote(errorList, execution, null); + saveErrorListRemote(errorList, variables, null); } } - public static void addAllRemote(ProcessErrors errors, DelegateExecution execution, String correlationKey) + public static void addAllRemote(ProcessErrors errors, Variables variables, String correlationKey) { - ProcessErrors errorList = correlationKey != null ? getErrorListRemote(execution, correlationKey) - : getErrorListRemote(execution); + ProcessErrors errorList = correlationKey != null ? getErrorListRemote(variables, correlationKey) + : getErrorListRemote(variables); if (errors != null) { errorList.addAll(errors); - saveErrorListRemote(errorList, execution, correlationKey); + saveErrorListRemote(errorList, variables, correlationKey); } } - public static void add(ProcessError error, DelegateExecution execution) + public static void add(ProcessError error, Variables variables) { - add(error, execution, null); + add(error, variables, null); } - public static void add(ProcessError error, DelegateExecution execution, String correlationKey) + public static void add(ProcessError error, Variables variables, String correlationKey) { if (correlationKey != null) { - add(error, ExecutionVariables.errors.correlatedValue(correlationKey), execution); + add(error, ExecutionVariables.errors.correlatedValue(correlationKey), variables); } else { - add(error, ExecutionVariables.errors.name(), execution); + add(error, ExecutionVariables.errors.name(), variables); } } - public static void addRemote(ProcessError error, DelegateExecution execution) + public static void addRemote(ProcessError error, Variables variables) { - addRemote(error, execution, null); + addRemote(error, variables, null); } - public static void addRemote(ProcessError error, DelegateExecution execution, String correlationKey) + public static void addRemote(ProcessError error, Variables variables, String correlationKey) { if (correlationKey != null) { - add(error, ExecutionVariables.errorsRemote.correlatedValue(correlationKey), execution); + add(error, ExecutionVariables.errorsRemote.correlatedValue(correlationKey), variables); } else { - add(error, ExecutionVariables.errorsRemote.name(), execution); + add(error, ExecutionVariables.errorsRemote.name(), variables); } } - public static ProcessErrors getErrorList(DelegateExecution execution) + public static ProcessErrors getErrorList(Variables variables) { - return getErrorList(execution, null); + return getErrorList(variables, null); } - public static ProcessErrors getErrorList(DelegateExecution execution, String correlationKey) + public static ProcessErrors getErrorList(Variables variables, String correlationKey) { if (correlationKey != null) { - return getErrorList(ExecutionVariables.errors.correlatedValue(correlationKey), execution); + return getErrorList(ExecutionVariables.errors.correlatedValue(correlationKey), variables); } else { - return getErrorList(ExecutionVariables.errors.name(), execution); + return getErrorList(ExecutionVariables.errors.name(), variables); } } - public static ProcessErrors getErrorListRemote(DelegateExecution execution) + public static ProcessErrors getErrorListRemote(Variables variables) { - return getErrorListRemote(execution, null); + return getErrorListRemote(variables, null); } - public static ProcessErrors getErrorListRemote(DelegateExecution execution, String correlationKey) + public static ProcessErrors getErrorListRemote(Variables variables, String correlationKey) { if (correlationKey != null) { - return getErrorList(ExecutionVariables.errorsRemote.correlatedValue(correlationKey), execution); + return getErrorList(ExecutionVariables.errorsRemote.correlatedValue(correlationKey), variables); } else { - return getErrorList(ExecutionVariables.errorsRemote.name(), execution); + return getErrorList(ExecutionVariables.errorsRemote.name(), variables); } } - public static ProcessErrors getErrorList(String variableName, DelegateExecution execution) + public static ProcessErrors getErrorList(String variableName, Variables variables) { - ProcessErrors errors = (ProcessErrors) execution.getVariable(variableName); + ProcessErrors errors = variables.getVariable(variableName); if (errors == null) { errors = new ProcessErrors(); - saveErrorList(errors, variableName, execution); + saveErrorList(errors, variableName, variables); } return errors; } - public static void add(ProcessError error, String variableName, DelegateExecution execution) + public static void add(ProcessError error, String variableName, Variables variables) { - ProcessErrors errors = getErrorList(variableName, execution); + ProcessErrors errors = getErrorList(variableName, variables); errors.add(error); - saveErrorList(errors, variableName, execution); + saveErrorList(errors, variableName, variables); } - private static void saveErrorList(ProcessErrors errors, DelegateExecution execution, String correlationKey) + private static void saveErrorList(ProcessErrors errors, Variables variables, String correlationKey) { if (correlationKey != null) { - saveErrorList(errors, ExecutionVariables.errors.correlatedValue(correlationKey), execution); + saveErrorList(errors, ExecutionVariables.errors.correlatedValue(correlationKey), variables); } else { - saveErrorList(errors, ExecutionVariables.errors.name(), execution); + saveErrorList(errors, ExecutionVariables.errors.name(), variables); } } - private static void saveErrorListRemote(ProcessErrors errors, DelegateExecution execution, String correlationKey) + private static void saveErrorListRemote(ProcessErrors errors, Variables variables, String correlationKey) { if (correlationKey != null) { - saveErrorList(errors, ExecutionVariables.errorsRemote.correlatedValue(correlationKey), execution); + saveErrorList(errors, ExecutionVariables.errorsRemote.correlatedValue(correlationKey), variables); } else { - saveErrorList(errors, ExecutionVariables.errorsRemote.name(), execution); + saveErrorList(errors, ExecutionVariables.errorsRemote.name(), variables); } } - private static void saveErrorList(ProcessErrors errors, String variableName, DelegateExecution execution) + private static void saveErrorList(ProcessErrors errors, String variableName, Variables variables) { - execution.setVariable(variableName, new ProcessErrorsValueImpl(errors)); + variables.setJsonVariable(variableName, errors); } } From 373b8e90b0153675ae2183e7b2d6b92a75022725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 17:16:06 +0200 Subject: [PATCH 40/68] API v2 changes: - Extend AbstractProcessPluginDefinition in PingProcessPluginDefinition instead of implementing ProcessPluginDefinition to make use of plugin.properties which removes duplication of data such as the version and release date in ProcessPluginDefinition implementations and pom.xml --- pom.xml | 6 ++++ .../dsf/bpe/PingProcessPluginDefinition.java | 34 ++----------------- src/main/resources/plugin.properties | 6 ++++ 3 files changed, 14 insertions(+), 32 deletions(-) create mode 100644 src/main/resources/plugin.properties diff --git a/pom.xml b/pom.xml index e4ccd457..c40835f2 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,8 @@ jar + 2026-07-05T12:00:00+02:00 + UTF-8 17 17 @@ -21,6 +23,10 @@ dsf-process-ping-pong DSF ping-pong process for connection tests between DSF instances https://github.com/datasharingframework/dsf-process-ping-pong + + Data Sharing Framework + dsf.dev + scm:git:git://github.com/datasharingframework/dsf-process-ping-pong.git diff --git a/src/main/java/dev/dsf/bpe/PingProcessPluginDefinition.java b/src/main/java/dev/dsf/bpe/PingProcessPluginDefinition.java index 517a0ffa..fdbe7073 100644 --- a/src/main/java/dev/dsf/bpe/PingProcessPluginDefinition.java +++ b/src/main/java/dev/dsf/bpe/PingProcessPluginDefinition.java @@ -1,44 +1,14 @@ package dev.dsf.bpe; -import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; import dev.dsf.bpe.spring.config.PingConfig; -import dev.dsf.bpe.v1.ProcessPluginDefinition; +import dev.dsf.bpe.v2.AbstractProcessPluginDefinition; -public class PingProcessPluginDefinition implements ProcessPluginDefinition +public class PingProcessPluginDefinition extends AbstractProcessPluginDefinition { - public static final String RESOURCE_VERSION = "2.1"; - public static final String NON_RESOURCE_VERSION = "0.0"; - public static final String VERSION = RESOURCE_VERSION + "." + NON_RESOURCE_VERSION; - public static final LocalDate RELEASE_DATE = LocalDate.of(2025, 11, 25); - - @Override - public String getName() - { - return "dsf-process-ping-pong"; - } - - @Override - public String getVersion() - { - return VERSION; - } - - @Override - public String getResourceVersion() - { - return RESOURCE_VERSION; - } - - @Override - public LocalDate getReleaseDate() - { - return RELEASE_DATE; - } - @Override public List getProcessModels() { diff --git a/src/main/resources/plugin.properties b/src/main/resources/plugin.properties new file mode 100644 index 00000000..5ef8b65a --- /dev/null +++ b/src/main/resources/plugin.properties @@ -0,0 +1,6 @@ +release-date=${project.build.outputTimestamp} +version=${project.version} +name=${project.artifactId} +title=${project.description} +publisher=${project.organization.name} +publisher-email=mail@test.com \ No newline at end of file From cb73b9c184fc99dec1fc0a8c2b522b366d6338cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 17:50:46 +0200 Subject: [PATCH 41/68] API v2 changes: - Use ActivityPrototypeBeanCreator for all activities that have a no-argument constructor - No more need for serializers because variables.setJsonVariable takes care of serialization - Activities with constructor arguments don't need ProcessPluginApi injected anymore --- .../dev/dsf/bpe/spring/config/PingConfig.java | 226 ++---------------- 1 file changed, 20 insertions(+), 206 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java index facf729a..3ff22779 100644 --- a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java +++ b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java @@ -44,12 +44,9 @@ import dev.dsf.bpe.service.pong.StoreDownloadSpeed; import dev.dsf.bpe.service.pong.StoreErrors; import dev.dsf.bpe.service.pong.StoreUploadSpeed; -import dev.dsf.bpe.v1.ProcessPluginApi; -import dev.dsf.bpe.v1.documentation.ProcessDocumentation; -import dev.dsf.bpe.variables.codesystem.dsfpingstatus.CodeValueSerializer; -import dev.dsf.bpe.variables.duration.DurationValueSerializer; -import dev.dsf.bpe.variables.process_error.ProcessErrorValueSerializer; -import dev.dsf.bpe.variables.process_errors.ProcessErrorsValueSerializer; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.documentation.ProcessDocumentation; +import dev.dsf.bpe.v2.spring.ActivityPrototypeBeanCreator; @Configuration public class PingConfig implements InitializingBean @@ -117,24 +114,23 @@ public void afterPropertiesSet() throws Exception } @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public PingPongProcessPluginDeploymentStateListener pingPongProcessPluginDeploymentStateListener() + public static ActivityPrototypeBeanCreator activityPrototypeBeanCreator() { - return new PingPongProcessPluginDeploymentStateListener(api); + return new ActivityPrototypeBeanCreator(SetTargetAndConfigureTimer.class, SendStartPing.class, + SetPongTimeoutDuration.class, SelectPingTargets.class, SendPingMessage.class, + SetCorrelationKeyListener.class, LogPing.class, SelectPongTarget.class, SendPongMessage.class, + CheckPingTaskStatus.class, CleanupPongMessage.class, DownloadResourceAndMeasureSpeed.class, + DownloadResourceAndMeasureSpeedInSubProcess.class, Cleanup.class, LogAndSaveAndStoreError.class, + LogAndSaveError.class, EstimateCleanupTimerDuration.class, SavePong.class, SetEndpointIdentifier.class, + LogAndSaveSendError.class, SaveTimeoutError.class, LogAndSaveUploadErrorPing.class, + LogAndSaveUploadErrorPong.class); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SetTargetAndConfigureTimer setTargetAndConfigureTimer() - { - return new SetTargetAndConfigureTimer(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SendStartPing sendStartPing() + public PingPongProcessPluginDeploymentStateListener pingPongProcessPluginDeploymentStateListener() { - return new SendStartPing(api); + return new PingPongProcessPluginDeploymentStateListener(api); } @Bean @@ -151,231 +147,49 @@ public AggregateErrorMailService aggregateErrorMailServicePong() AggregateErrorMailService.PONG_PROCESS_HAS_ERRORS); } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SetPongTimeoutDuration setPongTimeoutDuration() - { - return new SetPongTimeoutDuration(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SelectPingTargets selectPingTargets() - { - return new SelectPingTargets(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SendPingMessage sendPing() - { - return new SendPingMessage(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SetCorrelationKeyListener setCorrelationKeyListener() - { - return new SetCorrelationKeyListener(api); - } - @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public StoreResults savePingResults() { - return new StoreResults(api, aggregateErrorMailServicePing(), networkSpeedUnit); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogPing logPing() - { - return new LogPing(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SelectPongTarget selectPongTarget() - { - return new SelectPongTarget(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SendPongMessage sendPong() - { - return new SendPongMessage(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public CheckPingTaskStatus logAndSaveNoResponse() - { - return new CheckPingTaskStatus(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public CleanupPongMessage cleanupPongMessage() - { - return new CleanupPongMessage(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public DownloadResourceAndMeasureSpeed downloadResourceAndMeasureSpeed() - { - return new DownloadResourceAndMeasureSpeed(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public DownloadResourceAndMeasureSpeedInSubProcess downloadResourceAndMeasureSpeedInSubProcess() - { - return new DownloadResourceAndMeasureSpeedInSubProcess(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public Cleanup cleanup() - { - return new Cleanup(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogAndSaveAndStoreError logAndSaveAndStoreError() - { - return new LogAndSaveAndStoreError(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogAndSaveError logAndSaveError() - { - return new LogAndSaveError(api); + return new StoreResults(aggregateErrorMailServicePing(), networkSpeedUnit); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public StoreUploadSpeed storeDownloadSpeeds() { - return new StoreUploadSpeed(api, networkSpeedUnit); + return new StoreUploadSpeed(networkSpeedUnit); } - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public EstimateCleanupTimerDuration estimateCleanupTimerDuration() - { - return new EstimateCleanupTimerDuration(api); - } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public SetDownloadResourceSize setDownloadResourceSize() { - return new SetDownloadResourceSize(api, maxDownloadSizeBytes); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SavePong savePong() - { - return new SavePong(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SetEndpointIdentifier setEndpointIdentifier() - { - return new SetEndpointIdentifier(api); + return new SetDownloadResourceSize(maxDownloadSizeBytes); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public StoreDownloadSpeed storeDownloadSpeed() { - return new StoreDownloadSpeed(api, networkSpeedUnit); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogAndSaveSendError logAndSaveSendError() - { - return new LogAndSaveSendError(api); + return new StoreDownloadSpeed(networkSpeedUnit); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public GenerateAndStoreResource generateAndStoreResource() { - return new GenerateAndStoreResource(api, maxUploadSizeBytes); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public SaveTimeoutError saveTimeoutError() - { - return new SaveTimeoutError(api); + return new GenerateAndStoreResource(maxUploadSizeBytes); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public StoreErrors storeErrors() { - return new StoreErrors(api, aggregateErrorMailServicePong()); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogAndSaveUploadErrorPing logAndSaveUploadErrorPing() - { - return new LogAndSaveUploadErrorPing(api); - } - - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public LogAndSaveUploadErrorPong logAndSaveUploadErrorPong() - { - return new LogAndSaveUploadErrorPong(api); - } - - @Bean - public CodeValueSerializer pingStatusCodeSerializer() - { - return new CodeValueSerializer(); + return new StoreErrors(aggregateErrorMailServicePong()); } - @Bean - public DurationValueSerializer durationValueSerializer( - @Qualifier(OBJECT_MAPPER_WITH_TIME_MODULE) ObjectMapper objectMapper) - { - return new DurationValueSerializer(objectMapper); - } - - @Bean - public ProcessErrorValueSerializer processErrorValueSerializer() - { - return new ProcessErrorValueSerializer(); - } - - @Bean - public ProcessErrorsValueSerializer processErrorsValueSerializer() - { - return new ProcessErrorsValueSerializer(); - } - - @Bean(name = OBJECT_MAPPER_WITH_TIME_MODULE) - public ObjectMapper objectMapperWithJavaTimeModule() - { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - return objectMapper; - } - - private static final String OBJECT_MAPPER_WITH_TIME_MODULE = "objectMapperWithJavaTimeModule"; - private void fixMaxResourceSizes() { if (getMaxDownloadSizeBytes() < 0) From b6034ce0cc0aca28a751072a2d6b19a37a1b2318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 17:52:12 +0200 Subject: [PATCH 42/68] Starters are not needed anymore --- .../start/Ping3DicFromTtpExampleStarter.java | 46 ---------------- .../start/PingTtpsFromDic1ExampleStarter.java | 54 ------------------- ...utostartPing3DicFromTtpExampleStarter.java | 53 ------------------ ...utostartPing3DicFromTtpExampleStarter.java | 47 ---------------- 4 files changed, 200 deletions(-) delete mode 100644 src/test/java/dev/dsf/bpe/start/Ping3DicFromTtpExampleStarter.java delete mode 100644 src/test/java/dev/dsf/bpe/start/PingTtpsFromDic1ExampleStarter.java delete mode 100644 src/test/java/dev/dsf/bpe/start/StartAutostartPing3DicFromTtpExampleStarter.java delete mode 100644 src/test/java/dev/dsf/bpe/start/StopAutostartPing3DicFromTtpExampleStarter.java diff --git a/src/test/java/dev/dsf/bpe/start/Ping3DicFromTtpExampleStarter.java b/src/test/java/dev/dsf/bpe/start/Ping3DicFromTtpExampleStarter.java deleted file mode 100644 index 3778876b..00000000 --- a/src/test/java/dev/dsf/bpe/start/Ping3DicFromTtpExampleStarter.java +++ /dev/null @@ -1,46 +0,0 @@ -package dev.dsf.bpe.start; - -import java.util.Date; - -import org.hl7.fhir.r4.model.ResourceType; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.Task; - -import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; - -public class Ping3DicFromTtpExampleStarter -{ - // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate - // dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 - // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate - // password - public static void main(String[] args) throws Exception - { - ExampleStarter.forServer(args, ConstantsExampleStarters.TTP_FHIR_BASE_URL).startWith(task()); - } - - private static Task task() - { - var def = new PingProcessPluginDefinition(); - - Task task = new Task(); - task.getMeta().addProfile(ConstantsPing.PROFILE_DSF_TASK_START_PING + "|" + def.getResourceVersion()); - task.setInstantiatesCanonical(ConstantsPing.PROFILE_DSF_TASK_PING_PROCESS_URI + "|" + def.getResourceVersion()); - task.setStatus(Task.TaskStatus.REQUESTED); - task.setIntent(Task.TaskIntent.ORDER); - task.setAuthoredOn(new Date()); - task.getRequester().setType(ResourceType.Organization.name()).setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - task.getRestriction().addRecipient().setType(ResourceType.Organization.name()) - .setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - - task.addInput().setValue(new StringType(ConstantsPing.PROFILE_DSF_TASK_START_PING_MESSAGE_NAME)).getType() - .addCoding(BpmnMessage.messageName()); - - return task; - } -} diff --git a/src/test/java/dev/dsf/bpe/start/PingTtpsFromDic1ExampleStarter.java b/src/test/java/dev/dsf/bpe/start/PingTtpsFromDic1ExampleStarter.java deleted file mode 100644 index ceec3006..00000000 --- a/src/test/java/dev/dsf/bpe/start/PingTtpsFromDic1ExampleStarter.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.dsf.bpe.start; - -import java.util.Date; - -import org.hl7.fhir.r4.model.ResourceType; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.Task; - -import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; - -public class PingTtpsFromDic1ExampleStarter -{ - // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate - // dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 - // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate - // password - public static void main(String[] args) throws Exception - { - ExampleStarter.forServer(args, ConstantsExampleStarters.DIC_1_FHIR_BASE_URL).startWith(task()); - } - - private static Task task() - { - var def = new PingProcessPluginDefinition(); - - Task task = new Task(); - task.getMeta().addProfile(ConstantsPing.PROFILE_DSF_TASK_START_PING + "|" + def.getResourceVersion()); - task.setInstantiatesCanonical(ConstantsPing.PROFILE_DSF_TASK_PING_PROCESS_URI + "|" + def.getResourceVersion()); - task.setStatus(Task.TaskStatus.REQUESTED); - task.setIntent(Task.TaskIntent.ORDER); - task.setAuthoredOn(new Date()); - task.getRequester().setType(ResourceType.Organization.name()).setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_DIC_1)); - task.getRestriction().addRecipient().setType(ResourceType.Organization.name()) - .setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_DIC_1)); - - task.addInput().setValue(new StringType(ConstantsPing.PROFILE_DSF_TASK_START_PING_MESSAGE_NAME)).getType() - .addCoding(BpmnMessage.messageName()); - - task.addInput().setValue(new StringType( - "OrganizationAffiliation?primary-organization:identifier=http://dsf.dev/sid/organization-identifier|highmed.org" - + "&role=http://dsf.dev/fhir/CodeSystem/organization-role|TTP" - + "&_include=OrganizationAffiliation:endpoint")) - .getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()); - - return task; - } -} diff --git a/src/test/java/dev/dsf/bpe/start/StartAutostartPing3DicFromTtpExampleStarter.java b/src/test/java/dev/dsf/bpe/start/StartAutostartPing3DicFromTtpExampleStarter.java deleted file mode 100644 index 396f424e..00000000 --- a/src/test/java/dev/dsf/bpe/start/StartAutostartPing3DicFromTtpExampleStarter.java +++ /dev/null @@ -1,53 +0,0 @@ -package dev.dsf.bpe.start; - -import java.util.Date; - -import org.hl7.fhir.r4.model.ResourceType; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.Task; - -import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; - -public class StartAutostartPing3DicFromTtpExampleStarter -{ - // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate - // dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 - // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate - // password - public static void main(String[] args) throws Exception - { - ExampleStarter.forServer(args, ConstantsExampleStarters.TTP_FHIR_BASE_URL).startWith(task()); - } - - private static Task task() - { - var def = new PingProcessPluginDefinition(); - - Task task = new Task(); - task.getMeta().addProfile(ConstantsPing.PROFILE_DSF_TASK_START_PING_AUTOSTART + "|" + def.getResourceVersion()); - task.setInstantiatesCanonical( - ConstantsPing.PROFILE_DSF_TASK_START_PING_AUTOSTART_PROCESS_URI + "|" + def.getResourceVersion()); - task.setStatus(Task.TaskStatus.REQUESTED); - task.setIntent(Task.TaskIntent.ORDER); - task.setAuthoredOn(new Date()); - task.getRequester().setType(ResourceType.Organization.name()).setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - task.getRestriction().addRecipient().setType(ResourceType.Organization.name()) - .setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - - task.addInput().setValue(new StringType(ConstantsPing.PROFILE_DSF_TASK_START_PING_AUTOSTART_MESSAGE_NAME)) - .getType().addCoding(BpmnMessage.messageName()); - task.addInput().setValue(new StringType("Endpoint?identifier=http://dsf.dev/sid/endpoint-identifier|")) - .getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()); - task.addInput().setValue(new StringType("PT7M")).getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TIMER_INTERVAL.getValue()); - - return task; - } -} diff --git a/src/test/java/dev/dsf/bpe/start/StopAutostartPing3DicFromTtpExampleStarter.java b/src/test/java/dev/dsf/bpe/start/StopAutostartPing3DicFromTtpExampleStarter.java deleted file mode 100644 index 94bc4d35..00000000 --- a/src/test/java/dev/dsf/bpe/start/StopAutostartPing3DicFromTtpExampleStarter.java +++ /dev/null @@ -1,47 +0,0 @@ -package dev.dsf.bpe.start; - -import java.util.Date; - -import org.hl7.fhir.r4.model.ResourceType; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.Task; - -import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; - -public class StopAutostartPing3DicFromTtpExampleStarter -{ - // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate - // dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 - // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate - // password - public static void main(String[] args) throws Exception - { - ExampleStarter.forServer(args, ConstantsExampleStarters.TTP_FHIR_BASE_URL).startWith(task()); - } - - private static Task task() - { - var def = new PingProcessPluginDefinition(); - - Task task = new Task(); - task.getMeta().addProfile(ConstantsPing.PROFILE_DSF_TASK_STOP_PING_AUTOSTART + "|" + def.getResourceVersion()); - task.setInstantiatesCanonical( - ConstantsPing.PROFILE_DSF_TASK_STOP_PING_AUTOSTART_PROCESS_URI + "|" + def.getResourceVersion()); - task.setStatus(Task.TaskStatus.REQUESTED); - task.setIntent(Task.TaskIntent.ORDER); - task.setAuthoredOn(new Date()); - task.getRequester().setType(ResourceType.Organization.name()).setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - task.getRestriction().addRecipient().setType(ResourceType.Organization.name()) - .setIdentifier(OrganizationIdentifier - .withValue(ConstantsExampleStarters.NAMINGSYSTEM_DSF_ORGANIZATION_IDENTIFIER_VALUE_TTP)); - - task.addInput().setValue(new StringType(ConstantsPing.PROFILE_DSF_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME)) - .getType().addCoding(BpmnMessage.messageName()); - - return task; - } -} From 2c7e4e393098a2d41719fb55fc8ae803b7ced424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Fri, 26 Jun 2026 17:52:30 +0200 Subject: [PATCH 43/68] Update import statement --- src/test/java/dev/dsf/bpe/PingProcessPluginDefinitionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/dev/dsf/bpe/PingProcessPluginDefinitionTest.java b/src/test/java/dev/dsf/bpe/PingProcessPluginDefinitionTest.java index 55e289ab..69e74619 100644 --- a/src/test/java/dev/dsf/bpe/PingProcessPluginDefinitionTest.java +++ b/src/test/java/dev/dsf/bpe/PingProcessPluginDefinitionTest.java @@ -8,7 +8,7 @@ import org.junit.Test; -import dev.dsf.bpe.v1.ProcessPluginDefinition; +import dev.dsf.bpe.v2.ProcessPluginDefinition; public class PingProcessPluginDefinitionTest { From 7390ee93be4e8b1d721e657c5d42ca6683a28756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:21:53 +0200 Subject: [PATCH 44/68] No longer need custom serialization because Variables#setJsonVariable offers serialization for any type --- .../GenericPrimitiveTypeSerializer.java | 100 ------------------ .../codesystem/dsfpingstatus/CodeValue.java | 9 -- .../dsfpingstatus/CodeValueImpl.java | 26 ----- .../dsfpingstatus/CodeValueSerializer.java | 18 ---- .../dsfpingstatus/CodeValueTypeImpl.java | 35 ------ .../bpe/variables/duration/DurationValue.java | 9 -- .../variables/duration/DurationValueImpl.java | 25 ----- .../duration/DurationValueSerializer.java | 19 ---- .../duration/DurationValueTypeImpl.java | 34 ------ .../process_error/ProcessErrorValue.java | 9 -- .../process_error/ProcessErrorValueImpl.java | 26 ----- .../ProcessErrorValueSerializer.java | 16 --- .../ProcessErrorValueTypeImpl.java | 36 ------- .../process_errors/ProcessErrorsValue.java | 9 -- .../ProcessErrorsValueImpl.java | 26 ----- .../ProcessErrorsValueSerializer.java | 16 --- .../ProcessErrorsValueTypeImpl.java | 36 ------- 17 files changed, 449 deletions(-) delete mode 100644 src/main/java/dev/dsf/bpe/variables/GenericPrimitiveTypeSerializer.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValue.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueSerializer.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueTypeImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/duration/DurationValue.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/duration/DurationValueImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/duration/DurationValueSerializer.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/duration/DurationValueTypeImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValue.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueSerializer.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueTypeImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValue.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueImpl.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueSerializer.java delete mode 100644 src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueTypeImpl.java diff --git a/src/main/java/dev/dsf/bpe/variables/GenericPrimitiveTypeSerializer.java b/src/main/java/dev/dsf/bpe/variables/GenericPrimitiveTypeSerializer.java deleted file mode 100644 index 9702968b..00000000 --- a/src/main/java/dev/dsf/bpe/variables/GenericPrimitiveTypeSerializer.java +++ /dev/null @@ -1,100 +0,0 @@ -package dev.dsf.bpe.variables; - -import java.lang.reflect.InvocationTargetException; -import java.util.Objects; - -import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; -import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; -import org.camunda.bpm.engine.variable.value.PrimitiveValue; -import org.springframework.beans.factory.InitializingBean; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -public abstract class GenericPrimitiveTypeSerializer & PrimitiveValue> - extends PrimitiveValueSerializer implements InitializingBean -{ - private final ObjectMapper objectMapper; - private final Class typeClass; - private final Class valueClass; - private final PrimitiveValueType primitiveValueType; - - public GenericPrimitiveTypeSerializer(PrimitiveValueType variableType, ObjectMapper objectMapper, - Class typeClass, Class valueClass) - { - super(variableType); - this.objectMapper = objectMapper; - this.typeClass = typeClass; - this.valueClass = valueClass; - this.primitiveValueType = variableType; - } - - @Override - public void afterPropertiesSet() - { - Objects.requireNonNull(objectMapper); - } - - @Override - public T readValue(ValueFields valueFields, boolean asTransientValue) - { - try - { - byte[] bytes = valueFields.getByteArrayValue(); - return (bytes == null || bytes.length == 0) ? null - : typeClass.getConstructor(valueClass, PrimitiveValueType.class) - .newInstance(objectMapper.readValue(bytes, valueClass), primitiveValueType); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - - @Override - public void writeValue(T value, ValueFields valueFields) - { - try - { - valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(value.getValue())); - } - catch (JsonProcessingException e) - { - throw new RuntimeException(e); - } - } - - @Override - public T convertToTypedValue(UntypedValueImpl untypedValue) - { - try - { - if (untypedValue != null && typeClass.isAssignableFrom(untypedValue.getValue().getClass())) - { - T typedValue = typeClass.cast(untypedValue.getValue()); - - return typeClass.getConstructor(typeClass, primitiveValueType.getClass()).newInstance(typedValue, - primitiveValueType); - - } - else if (untypedValue != null) - { - throw new IllegalArgumentException("Cannot convert " - + untypedValue.getValue().getClass().getSimpleName() + " to " + typeClass.getSimpleName()); - } - throw new IllegalArgumentException("Cannot convert " + null + " to " + typeClass.getSimpleName()); - } - catch (NoSuchMethodException e) - { - throw new IllegalArgumentException("Cannot convert " + untypedValue.getValue().getClass().getSimpleName() - + " to " + typeClass.getSimpleName()); - } - catch (InvocationTargetException | IllegalAccessException | InstantiationException e) - { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValue.java b/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValue.java deleted file mode 100644 index 7614746e..00000000 --- a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValue.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.dsf.bpe.variables.codesystem.dsfpingstatus; - -import org.camunda.bpm.engine.variable.value.PrimitiveValue; - -import dev.dsf.bpe.CodeSystem; - -public interface CodeValue extends PrimitiveValue -{ -} diff --git a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueImpl.java b/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueImpl.java deleted file mode 100644 index ecf084cf..00000000 --- a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.dsf.bpe.variables.codesystem.dsfpingstatus; - -import java.io.Serial; - -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -import dev.dsf.bpe.CodeSystem; - -public class CodeValueImpl extends PrimitiveTypeValueImpl implements CodeValue -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final PrimitiveValueType DURATION_VALUE_TYPE = new CodeValueTypeImpl(); - - public CodeValueImpl(CodeSystem.DsfPingStatus.Code value) - { - super(value, DURATION_VALUE_TYPE); - } - - public CodeValueImpl(CodeSystem.DsfPingStatus.Code value, PrimitiveValueType type) - { - super(value, type); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueSerializer.java b/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueSerializer.java deleted file mode 100644 index 462f66f1..00000000 --- a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueSerializer.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.dsf.bpe.variables.codesystem.dsfpingstatus; - -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.variables.GenericPrimitiveTypeSerializer; - -public class CodeValueSerializer extends GenericPrimitiveTypeSerializer -{ - private static final PrimitiveValueType DURATION_VALUE_TYPE = new CodeValueTypeImpl(); - - public CodeValueSerializer() - { - super(DURATION_VALUE_TYPE, new ObjectMapper(), CodeValueImpl.class, CodeSystem.DsfPingStatus.Code.class); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueTypeImpl.java b/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueTypeImpl.java deleted file mode 100644 index 0e90f6a0..00000000 --- a/src/main/java/dev/dsf/bpe/variables/codesystem/dsfpingstatus/CodeValueTypeImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.dsf.bpe.variables.codesystem.dsfpingstatus; - -import java.io.Serial; -import java.util.Map; - -import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; - -import dev.dsf.bpe.CodeSystem; - -public class CodeValueTypeImpl extends PrimitiveValueTypeImpl -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final Class CODE_CLASS = CodeSystem.DsfPingStatus.Code.class; - - public CodeValueTypeImpl() - { - super(CODE_CLASS); - } - - @Override - public CodeValueImpl createValue(Object o, Map map) - { - if (o instanceof CodeSystem.DsfPingStatus.Code code) - { - return new CodeValueImpl(code); - } - else - { - throw new IllegalArgumentException("Cannot create value of type " + CODE_CLASS.getSimpleName() - + " from type " + o.getClass().getSimpleName()); - } - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/duration/DurationValue.java b/src/main/java/dev/dsf/bpe/variables/duration/DurationValue.java deleted file mode 100644 index 531ed68d..00000000 --- a/src/main/java/dev/dsf/bpe/variables/duration/DurationValue.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.dsf.bpe.variables.duration; - -import java.time.Duration; - -import org.camunda.bpm.engine.variable.value.PrimitiveValue; - -public interface DurationValue extends PrimitiveValue -{ -} diff --git a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueImpl.java b/src/main/java/dev/dsf/bpe/variables/duration/DurationValueImpl.java deleted file mode 100644 index 645a9862..00000000 --- a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.dsf.bpe.variables.duration; - -import java.io.Serial; -import java.time.Duration; - -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -public class DurationValueImpl extends PrimitiveTypeValueImpl implements DurationValue -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final PrimitiveValueType DURATION_VALUE_TYPE = new DurationValueTypeImpl(); - - public DurationValueImpl(Duration value) - { - super(value, DURATION_VALUE_TYPE); - } - - public DurationValueImpl(Duration value, PrimitiveValueType type) - { - super(value, type); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueSerializer.java b/src/main/java/dev/dsf/bpe/variables/duration/DurationValueSerializer.java deleted file mode 100644 index 5e50fb41..00000000 --- a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueSerializer.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.dsf.bpe.variables.duration; - -import java.time.Duration; - -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.dsf.bpe.variables.GenericPrimitiveTypeSerializer; - -public class DurationValueSerializer extends GenericPrimitiveTypeSerializer -{ - private static final PrimitiveValueType DURATION_VALUE_TYPE = new DurationValueTypeImpl(); - - public DurationValueSerializer(ObjectMapper objectMapperWithJavaTimeModule) - { - super(DURATION_VALUE_TYPE, objectMapperWithJavaTimeModule, DurationValueImpl.class, Duration.class); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueTypeImpl.java b/src/main/java/dev/dsf/bpe/variables/duration/DurationValueTypeImpl.java deleted file mode 100644 index 5a51e8e5..00000000 --- a/src/main/java/dev/dsf/bpe/variables/duration/DurationValueTypeImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.dsf.bpe.variables.duration; - -import java.io.Serial; -import java.time.Duration; -import java.util.Map; - -import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; - -public class DurationValueTypeImpl extends PrimitiveValueTypeImpl -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final Class DURATION_CLASS = Duration.class; - - public DurationValueTypeImpl() - { - super(DURATION_CLASS); - } - - @Override - public DurationValueImpl createValue(Object o, Map map) - { - if (o instanceof Duration duration) - { - return new DurationValueImpl(duration); - } - else - { - throw new IllegalArgumentException("Cannot create value of type " + DURATION_CLASS.getSimpleName() - + " from type " + o.getClass().getSimpleName()); - } - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValue.java b/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValue.java deleted file mode 100644 index ffe1451e..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValue.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.dsf.bpe.variables.process_error; - -import org.camunda.bpm.engine.variable.value.PrimitiveValue; - -import dev.dsf.bpe.ProcessError; - -public interface ProcessErrorValue extends PrimitiveValue -{ -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueImpl.java b/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueImpl.java deleted file mode 100644 index ad9827cd..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.dsf.bpe.variables.process_error; - -import java.io.Serial; - -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -import dev.dsf.bpe.ProcessError; - -public class ProcessErrorValueImpl extends PrimitiveTypeValueImpl implements ProcessErrorValue -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final ProcessErrorValueTypeImpl PROCESS_ERROR_VALUE_TYPE = new ProcessErrorValueTypeImpl(); - - public ProcessErrorValueImpl(ProcessError value) - { - super(value, PROCESS_ERROR_VALUE_TYPE); - } - - public ProcessErrorValueImpl(ProcessError value, PrimitiveValueType type) - { - super(value, type); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueSerializer.java b/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueSerializer.java deleted file mode 100644 index 079990ba..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueSerializer.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.dsf.bpe.variables.process_error; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.dsf.bpe.ProcessError; -import dev.dsf.bpe.variables.GenericPrimitiveTypeSerializer; - -public class ProcessErrorValueSerializer extends GenericPrimitiveTypeSerializer -{ - private static final ProcessErrorValueTypeImpl PROCESS_ERROR_VALUE_TYPE = new ProcessErrorValueTypeImpl(); - - public ProcessErrorValueSerializer() - { - super(PROCESS_ERROR_VALUE_TYPE, new ObjectMapper(), ProcessErrorValueImpl.class, ProcessError.class); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueTypeImpl.java b/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueTypeImpl.java deleted file mode 100644 index a18e795d..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_error/ProcessErrorValueTypeImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.dsf.bpe.variables.process_error; - -import java.io.Serial; -import java.util.Map; - -import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; -import org.camunda.bpm.engine.variable.value.TypedValue; - -import dev.dsf.bpe.ProcessError; - -public class ProcessErrorValueTypeImpl extends PrimitiveValueTypeImpl -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final Class PROCESS_ERROR_CLASS = ProcessError.class; - - public ProcessErrorValueTypeImpl() - { - super(PROCESS_ERROR_CLASS); - } - - @Override - public TypedValue createValue(Object value, Map valueInfo) - { - if (value instanceof ProcessError error) - { - return new ProcessErrorValueImpl(error); - } - else - { - throw new IllegalArgumentException("Cannot create value of type " + PROCESS_ERROR_CLASS.getSimpleName() - + " from type " + value.getClass().getSimpleName()); - } - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValue.java b/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValue.java deleted file mode 100644 index 75c99472..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValue.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.dsf.bpe.variables.process_errors; - -import org.camunda.bpm.engine.variable.value.PrimitiveValue; - -import dev.dsf.bpe.ProcessErrors; - -public interface ProcessErrorsValue extends PrimitiveValue -{ -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueImpl.java b/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueImpl.java deleted file mode 100644 index 8e79fc2b..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.dsf.bpe.variables.process_errors; - -import java.io.Serial; - -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; - -import dev.dsf.bpe.ProcessErrors; - -public class ProcessErrorsValueImpl extends PrimitiveTypeValueImpl implements ProcessErrorsValue -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final ProcessErrorsValueTypeImpl PROCESS_ERRORS_VALUE_TYPE = new ProcessErrorsValueTypeImpl(); - - public ProcessErrorsValueImpl(ProcessErrors value) - { - super(value, PROCESS_ERRORS_VALUE_TYPE); - } - - public ProcessErrorsValueImpl(ProcessErrors value, PrimitiveValueType type) - { - super(value, type); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueSerializer.java b/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueSerializer.java deleted file mode 100644 index 54dfb15b..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueSerializer.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.dsf.bpe.variables.process_errors; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import dev.dsf.bpe.ProcessErrors; -import dev.dsf.bpe.variables.GenericPrimitiveTypeSerializer; - -public class ProcessErrorsValueSerializer extends GenericPrimitiveTypeSerializer -{ - private static final ProcessErrorsValueTypeImpl TYPE = new ProcessErrorsValueTypeImpl(); - - public ProcessErrorsValueSerializer() - { - super(TYPE, new ObjectMapper(), ProcessErrorsValueImpl.class, ProcessErrors.class); - } -} diff --git a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueTypeImpl.java b/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueTypeImpl.java deleted file mode 100644 index c7fc5727..00000000 --- a/src/main/java/dev/dsf/bpe/variables/process_errors/ProcessErrorsValueTypeImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.dsf.bpe.variables.process_errors; - -import java.io.Serial; -import java.util.Map; - -import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; -import org.camunda.bpm.engine.variable.value.TypedValue; - -import dev.dsf.bpe.ProcessErrors; - -public class ProcessErrorsValueTypeImpl extends PrimitiveValueTypeImpl -{ - @Serial - private static final long serialVersionUID = 1L; - - private static final Class PROCESS_ERRORS_CLASS = ProcessErrors.class; - - public ProcessErrorsValueTypeImpl() - { - super(PROCESS_ERRORS_CLASS); - } - - @Override - public TypedValue createValue(Object value, Map valueInfo) - { - if (value instanceof ProcessErrors errors) - { - return new ProcessErrorsValueImpl(errors); - } - else - { - throw new IllegalArgumentException("Cannot create value of type " + PROCESS_ERRORS_CLASS.getSimpleName() - + " from type " + value.getClass().getSimpleName()); - } - } -} From 8e4c05b0a5635f172acce426648ed9cee393c53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:26:07 +0200 Subject: [PATCH 45/68] API v2 changes: - new base resource versions - resource version and release date are now taken from process plugin definition getters as they are read from plugin.properties by AbstractProcessPluginDefinition --- .../ActivityDefinitionProfileTest.java | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java index 23e82bb4..b61d0415 100644 --- a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java +++ b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java @@ -15,8 +15,8 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; import ca.uhn.fhir.validation.ValidationResult; import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.fhir.authorization.process.ProcessAuthorizationHelper; -import dev.dsf.fhir.authorization.process.ProcessAuthorizationHelperImpl; +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper; +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelperImpl; import dev.dsf.fhir.validation.ResourceValidator; import dev.dsf.fhir.validation.ResourceValidatorImpl; import dev.dsf.fhir.validation.ValidationSupportRule; @@ -24,30 +24,31 @@ public class ActivityDefinitionProfileTest { private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); + private static final PingProcessPluginDefinition def = new PingProcessPluginDefinition(); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule( - PingProcessPluginDefinition.VERSION, PingProcessPluginDefinition.RELEASE_DATE, - Arrays.asList("dsf-activity-definition-1.0.0.xml", "dsf-extension-process-authorization-1.0.0.xml", - "dsf-extension-process-authorization-organization-1.0.0.xml", - "dsf-extension-process-authorization-organization-practitioner-1.0.0.xml", - "dsf-extension-process-authorization-parent-organization-role-1.0.0.xml", - "dsf-extension-process-authorization-parent-organization-role-practitioner-1.0.0.xml", - "dsf-extension-process-authorization-practitioner-1.0.0.xml", - "dsf-coding-process-authorization-local-all-1.0.0.xml", - "dsf-coding-process-authorization-local-all-practitioner-1.0.0.xml", - "dsf-coding-process-authorization-local-organization-1.0.0.xml", - "dsf-coding-process-authorization-local-organization-practitioner-1.0.0.xml", - "dsf-coding-process-authorization-local-parent-organization-role-1.0.0.xml", - "dsf-coding-process-authorization-local-parent-organization-role-practitioner-1.0.0.xml", - "dsf-coding-process-authorization-remote-all-1.0.0.xml", - "dsf-coding-process-authorization-remote-parent-organization-role-1.0.0.xml", - "dsf-coding-process-authorization-remote-organization-1.0.0.xml"), - Arrays.asList("dsf-organization-role-1.0.0.xml", "dsf-practitioner-role-1.0.0.xml", - "dsf-process-authorization-1.0.0.xml", "dsf-read-access-tag-1.0.0.xml"), - Arrays.asList("dsf-organization-role-1.0.0.xml", "dsf-practitioner-role-1.0.0.xml", - "dsf-process-authorization-recipient-1.0.0.xml", "dsf-process-authorization-requester-1.0.0.xml", - "dsf-read-access-tag-1.0.0.xml")); + public static final ValidationSupportRule validationRule = new ValidationSupportRule(def.getVersion(), + def.getReleaseDate(), + Arrays.asList("dsf-activity-definition-2.0.0.xml", "dsf-extension-process-authorization-2.0.0.xml", + "dsf-extension-process-authorization-organization-2.0.0.xml", + "dsf-extension-process-authorization-organization-practitioner-2.0.0.xml", + "dsf-extension-process-authorization-parent-organization-role-2.0.0.xml", + "dsf-extension-process-authorization-parent-organization-role-practitioner-2.0.0.xml", + "dsf-extension-process-authorization-practitioner-2.0.0.xml", + "dsf-coding-process-authorization-local-all-2.0.0.xml", + "dsf-coding-process-authorization-local-all-practitioner-2.0.0.xml", + "dsf-coding-process-authorization-local-organization-2.0.0.xml", + "dsf-coding-process-authorization-local-organization-practitioner-2.0.0.xml", + "dsf-coding-process-authorization-local-parent-organization-role-2.0.0.xml", + "dsf-coding-process-authorization-local-parent-organization-role-practitioner-2.0.0.xml", + "dsf-coding-process-authorization-remote-all-2.0.0.xml", + "dsf-coding-process-authorization-remote-parent-organization-role-2.0.0.xml", + "dsf-coding-process-authorization-remote-organization-2.0.0.xml"), + Arrays.asList("dsf-organization-role-2.0.0.xml", "dsf-practitioner-role-2.0.0.xml", + "dsf-process-authorization-2.0.0.xml", "dsf-read-access-tag-2.0.0.xml"), + Arrays.asList("dsf-organization-role-2.0.0.xml", "dsf-practitioner-role-2.0.0.xml", + "dsf-process-authorization-recipient-2.0.0.xml", "dsf-process-authorization-requester-2.0.0.xml", + "dsf-read-access-tag-2.0.0.xml")); private final ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), validationRule.getValidationSupport()); From de08b788b58e4833ad7b04699385f2a1235f1a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:29:56 +0200 Subject: [PATCH 46/68] API v2 changes: - FhirWebserviceClientProvider and FhirWebserviceClient are replaced by DsfClientProvider + DsfClient for all requests to a DSF FHIR server --- src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java b/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java index e554e6c3..0506bdeb 100644 --- a/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java +++ b/src/main/java/dev/dsf/bpe/util/BinaryResourceDownloader.java @@ -63,8 +63,7 @@ public DownloadResult download(Variables variables, ProcessPluginApi api, Task t String webserviceUrl = downloadResourceReferenceIdType.getBaseUrl(); try { - InputStream binaryResourceInputStream = api.getDsfClientProvider() - .getByEndpointUrl(webserviceUrl) + InputStream binaryResourceInputStream = api.getDsfClientProvider().getByEndpointUrl(webserviceUrl) .readBinary(downloadResourceReferenceId, ConstantsPing.DOWNLOAD_RESOURCE_MIME_TYPE); try (binaryResourceInputStream) From 5a65a15fbc1e70ce62e010d210634fea2fd03e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:34:56 +0200 Subject: [PATCH 47/68] API v2 changes: - FhirWebserviceClientProvider and FhirWebserviceClient are replaced by DsfClientProvider + DsfClient for all requests to a DSF FHIR server - BpmnError replaced by ErrorBoundary event which also requires an error message to be set --- .../dsf/bpe/service/ping/CheckPingTaskStatus.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java index 88b854af..625d8c88 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java +++ b/src/main/java/dev/dsf/bpe/service/ping/CheckPingTaskStatus.java @@ -43,10 +43,10 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound { if (taskId != null) { - DsfClient dsfClient = api.getDsfClientProvider() - .getByEndpointUrl(target.getEndpointUrl()); + DsfClient dsfClient = api.getDsfClientProvider().getByEndpointUrl(target.getEndpointUrl()); - Task pingTask = dsfClient.withRetry(3, DelayStrategy.constant(Duration.ofSeconds(1))).read(Task.class, taskId); + Task pingTask = dsfClient.withRetry(3, DelayStrategy.constant(Duration.ofSeconds(1))).read(Task.class, + taskId); ProcessError error = switch (pingTask.getStatus()) { case COMPLETED -> new ProcessError(ConstantsPing.PROCESS_NAME_PING, @@ -120,10 +120,10 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va { logger.error("Unexpected error while checking status of ping task.", e); String correlationKey = variables.getTarget().getCorrelationKey(); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - variables, correlationKey); - return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + ErrorListUtils.add(new ProcessError(ConstantsPing.PROCESS_NAME_PING, + CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), variables, correlationKey); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, + ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); } }; } From ebdd6e126a02fda0b85c75ea147be43e553ed756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:39:27 +0200 Subject: [PATCH 48/68] API v2 changes: - FhirWebserviceClientProvider and FhirWebserviceClient are replaced by DsfClientProvider + DsfClient for all requests to a DSF FHIR server --- src/main/java/dev/dsf/bpe/service/Cleanup.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/Cleanup.java b/src/main/java/dev/dsf/bpe/service/Cleanup.java index 76b596de..70c93e8c 100644 --- a/src/main/java/dev/dsf/bpe/service/Cleanup.java +++ b/src/main/java/dev/dsf/bpe/service/Cleanup.java @@ -38,10 +38,8 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound { try { - api.getDsfClientProvider().getLocal().delete(Binary.class, - downloadResourceId); - api.getDsfClientProvider().getLocal().deletePermanently(Binary.class, - downloadResourceId); + api.getDsfClientProvider().getLocal().delete(Binary.class, downloadResourceId); + api.getDsfClientProvider().getLocal().deletePermanently(Binary.class, downloadResourceId); logger.debug("Deleted Binary resource with ID {}", downloadResourceId); } catch (ProcessingException e) From 8577d0ee885a130f8670f7ed20cc3e56fb896684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:55:11 +0200 Subject: [PATCH 49/68] API v2 changes: - Resource version is no longer a static constant in PingProcessPluginDefintion. Therefore, inject resource version from ProcessPluginDefinition instance at runtime - As a result, PingStatusGenerator now also gets the resource version injected into the constructor instead of reading it from a static variable and requires configuration in PingConfig along any other services depending on it --- src/main/java/dev/dsf/bpe/CodeSystem.java | 19 ++- src/main/java/dev/dsf/bpe/ProcessError.java | 14 +-- ...gProcessPluginDeploymentStateListener.java | 20 ++-- .../dsf/bpe/message/CleanupPongMessage.java | 14 ++- .../dev/dsf/bpe/message/SendPingMessage.java | 18 +-- .../dev/dsf/bpe/message/SendPongMessage.java | 27 +++-- .../dsf/bpe/service/ping/StoreResults.java | 16 ++- .../service/pong/LogAndSaveAndStoreError.java | 15 ++- .../bpe/service/pong/StoreDownloadSpeed.java | 6 +- .../dev/dsf/bpe/service/pong/StoreErrors.java | 11 +- .../bpe/service/pong/StoreUploadSpeed.java | 6 +- .../dev/dsf/bpe/spring/config/PingConfig.java | 34 ++++-- .../DownloadResourceReferenceGenerator.java | 6 +- .../DownloadResourceSizeGenerator.java | 6 +- .../generator/DownloadedBytesGenerator.java | 6 +- .../DownloadedDurationGenerator.java | 5 +- .../ErrorInputComponentGenerator.java | 11 +- .../output/generator/PingStatusGenerator.java | 109 +++++++++--------- .../dsf/bpe/util/PingStatusGeneratorTest.java | 8 +- 19 files changed, 194 insertions(+), 157 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/CodeSystem.java b/src/main/java/dev/dsf/bpe/CodeSystem.java index 12b891ae..01870f13 100644 --- a/src/main/java/dev/dsf/bpe/CodeSystem.java +++ b/src/main/java/dev/dsf/bpe/CodeSystem.java @@ -57,10 +57,9 @@ private DsfPing() { } - public static Coding fromCode(Code code) + public static Coding fromCode(Code code, String resourceVersion) { - return new Coding().setSystem(URL).setCode(code.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + return new Coding().setSystem(URL).setCode(code.getValue()).setVersion(resourceVersion); } public enum Code implements SingleStringValueEnum @@ -104,10 +103,9 @@ private DsfPingStatus() { } - public static Coding fromCode(Code code) + public static Coding fromCode(Code code, String resourceVersion) { - return new Coding().setSystem(URL).setCode(code.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + return new Coding().setSystem(URL).setCode(code.getValue()).setVersion(resourceVersion); } public enum Code implements SingleStringValueEnum @@ -146,10 +144,9 @@ private DsfPingUnits() { } - public static Coding fromCode(Code code) + public static Coding fromCode(Code code, String resourceVersion) { - return new Coding().setSystem(URL).setCode(code.toUcum()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + return new Coding().setSystem(URL).setCode(code.toUcum()).setVersion(resourceVersion); } public enum Code @@ -359,10 +356,10 @@ private DsfPingError() { } - public static Coding fromConcept(Concept concept) + public static Coding fromConcept(Concept concept, String resourceVersion) { return new Coding().setSystem(URL).setCode(concept.getCode()).setDisplay(concept.getDisplay()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setVersion(resourceVersion); } public enum Concept diff --git a/src/main/java/dev/dsf/bpe/ProcessError.java b/src/main/java/dev/dsf/bpe/ProcessError.java index 17a5a8c7..6cdd05c5 100644 --- a/src/main/java/dev/dsf/bpe/ProcessError.java +++ b/src/main/java/dev/dsf/bpe/ProcessError.java @@ -15,7 +15,7 @@ public record ProcessError(String process, CodeSystem.DsfPingError.Concept concept, String potentialFixUrl) implements Serializable { - public static Extension toExtension(ProcessError error) + public static Extension toExtension(ProcessError error, String resourceVersion) { Objects.requireNonNull(error); Objects.requireNonNull(error.concept()); @@ -25,7 +25,7 @@ public static Extension toExtension(ProcessError error) extension.setUrl(ConstantsPing.STRUCTURE_DEFINITION_URL_EXTENSION_ERROR); extension.addExtension().setUrl(ConstantsPing.EXTENSION_URL_ERROR) - .setValue(CodeSystem.DsfPingError.fromConcept(error.concept())); + .setValue(CodeSystem.DsfPingError.fromConcept(error.concept(), resourceVersion)); if (Objects.nonNull(error.potentialFixUrl)) { extension.addExtension().setUrl(ConstantsPing.EXTENSION_URL_POTENTIAL_FIX) @@ -50,19 +50,19 @@ public static ProcessError toError(Extension extension, String process) return new ProcessError(process, error, potentialFixUrl); } - public static List toTaskOutput(List errors) + public static List toTaskOutput(List errors, String resourceVersion) { if (errors == null || errors.isEmpty()) return List.of(); - return errors.stream().map(ProcessError::toTaskOutput).collect(Collectors.toList()); + return errors.stream().map(e -> toTaskOutput(e, resourceVersion)).collect(Collectors.toList()); } - public static Task.TaskOutputComponent toTaskOutput(ProcessError error) + public static Task.TaskOutputComponent toTaskOutput(ProcessError error, String resourceVersion) { Task.TaskOutputComponent param = new Task.TaskOutputComponent(); - param.getType().addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.ERROR)); - param.addExtension(ProcessError.toExtension(error)); + param.getType().addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.ERROR, resourceVersion)); + param.addExtension(ProcessError.toExtension(error, resourceVersion)); Extension dataAbsentReason = new Extension() .setUrl("http://hl7.org/fhir/StructureDefinition/data-absent-reason") .setValue(new CodeType("not-applicable")); diff --git a/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java b/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java index 12b1c91a..247959b1 100644 --- a/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java +++ b/src/main/java/dev/dsf/bpe/listener/PingPongProcessPluginDeploymentStateListener.java @@ -1,7 +1,5 @@ package dev.dsf.bpe.listener; -import static dev.dsf.bpe.PingProcessPluginDefinition.RESOURCE_VERSION; - import java.util.List; import java.util.Map; import java.util.Objects; @@ -26,14 +24,15 @@ import dev.dsf.bpe.v2.ProcessPluginDeploymentListener; import dev.dsf.bpe.v2.client.dsf.DsfClient; -public class PingPongProcessPluginDeploymentStateListener - implements ProcessPluginDeploymentListener, InitializingBean +public class PingPongProcessPluginDeploymentStateListener implements ProcessPluginDeploymentListener, InitializingBean { private final ProcessPluginApi api; + private final String resourceVersion; public PingPongProcessPluginDeploymentStateListener(ProcessPluginApi api) { this.api = api; + this.resourceVersion = api.getProcessPluginDefinition().getResourceVersion(); } @Override @@ -67,8 +66,8 @@ private void updateDraftTaskResources() { DsfClient client = api.getDsfClientProvider().getLocal(); - String pingProcessPrefix = "http://dsf.dev/bpe/Process/ping/" + RESOURCE_VERSION; - String pingAutostartProcessPrefix = "http://dsf.dev/bpe/Process/pingAutostart/" + RESOURCE_VERSION; + String pingProcessPrefix = "http://dsf.dev/bpe/Process/ping/" + resourceVersion; + String pingAutostartProcessPrefix = "http://dsf.dev/bpe/Process/pingAutostart/" + resourceVersion; List draftTaskResourceIdentifiers = List.of(pingProcessPrefix + "/task-start-ping", pingAutostartProcessPrefix + "/task-start-ping-autostart"); @@ -91,7 +90,7 @@ private void adaptDraftTask(Task task) Coding downloadResourceSizeBytesCoding = new Coding(); downloadResourceSizeBytesCoding.setSystem(dev.dsf.bpe.CodeSystem.DsfPing.URL) .setCode(dev.dsf.bpe.CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES.getValue()) - .setVersion(RESOURCE_VERSION); + .setVersion(resourceVersion); Optional optInput = api.getTaskHelper().getFirstInputParameter(task, downloadResourceSizeBytesCoding, DecimalType.class); @@ -106,7 +105,7 @@ private void adaptDraftTask(Task task) Coding pongTimeoutDurationCoding = new Coding(); pongTimeoutDurationCoding.setSystem(dev.dsf.bpe.CodeSystem.DsfPing.URL) .setCode(dev.dsf.bpe.CodeSystem.DsfPing.Code.PONG_TIMEOUT_DURATION_ISO_8601.getValue()) - .setVersion(RESOURCE_VERSION); + .setVersion(resourceVersion); optInput = api.getTaskHelper().getFirstInputParameter(task, pongTimeoutDurationCoding, StringType.class); if (optInput.isEmpty()) @@ -134,8 +133,7 @@ private void updateOlderResourcesIfCurrentIsNewestR private Bundle search(Class type, String url) { - return api.getDsfClientProvider().getLocal().search(type, - Map.of("url", List.of(url))); + return api.getDsfClientProvider().getLocal().search(type, Map.of("url", List.of(url))); } private Bundle searchTask(String identifier) @@ -170,7 +168,7 @@ else if (version1.major < version2.major) private boolean currentIsNewestResource(List resources) { - return !resources.isEmpty() && RESOURCE_VERSION.equals(resources.get(resources.size() - 1).getVersion()); + return !resources.isEmpty() && resourceVersion.equals(resources.get(resources.size() - 1).getVersion()); } private MinorMajorVersion getMajorMinorVersion(String version) diff --git a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java index 7cc1fef5..b750ad11 100644 --- a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java @@ -40,11 +40,13 @@ public List getAdditionalInputParameters(ProcessPluginA List additionalInputParameters = new ArrayList<>(); + String resourceVersion = api.getProcessPluginDefinition().getResourceVersion(); + if (downloadedBytes != null) - additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes)); + additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes, resourceVersion)); if (downloadedDuration != null) - additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration)); + additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration, resourceVersion)); return additionalInputParameters; } @@ -69,8 +71,9 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va SendTaskErrorConverter.ProcessErrorWithStatusCode errorAndStatus = SendTaskErrorConverter .convertLocal(e, false, ConstantsPing.PROCESS_NAME_PING); - variables.setJsonVariableLocal(ExecutionVariables.error.name(),errorAndStatus.error()); - variables.setStringLocal(ExecutionVariables.statusCode.name(), CodeSystem.DsfPing.Code.ERROR.getValue()); + variables.setJsonVariableLocal(ExecutionVariables.error.name(), errorAndStatus.error()); + variables.setStringLocal(ExecutionVariables.statusCode.name(), + CodeSystem.DsfPing.Code.ERROR.getValue()); logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), errorAndStatus.error().concept().getDisplay()); @@ -83,7 +86,8 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va @Override public TaskSender getTaskSender(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) { - return new DefaultTaskSender(api, variables, sendTaskValues, this.getBusinessKeyStrategy()) { + return new DefaultTaskSender(api, variables, sendTaskValues, this.getBusinessKeyStrategy()) + { @Override protected Target getTarget() { diff --git a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java index fe35e111..b9747c9e 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java @@ -42,16 +42,18 @@ public List getAdditionalInputParameters(ProcessPluginA List additionalInputParameters = new ArrayList<>(); + String resourceVersion = api.getProcessPluginDefinition().getResourceVersion(); + if (downloadResourceReference != null) - additionalInputParameters.add(DownloadResourceReferenceGenerator.create(downloadResourceReference)); + additionalInputParameters + .add(DownloadResourceReferenceGenerator.create(downloadResourceReference, resourceVersion)); - additionalInputParameters.add(DownloadResourceSizeGenerator.create(downloadResourceSizeBytes)); + additionalInputParameters.add(DownloadResourceSizeGenerator.create(downloadResourceSizeBytes, resourceVersion)); Task.ParameterComponent endpointIdentifierComponent = api.getTaskHelper().createInput( new Reference().setIdentifier(getLocalEndpointIdentifier(api)).setType(ResourceType.Endpoint.name()), - CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue(), api.getProcessPluginDefinition().getResourceVersion()); - endpointIdentifierComponent.getType().getCodingFirstRep() - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue(), resourceVersion); + endpointIdentifierComponent.getType().getCodingFirstRep().setVersion(resourceVersion); additionalInputParameters.add(endpointIdentifierComponent); @@ -61,7 +63,8 @@ public List getAdditionalInputParameters(ProcessPluginA @Override public TaskSender getTaskSender(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) { - return new DefaultTaskSender(api, variables, sendTaskValues, getBusinessKeyStrategy()) { + return new DefaultTaskSender(api, variables, sendTaskValues, getBusinessKeyStrategy()) + { @Override protected IdType doSend(Task task, String targetEndpointUrl) { @@ -96,8 +99,7 @@ public Exception handleException(ProcessPluginApi processPluginApi, Variables va .convertLocal(e, true, ConstantsPing.PROCESS_NAME_PING); variables.setJsonVariableLocal(ExecutionVariables.error.name(), errorAndStatus.error()); - variables.setJsonVariableLocal(ExecutionVariables.statusCode.name(), - errorAndStatus.statusCode()); + variables.setJsonVariableLocal(ExecutionVariables.statusCode.name(), errorAndStatus.statusCode()); logger.info("Request to {} resulted in error: {}", target.getEndpointUrl(), errorAndStatus.error().concept().getDisplay()); diff --git a/src/main/java/dev/dsf/bpe/message/SendPongMessage.java b/src/main/java/dev/dsf/bpe/message/SendPongMessage.java index 5b62925e..11ca21e9 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPongMessage.java @@ -30,6 +30,12 @@ public class SendPongMessage implements MessageSendTask { private static final Logger logger = LoggerFactory.getLogger(SendPongMessage.class); + private final PingStatusGenerator pingStatusGenerator; + + public SendPongMessage(PingStatusGenerator pingStatusGenerator) + { + this.pingStatusGenerator = pingStatusGenerator; + } @Override public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, @@ -37,31 +43,33 @@ public List getAdditionalInputParameters(ProcessPluginA { ProcessErrors errorListRemote = ErrorListUtils.getErrorListRemote(variables); long downloadResourceSizeBytes = variables.getLong(ExecutionVariables.downloadResourceSizeBytes.name()); + String resourceVersion = api.getProcessPluginDefinition().getResourceVersion(); if (downloadResourceSizeBytes >= 0) { Long downloadedBytes = variables.getLong(ExecutionVariables.downloadedBytes.name()); - Duration downloadedDuration = variables - .getVariable(ExecutionVariables.downloadedDuration.name()); + Duration downloadedDuration = variables.getVariable(ExecutionVariables.downloadedDuration.name()); String downloadResourceReference = variables.getString(ExecutionVariables.downloadResourceReference.name()); ArrayList additionalInputParameters = new ArrayList<>(); if (downloadedBytes != null) - additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes)); + additionalInputParameters.add(DownloadedBytesGenerator.create(downloadedBytes, resourceVersion)); if (downloadedDuration != null) - additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration)); + additionalInputParameters.add(DownloadedDurationGenerator.create(downloadedDuration, resourceVersion)); if (downloadResourceReference != null) - additionalInputParameters.add(DownloadResourceReferenceGenerator.create(downloadResourceReference)); + additionalInputParameters + .add(DownloadResourceReferenceGenerator.create(downloadResourceReference, resourceVersion)); - additionalInputParameters.addAll(ErrorInputComponentGenerator.create(errorListRemote.getEntries())); + additionalInputParameters + .addAll(ErrorInputComponentGenerator.create(errorListRemote.getEntries(), resourceVersion)); return additionalInputParameters; } else { - return ErrorInputComponentGenerator.create(errorListRemote.getEntries()); + return ErrorInputComponentGenerator.create(errorListRemote.getEntries(), resourceVersion); } } @@ -71,9 +79,8 @@ public void execute(ProcessPluginApi api, Variables variables, SendTaskValues se { Target target = variables.getTarget(); Task mainTask = variables.getStartTask(); - variables.setJsonVariable(ExecutionVariables.statusCode.name(), - CodeSystem.DsfPingStatus.Code.PONG_SENT); - PingStatusGenerator.updatePongStatusOutput(mainTask, target); + variables.setJsonVariable(ExecutionVariables.statusCode.name(), CodeSystem.DsfPingStatus.Code.PONG_SENT); + pingStatusGenerator.updatePongStatusOutput(mainTask, target); variables.updateTask(mainTask); MessageSendTask.super.execute(api, variables, sendTaskValues); } diff --git a/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java b/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java index f15fb0df..8e0056dd 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java +++ b/src/main/java/dev/dsf/bpe/service/ping/StoreResults.java @@ -33,12 +33,14 @@ public class StoreResults implements ServiceTask, InitializingBean private static final Logger logger = LoggerFactory.getLogger(StoreResults.class); private final AggregateErrorMailService errorMailService; private final CodeSystem.DsfPingUnits.Code networkSpeedUnit; + private final PingStatusGenerator pingStatusGenerator; - public StoreResults(AggregateErrorMailService errorMailService, - CodeSystem.DsfPingUnits.Code networkSpeedUnit) + public StoreResults(AggregateErrorMailService errorMailService, CodeSystem.DsfPingUnits.Code networkSpeedUnit, + PingStatusGenerator pingStatusGenerator) { this.networkSpeedUnit = networkSpeedUnit; this.errorMailService = errorMailService; + this.pingStatusGenerator = pingStatusGenerator; } @Override @@ -48,15 +50,17 @@ public void afterPropertiesSet() throws Exception } @Override - public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception + public void execute(ProcessPluginApi api, Variables variables) throws ErrorBoundaryEvent, Exception { logger.debug("Storing results for process started with Task {}", variables.getStartTask().getIdElement().getValue()); Task task = variables.getStartTask(); Targets targets = variables.getTargets(); Map> errorsPerTarget = new HashMap<>(); + String resourceVersion = api.getProcessPluginDefinition().getResourceVersion(); - ProcessError.toTaskOutput(ErrorListUtils.getErrorList(variables).getEntries()).forEach(task::addOutput); + ProcessError.toTaskOutput(ErrorListUtils.getErrorList(variables).getEntries(), resourceVersion) + .forEach(task::addOutput); targets.getEntries().stream().sorted(Comparator.comparing(Target::getEndpointIdentifierValue)).forEach(target -> { @@ -93,12 +97,12 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro .map(CodeSystem.DsfPingUnits.Code.SpeedAndUnit::unit).orElse(null); - PingStatusGenerator.createPingStatusOutput(target, statusCode, errors.getEntries(), downloadSpeed, + pingStatusGenerator.createPingStatusOutput(target, statusCode, errors.getEntries(), downloadSpeed, downloadSpeedUnit, uploadSpeed, uploadSpeedUnit).ifPresent(task::addOutput); } else // if slim-ping { - PingStatusGenerator.createPingStatusOutput(target, statusCode, errors.getEntries()) + pingStatusGenerator.createPingStatusOutput(target, statusCode, errors.getEntries()) .ifPresent(task::addOutput); } errorsPerTarget.put(target, errors.getEntries()); diff --git a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java index ae91d123..4d5ca858 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java +++ b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveAndStoreError.java @@ -17,6 +17,12 @@ public class LogAndSaveAndStoreError implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(LogAndSaveAndStoreError.class); + private final PingStatusGenerator pingStatusGenerator; + + public LogAndSaveAndStoreError(PingStatusGenerator pingStatusGenerator) + { + this.pingStatusGenerator = pingStatusGenerator; + } @Override public void execute(ProcessPluginApi processPluginApi, Variables variables) throws ErrorBoundaryEvent, Exception @@ -24,16 +30,13 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro Target target = variables.getTarget(); Task startTask = variables.getStartTask(); - ProcessError error = variables - .getVariable(ExecutionVariables.resourceDownloadError.name()); + ProcessError error = variables.getVariable(ExecutionVariables.resourceDownloadError.name()); ErrorListUtils.add(error, variables); - ProcessError errorRemote = variables - .getVariable(ExecutionVariables.resourceDownloadErrorRemote.name()); + ProcessError errorRemote = variables.getVariable(ExecutionVariables.resourceDownloadErrorRemote.name()); ErrorListUtils.addRemote(errorRemote, variables); - PingStatusGenerator.updatePongStatusOutput(startTask, - ErrorListUtils.getErrorList(variables).getEntries()); + pingStatusGenerator.updatePongStatusOutput(startTask, ErrorListUtils.getErrorList(variables).getEntries()); variables.updateTask(startTask); logger.info("Error while trying to download resource from {}: {}", target.getEndpointUrl(), diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java b/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java index a616a993..8cb5a3c4 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreDownloadSpeed.java @@ -19,11 +19,13 @@ public class StoreDownloadSpeed implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(StoreDownloadSpeed.class); + private final PingStatusGenerator pingStatusGenerator; private CodeSystem.DsfPingUnits.Code networkSpeedUnit; - public StoreDownloadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit) + public StoreDownloadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit, PingStatusGenerator pingStatusGenerator) { this.networkSpeedUnit = networkSpeedUnit; + this.pingStatusGenerator = pingStatusGenerator; } @Override @@ -51,7 +53,7 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro } } - PingStatusGenerator.updatePongStatusOutputDownloadSpeed(startTask, downloadSpeed, networkSpeedUnit); + pingStatusGenerator.updatePongStatusOutputDownloadSpeed(startTask, downloadSpeed, networkSpeedUnit); variables.updateTask(startTask); logger.debug("Stored download speed: " + downloadSpeed + " " + networkSpeedUnit); diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java b/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java index 52b55f67..de9b2027 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreErrors.java @@ -25,10 +25,12 @@ public class StoreErrors implements ServiceTask, InitializingBean private static final Logger logger = LoggerFactory.getLogger(StoreErrors.class); private final AggregateErrorMailService errorMailService; + private final PingStatusGenerator pingStatusGenerator; - public StoreErrors(AggregateErrorMailService errorMailService) + public StoreErrors(AggregateErrorMailService errorMailService, PingStatusGenerator pingStatusGenerator) { this.errorMailService = errorMailService; + this.pingStatusGenerator = pingStatusGenerator; } @Override @@ -44,11 +46,10 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro logger.debug("Storing errors..."); ProcessErrors errors = ErrorListUtils.getErrorList(variables); - PingStatusGenerator.updatePongStatusOutput(startTask, errors.getEntries()); + pingStatusGenerator.updatePongStatusOutput(startTask, errors.getEntries()); - CodeSystem.DsfPingStatus.Code status = variables - .getVariable(ExecutionVariables.statusCode.name()); - PingStatusGenerator.updatePongStatusOutput(startTask, status); + CodeSystem.DsfPingStatus.Code status = variables.getVariable(ExecutionVariables.statusCode.name()); + pingStatusGenerator.updatePongStatusOutput(startTask, status); variables.updateTask(startTask); diff --git a/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java b/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java index 5a471e2b..7494ecac 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java +++ b/src/main/java/dev/dsf/bpe/service/pong/StoreUploadSpeed.java @@ -21,11 +21,13 @@ public class StoreUploadSpeed implements ServiceTask { private static final Logger logger = LoggerFactory.getLogger(StoreUploadSpeed.class); + private final PingStatusGenerator pingStatusGenerator; private CodeSystem.DsfPingUnits.Code networkSpeedUnit; - public StoreUploadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit) + public StoreUploadSpeed(CodeSystem.DsfPingUnits.Code networkSpeedUnit, PingStatusGenerator pingStatusGenerator) { this.networkSpeedUnit = networkSpeedUnit; + this.pingStatusGenerator = pingStatusGenerator; } @Override @@ -58,7 +60,7 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound } } - PingStatusGenerator.updatePongStatusOutputUploadSpeed(startTask, uploadSpeed, networkSpeedUnit); + pingStatusGenerator.updatePongStatusOutputUploadSpeed(startTask, uploadSpeed, networkSpeedUnit); variables.updateTask(startTask); logger.debug("Stored upload speed: " + uploadSpeed + " " + networkSpeedUnit); diff --git a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java index 3ff22779..bfbd9680 100644 --- a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java +++ b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java @@ -44,6 +44,7 @@ import dev.dsf.bpe.service.pong.StoreDownloadSpeed; import dev.dsf.bpe.service.pong.StoreErrors; import dev.dsf.bpe.service.pong.StoreUploadSpeed; +import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; import dev.dsf.bpe.v2.ProcessPluginApi; import dev.dsf.bpe.v2.documentation.ProcessDocumentation; import dev.dsf.bpe.v2.spring.ActivityPrototypeBeanCreator; @@ -118,8 +119,8 @@ public static ActivityPrototypeBeanCreator activityPrototypeBeanCreator() { return new ActivityPrototypeBeanCreator(SetTargetAndConfigureTimer.class, SendStartPing.class, SetPongTimeoutDuration.class, SelectPingTargets.class, SendPingMessage.class, - SetCorrelationKeyListener.class, LogPing.class, SelectPongTarget.class, SendPongMessage.class, - CheckPingTaskStatus.class, CleanupPongMessage.class, DownloadResourceAndMeasureSpeed.class, + SetCorrelationKeyListener.class, LogPing.class, SelectPongTarget.class, CheckPingTaskStatus.class, + CleanupPongMessage.class, DownloadResourceAndMeasureSpeed.class, DownloadResourceAndMeasureSpeedInSubProcess.class, Cleanup.class, LogAndSaveAndStoreError.class, LogAndSaveError.class, EstimateCleanupTimerDuration.class, SavePong.class, SetEndpointIdentifier.class, LogAndSaveSendError.class, SaveTimeoutError.class, LogAndSaveUploadErrorPing.class, @@ -133,6 +134,19 @@ public PingPongProcessPluginDeploymentStateListener pingPongProcessPluginDeploym return new PingPongProcessPluginDeploymentStateListener(api); } + @Bean + public PingStatusGenerator pingStatusGenerator() + { + return new PingStatusGenerator(api.getProcessPluginDefinition().getResourceVersion()); + } + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public SendPongMessage sendPongMessage(PingStatusGenerator pingStatusGenerator) + { + return new SendPongMessage(pingStatusGenerator); + } + @Bean public AggregateErrorMailService aggregateErrorMailServicePing() { @@ -149,16 +163,16 @@ public AggregateErrorMailService aggregateErrorMailServicePong() @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public StoreResults savePingResults() + public StoreResults savePingResults(PingStatusGenerator pingStatusGenerator) { - return new StoreResults(aggregateErrorMailServicePing(), networkSpeedUnit); + return new StoreResults(aggregateErrorMailServicePing(), networkSpeedUnit, pingStatusGenerator); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public StoreUploadSpeed storeDownloadSpeeds() + public StoreUploadSpeed storeUploadSpeed(PingStatusGenerator pingStatusGenerator) { - return new StoreUploadSpeed(networkSpeedUnit); + return new StoreUploadSpeed(networkSpeedUnit, pingStatusGenerator); } @@ -171,9 +185,9 @@ public SetDownloadResourceSize setDownloadResourceSize() @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public StoreDownloadSpeed storeDownloadSpeed() + public StoreDownloadSpeed storeDownloadSpeed(PingStatusGenerator pingStatusGenerator) { - return new StoreDownloadSpeed(networkSpeedUnit); + return new StoreDownloadSpeed(networkSpeedUnit, pingStatusGenerator); } @Bean @@ -185,9 +199,9 @@ public GenerateAndStoreResource generateAndStoreResource() @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public StoreErrors storeErrors() + public StoreErrors storeErrors(PingStatusGenerator pingStatusGenerator) { - return new StoreErrors(aggregateErrorMailServicePong()); + return new StoreErrors(aggregateErrorMailServicePong(), pingStatusGenerator); } private void fixMaxResourceSizes() diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceReferenceGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceReferenceGenerator.java index a8e2a09f..ee2ab3a1 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceReferenceGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceReferenceGenerator.java @@ -11,13 +11,13 @@ private DownloadResourceReferenceGenerator() { } - public static Task.ParameterComponent create(String uri) + public static Task.ParameterComponent create(String uri, String resourceVersion) { Reference reference = new Reference(uri); reference.setType("Binary"); Task.ParameterComponent param = new Task.ParameterComponent(); - param.setValue(reference).getType() - .addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_REFERENCE)); + param.setValue(reference).getType().addCoding( + CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_REFERENCE, resourceVersion)); return param; } } diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceSizeGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceSizeGenerator.java index 53429582..1825d346 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceSizeGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadResourceSizeGenerator.java @@ -11,11 +11,11 @@ private DownloadResourceSizeGenerator() { } - public static Task.ParameterComponent create(long sizeBytes) + public static Task.ParameterComponent create(long sizeBytes, String resourceVersion) { Task.ParameterComponent param = new Task.ParameterComponent(); - param.setValue(new DecimalType(sizeBytes)).getType() - .addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES)); + param.setValue(new DecimalType(sizeBytes)).getType().addCoding( + CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES, resourceVersion)); return param; } } diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java index e8f22422..e4cce434 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java @@ -5,6 +5,7 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.PingProcessPluginDefinition; +import dev.dsf.bpe.v2.ProcessPluginApi; public final class DownloadedBytesGenerator { @@ -12,12 +13,11 @@ private DownloadedBytesGenerator() { } - public static Task.ParameterComponent create(long bytes) + public static Task.ParameterComponent create(long bytes, String resourceVersion) { Task.ParameterComponent param = new Task.ParameterComponent(); param.setValue(new DecimalType(bytes)).getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.DOWNLOADED_BYTES.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.DOWNLOADED_BYTES.getValue()).setVersion(resourceVersion); return param; } } diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java index b24288f5..5f50b9cc 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java @@ -16,13 +16,12 @@ private DownloadedDurationGenerator() { } - public static Task.ParameterComponent create(Duration duration) + public static Task.ParameterComponent create(Duration duration, String resourceVersion) { Task.ParameterComponent param = new Task.ParameterComponent(); param.setValue(new org.hl7.fhir.r4.model.Duration().setValue(duration.toMillis()).setSystem(CODESYSTEM_UCUM) .setCode(CODESYSTEM_UCUM_CODE_MILLISECONDS)).getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.DOWNLOADED_DURATION_MILLIS.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.DOWNLOADED_DURATION_MILLIS.getValue()).setVersion(resourceVersion); return param; } } diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/ErrorInputComponentGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/ErrorInputComponentGenerator.java index eb821935..8954f517 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/ErrorInputComponentGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/ErrorInputComponentGenerator.java @@ -17,19 +17,20 @@ private ErrorInputComponentGenerator() { } - public static List create(List errors) + public static List create(List errors, String resourceVersion) { if (errors == null || errors.isEmpty()) return List.of(); - return errors.stream().map(ErrorInputComponentGenerator::create).collect(Collectors.toList()); + return errors.stream().map(e -> ErrorInputComponentGenerator.create(e, resourceVersion)) + .collect(Collectors.toList()); } - public static Task.ParameterComponent create(ProcessError error) + public static Task.ParameterComponent create(ProcessError error, String resourceVersion) { Task.ParameterComponent param = new Task.ParameterComponent(); - param.getType().addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.ERROR)); - param.addExtension(ProcessError.toExtension(error)); + param.getType().addCoding(CodeSystem.DsfPing.fromCode(CodeSystem.DsfPing.Code.ERROR, resourceVersion)); + param.addExtension(ProcessError.toExtension(error, resourceVersion)); Extension dataAbsentReason = new Extension() .setUrl("http://hl7.org/fhir/StructureDefinition/data-absent-reason") .setValue(new CodeType("not-applicable")); diff --git a/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java b/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java index 4b0f89d8..3a42a045 100644 --- a/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/output/generator/PingStatusGenerator.java @@ -17,7 +17,6 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; -import dev.dsf.bpe.PingProcessPluginDefinition; import dev.dsf.bpe.ProcessError; import dev.dsf.bpe.v2.constants.NamingSystems.EndpointIdentifier; import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; @@ -25,13 +24,15 @@ public final class PingStatusGenerator { - private static final String CODESYSTEM_UCUM = "http://unitsofmeasure.org"; + private final String CODESYSTEM_UCUM = "http://unitsofmeasure.org"; + private final String resourceVersion; - private PingStatusGenerator() + public PingStatusGenerator(String resourceVersion) { + this.resourceVersion = resourceVersion; } - public static Task updatePongStatusOutput(Task task, List errors) + public Task updatePongStatusOutput(Task task, List errors) { List pongStatusOutputs = getOutputsByExtensionUrlAndCodes(task, CodeSystem.DsfPing.Code.PONG_STATUS.getValue()); @@ -54,7 +55,7 @@ public static Task updatePongStatusOutput(Task task, List errors) return task; } - public static TaskOutputComponent updateStatusOutput(TaskOutputComponent output, List errors) + public TaskOutputComponent updateStatusOutput(TaskOutputComponent output, List errors) { if (output != null) { @@ -74,7 +75,7 @@ public static TaskOutputComponent updateStatusOutput(TaskOutputComponent output, return output; } - public static Task updatePongStatusOutput(Task task, CodeSystem.DsfPingStatus.Code statusCode) + public Task updatePongStatusOutput(Task task, CodeSystem.DsfPingStatus.Code statusCode) { List pongStatusOutputs = getOutputsByExtensionUrlAndCodes(task, CodeSystem.DsfPing.Code.PONG_STATUS.getValue()); @@ -97,7 +98,7 @@ public static Task updatePongStatusOutput(Task task, CodeSystem.DsfPingStatus.Co return task; } - private static TaskOutputComponent updatePongStatusOutput(TaskOutputComponent outputComponent, + private TaskOutputComponent updatePongStatusOutput(TaskOutputComponent outputComponent, CodeSystem.DsfPingStatus.Code statusCode) { if (hasStatusCodeSet(outputComponent)) @@ -112,7 +113,7 @@ private static TaskOutputComponent updatePongStatusOutput(TaskOutputComponent ou return outputComponent; } - public static Task updatePongStatusOutput(Task task, Target target) + public Task updatePongStatusOutput(Task task, Target target) { List outputs = getOutputsByExtensionUrlAndCodes(task, CodeSystem.DsfPing.Code.PONG_STATUS.getValue()); @@ -135,7 +136,7 @@ public static Task updatePongStatusOutput(Task task, Target target) return task; } - private static TaskOutputComponent updateStatusOutput(TaskOutputComponent outputComponent, Target target) + private TaskOutputComponent updateStatusOutput(TaskOutputComponent outputComponent, Target target) { if (hasTargetSet(outputComponent)) { @@ -148,7 +149,7 @@ private static TaskOutputComponent updateStatusOutput(TaskOutputComponent output return outputComponent; } - public static Task updatePongStatusOutputDownloadSpeed(Task task, BigDecimal downloadSpeed, + public Task updatePongStatusOutputDownloadSpeed(Task task, BigDecimal downloadSpeed, CodeSystem.DsfPingUnits.Code networkSpeedUnit) { List outputs = getOutputsByExtensionUrlAndCodes(task, @@ -172,7 +173,7 @@ public static Task updatePongStatusOutputDownloadSpeed(Task task, BigDecimal dow return task; } - private static TaskOutputComponent updateStatusOutputDownloadSpeed(TaskOutputComponent outputComponent, + private TaskOutputComponent updateStatusOutputDownloadSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, CodeSystem.DsfPingUnits.Code networkSpeedUnit) { if (hasDownloadSpeedSet(outputComponent)) @@ -190,7 +191,7 @@ private static TaskOutputComponent updateStatusOutputDownloadSpeed(TaskOutputCom return outputComponent; } - public static Task updatePongStatusOutputUploadSpeed(Task task, BigDecimal uploadSpeed, + public Task updatePongStatusOutputUploadSpeed(Task task, BigDecimal uploadSpeed, CodeSystem.DsfPingUnits.Code networkSpeedUnit) { List outputs = getOutputsByExtensionUrlAndCodes(task, @@ -214,7 +215,7 @@ public static Task updatePongStatusOutputUploadSpeed(Task task, BigDecimal uploa return task; } - private static TaskOutputComponent updateStatusOutputUploadSpeed(TaskOutputComponent outputComponent, + private TaskOutputComponent updateStatusOutputUploadSpeed(TaskOutputComponent outputComponent, BigDecimal uploadSpeed, CodeSystem.DsfPingUnits.Code networkSpeedUnit) { if (hasDownloadSpeedSet(outputComponent)) @@ -231,7 +232,7 @@ private static TaskOutputComponent updateStatusOutputUploadSpeed(TaskOutputCompo return outputComponent; } - private static boolean hasTargetSet(TaskOutputComponent outputComponent) + private boolean hasTargetSet(TaskOutputComponent outputComponent) { List correlationKeyExtensions = outputComponent .getExtensionsByUrl(ConstantsPing.EXTENSION_URL_CORRELATION_KEY); @@ -243,7 +244,7 @@ private static boolean hasTargetSet(TaskOutputComponent outputComponent) || !endpointIdentifierExtensions.isEmpty(); } - private static boolean hasStatusCodeSet(TaskOutputComponent outputComponent) + private boolean hasStatusCodeSet(TaskOutputComponent outputComponent) { Type valueType = outputComponent.getValue(); List outputTypeCodings = outputComponent.getType().getCoding(); @@ -252,7 +253,7 @@ private static boolean hasStatusCodeSet(TaskOutputComponent outputComponent) || outputTypeCodings.stream().anyMatch(coding -> CodeSystem.DsfPing.URL.equals(coding.getSystem())); } - private static boolean hasDownloadSpeedSet(TaskOutputComponent outputComponent) + private boolean hasDownloadSpeedSet(TaskOutputComponent outputComponent) { Extension extension = getOrCreatePingStatusExtension(outputComponent); Extension downloadSpeedExtension = extension.getExtensionByUrl(ConstantsPing.EXTENSION_URL_DOWNLOAD_SPEED); @@ -260,16 +261,16 @@ private static boolean hasDownloadSpeedSet(TaskOutputComponent outputComponent) return downloadSpeedExtension != null; } - public static Optional createPingStatusOutput(Target target, - CodeSystem.DsfPingStatus.Code statusCode, List errors) + public Optional createPingStatusOutput(Target target, CodeSystem.DsfPingStatus.Code statusCode, + List errors) { return createStatusOutput(target, CodeSystem.DsfPing.Code.PING_STATUS, statusCode, errors, null, null, null, null, null, null, null, null); } - public static Optional createPingStatusOutput(Target target, - CodeSystem.DsfPingStatus.Code statusCode, List errors, BigDecimal downloadSpeed, - CodeSystem.DsfPingUnits.Code downloadUnit, BigDecimal uploadSpeed, CodeSystem.DsfPingUnits.Code uploadUnit) + public Optional createPingStatusOutput(Target target, CodeSystem.DsfPingStatus.Code statusCode, + List errors, BigDecimal downloadSpeed, CodeSystem.DsfPingUnits.Code downloadUnit, + BigDecimal uploadSpeed, CodeSystem.DsfPingUnits.Code uploadUnit) { return createStatusOutput(target, CodeSystem.DsfPing.Code.PING_STATUS, statusCode, errors, downloadSpeed, @@ -279,18 +280,17 @@ public static Optional createPingStatusOutput(Target target uploadUnit != null ? uploadUnit.toUcum() : null); } - public static Optional createPongStatusOutput(Target target, - CodeSystem.DsfPingStatus.Code statusCode, List errors) + public Optional createPongStatusOutput(Target target, CodeSystem.DsfPingStatus.Code statusCode, + List errors) { return createStatusOutput(target, CodeSystem.DsfPing.Code.PONG_STATUS, statusCode, errors, null, null, null, null, null, null, null, null); } - private static Optional createStatusOutput(Target target, - CodeSystem.DsfPing.Code outputParameter, CodeSystem.DsfPingStatus.Code statusCode, - List errors, BigDecimal downloadSpeed, String downloadUnit, String downloadUnitSystem, - String downloadUnitCode, BigDecimal uploadSpeed, String uploadUnit, String uploadUnitSystem, - String uploadUnitCode) + private Optional createStatusOutput(Target target, CodeSystem.DsfPing.Code outputParameter, + CodeSystem.DsfPingStatus.Code statusCode, List errors, BigDecimal downloadSpeed, + String downloadUnit, String downloadUnitSystem, String downloadUnitCode, BigDecimal uploadSpeed, + String uploadUnit, String uploadUnitSystem, String uploadUnitCode) { if (statusCode == null) return Optional.empty(); @@ -305,31 +305,30 @@ private static Optional createStatusOutput(Target target, return Optional.of(output); } - private static TaskOutputComponent addStatus(TaskOutputComponent outputComponent, - CodeSystem.DsfPing.Code outputParameter, CodeSystem.DsfPingStatus.Code statusCode) + private TaskOutputComponent addStatus(TaskOutputComponent outputComponent, CodeSystem.DsfPing.Code outputParameter, + CodeSystem.DsfPingStatus.Code statusCode) { if (outputParameter != null && statusCode != null) { - outputComponent.setValue(CodeSystem.DsfPingStatus.fromCode(statusCode)); - outputComponent.getType().addCoding(CodeSystem.DsfPing.fromCode(outputParameter)); + outputComponent.setValue(CodeSystem.DsfPingStatus.fromCode(statusCode, resourceVersion)); + outputComponent.getType().addCoding(CodeSystem.DsfPing.fromCode(outputParameter, resourceVersion)); sortStatusOutputExtensions(outputComponent); } return outputComponent; } - private static TaskOutputComponent updateStatus(TaskOutputComponent outputComponent, String outputParameter, + private TaskOutputComponent updateStatus(TaskOutputComponent outputComponent, String outputParameter, CodeSystem.DsfPingStatus.Code statusCode) { Type valueType = outputComponent.getValue(); if (valueType instanceof Coding coding) { - coding.setSystem(CodeSystem.DsfPingStatus.URL).setCode(statusCode.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + coding.setSystem(CodeSystem.DsfPingStatus.URL).setCode(statusCode.getValue()).setVersion(resourceVersion); } else { - outputComponent.setValue(CodeSystem.DsfPingStatus.fromCode(statusCode)); + outputComponent.setValue(CodeSystem.DsfPingStatus.fromCode(statusCode, resourceVersion)); } List outputTypeCodings = outputComponent.getType().getCoding(); @@ -355,7 +354,7 @@ private static TaskOutputComponent updateStatus(TaskOutputComponent outputCompon return outputComponent; } - private static TaskOutputComponent addTarget(TaskOutputComponent outputComponent, Target target) + private TaskOutputComponent addTarget(TaskOutputComponent outputComponent, Target target) { if (target != null) { @@ -373,7 +372,7 @@ private static TaskOutputComponent addTarget(TaskOutputComponent outputComponent return outputComponent; } - private static TaskOutputComponent updateTarget(TaskOutputComponent outputComponent, Target target) + private TaskOutputComponent updateTarget(TaskOutputComponent outputComponent, Target target) { Extension extension = getOrCreatePingStatusExtension(outputComponent); @@ -415,7 +414,7 @@ private static TaskOutputComponent updateTarget(TaskOutputComponent outputCompon return outputComponent; } - private static TaskOutputComponent addErrors(TaskOutputComponent outputComponent, List errors) + private TaskOutputComponent addErrors(TaskOutputComponent outputComponent, List errors) { if (errors != null && !errors.isEmpty()) { @@ -423,21 +422,21 @@ private static TaskOutputComponent addErrors(TaskOutputComponent outputComponent Extension errorsExtension = getOrCreateErrorsExtension(extension); for (ProcessError error : errors) { - errorsExtension.addExtension(ProcessError.toExtension(error)); + errorsExtension.addExtension(ProcessError.toExtension(error, resourceVersion)); } } sortStatusOutputExtensions(outputComponent); return outputComponent; } - private static TaskOutputComponent updateErrors(TaskOutputComponent outputComponent, List errors) + private TaskOutputComponent updateErrors(TaskOutputComponent outputComponent, List errors) { Extension extension = getOrCreatePingStatusExtension(outputComponent); Extension errorsExtension = getOrCreateErrorsExtension(extension); if (errors != null) { - List newErrorExtensions = errors.stream().map(ProcessError::toExtension) + List newErrorExtensions = errors.stream().map(e -> ProcessError.toExtension(e, resourceVersion)) .collect(Collectors.toCollection(ArrayList::new)); errorsExtension.setExtension(newErrorExtensions); } @@ -446,7 +445,7 @@ private static TaskOutputComponent updateErrors(TaskOutputComponent outputCompon return outputComponent; } - private static TaskOutputComponent addNetworkSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, + private TaskOutputComponent addNetworkSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, String downloadUnit, String downloadUnitSystem, String downloadUnitCode, BigDecimal uploadSpeed, String uploadUnit, String uploadUnitSystem, String uploadUnitCode) { @@ -456,7 +455,7 @@ private static TaskOutputComponent addNetworkSpeed(TaskOutputComponent outputCom return outputComponent; } - private static TaskOutputComponent addDownloadSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, + private TaskOutputComponent addDownloadSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, String unit, String unitSystem, String unitCode) { if (downloadSpeed != null && unit != null && unitSystem != null && unitCode != null) @@ -476,8 +475,8 @@ private static TaskOutputComponent addDownloadSpeed(TaskOutputComponent outputCo return outputComponent; } - private static TaskOutputComponent updateDownloadSpeed(TaskOutputComponent outputComponent, - BigDecimal downloadSpeed, String unit, String unitSystem, String unitCode) + private TaskOutputComponent updateDownloadSpeed(TaskOutputComponent outputComponent, BigDecimal downloadSpeed, + String unit, String unitSystem, String unitCode) { if (downloadSpeed != null && unit != null && unitSystem != null && unitCode != null) { @@ -508,8 +507,8 @@ private static TaskOutputComponent updateDownloadSpeed(TaskOutputComponent outpu return outputComponent; } - private static TaskOutputComponent addUploadSpeed(TaskOutputComponent outputComponent, BigDecimal uploadSpeed, - String unit, String unitSystem, String unitCode) + private TaskOutputComponent addUploadSpeed(TaskOutputComponent outputComponent, BigDecimal uploadSpeed, String unit, + String unitSystem, String unitCode) { if (uploadSpeed != null && unit != null && unitSystem != null && unitCode != null) { @@ -527,7 +526,7 @@ private static TaskOutputComponent addUploadSpeed(TaskOutputComponent outputComp return outputComponent; } - private static TaskOutputComponent updateUploadSpeed(TaskOutputComponent outputComponent, BigDecimal uploadSpeed, + private TaskOutputComponent updateUploadSpeed(TaskOutputComponent outputComponent, BigDecimal uploadSpeed, String unit, String unitSystem, String unitCode) { if (uploadSpeed != null && unit != null && unitSystem != null && unitCode != null) @@ -561,7 +560,7 @@ private static TaskOutputComponent updateUploadSpeed(TaskOutputComponent outputC return outputComponent; } - private static Extension getOrCreatePingStatusExtension(TaskOutputComponent outputComponent) + private Extension getOrCreatePingStatusExtension(TaskOutputComponent outputComponent) { Optional optionalExtension = getPingStatusExtension(outputComponent); if (optionalExtension.isPresent()) @@ -576,7 +575,7 @@ private static Extension getOrCreatePingStatusExtension(TaskOutputComponent outp } } - private static Optional getPingStatusExtension(TaskOutputComponent outputComponent) + private Optional getPingStatusExtension(TaskOutputComponent outputComponent) { List pingStatusExtensions = outputComponent.getExtension().stream().filter( extension -> ConstantsPing.STRUCTURE_DEFINITION_URL_EXTENSION_PING_STATUS.equals(extension.getUrl())) @@ -599,7 +598,7 @@ private static Optional getPingStatusExtension(TaskOutputComponent ou } } - private static Extension getOrCreateErrorsExtension(Extension extension) + private Extension getOrCreateErrorsExtension(Extension extension) { Optional optionalExtension = getErrorsExtension(extension); if (optionalExtension.isPresent()) @@ -614,7 +613,7 @@ private static Extension getOrCreateErrorsExtension(Extension extension) } } - private static Optional getErrorsExtension(Extension extension) + private Optional getErrorsExtension(Extension extension) { List errorsExtensions = extension.getExtension().stream() .filter(ex -> ConstantsPing.EXTENSION_URL_ERRORS.equals(ex.getUrl())).toList(); @@ -635,7 +634,7 @@ private static Optional getErrorsExtension(Extension extension) } } - private static List getOutputsByExtensionUrlAndCodes(Task task, String... codes) + private List getOutputsByExtensionUrlAndCodes(Task task, String... codes) { return task.getOutput().stream() .filter(outputComponent -> outputComponent.getType().getCoding().stream() @@ -647,7 +646,7 @@ private static List getOutputsByExtensionUrlAndCodes(T .collect(Collectors.toCollection(ArrayList::new)); } - private static void sortStatusOutputExtensions(TaskOutputComponent outputComponent) + private void sortStatusOutputExtensions(TaskOutputComponent outputComponent) { Optional optPingStatusExtension = getPingStatusExtension(outputComponent); if (optPingStatusExtension.isPresent()) diff --git a/src/test/java/dev/dsf/bpe/util/PingStatusGeneratorTest.java b/src/test/java/dev/dsf/bpe/util/PingStatusGeneratorTest.java index 04d32224..879f9f3b 100644 --- a/src/test/java/dev/dsf/bpe/util/PingStatusGeneratorTest.java +++ b/src/test/java/dev/dsf/bpe/util/PingStatusGeneratorTest.java @@ -13,12 +13,16 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; +import dev.dsf.bpe.PingProcessPluginDefinition; import dev.dsf.bpe.ProcessError; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; import dev.dsf.fhir.profiles.TaskProfileTest; public class PingStatusGeneratorTest { + private static final PingProcessPluginDefinition def = new PingProcessPluginDefinition(); + private static final PingStatusGenerator pingStatusGenerator = new PingStatusGenerator(def.getResourceVersion()); + @Test public void updatingPongErrorsResultsInOneErrorsExtensionTest() { @@ -28,11 +32,11 @@ public void updatingPongErrorsResultsInOneErrorsExtensionTest() Task pongTask = TaskProfileTest.createValidTaskStartPingProcess(); - PingStatusGenerator.updatePongStatusOutput(pongTask, errors); + pingStatusGenerator.updatePongStatusOutput(pongTask, errors); errors.add(new ProcessError(process, CodeSystem.DsfPingError.Concept.LOCAL_BINARY_POST_HTTP_UNEXPECTED, null)); - PingStatusGenerator.updatePongStatusOutput(pongTask, errors); + pingStatusGenerator.updatePongStatusOutput(pongTask, errors); List errorsExtensions = pongTask.getOutput().stream().map(Element::getExtension) .map(extensions -> extensions.stream() From 20658ecded60821a2d6302a5f718a2909e37ccf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:55:49 +0200 Subject: [PATCH 50/68] API v2 changes: - new base resource versions - resource version and release date are now taken from process plugin definition getters as they are read from plugin.properties by AbstractProcessPluginDefinition --- .../dsf/fhir/profiles/TaskProfileTest.java | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/test/java/dev/dsf/fhir/profiles/TaskProfileTest.java b/src/test/java/dev/dsf/fhir/profiles/TaskProfileTest.java index 5266ff79..1bfea638 100644 --- a/src/test/java/dev/dsf/fhir/profiles/TaskProfileTest.java +++ b/src/test/java/dev/dsf/fhir/profiles/TaskProfileTest.java @@ -44,10 +44,10 @@ import dev.dsf.bpe.util.task.input.generator.DownloadedDurationGenerator; import dev.dsf.bpe.util.task.input.generator.ErrorInputComponentGenerator; import dev.dsf.bpe.util.task.output.generator.PingStatusGenerator; -import dev.dsf.bpe.v1.constants.CodeSystems.BpmnMessage; -import dev.dsf.bpe.v1.constants.NamingSystems.EndpointIdentifier; -import dev.dsf.bpe.v1.constants.NamingSystems.OrganizationIdentifier; -import dev.dsf.bpe.v1.variables.Target; +import dev.dsf.bpe.v2.constants.CodeSystems.BpmnMessage; +import dev.dsf.bpe.v2.constants.NamingSystems.EndpointIdentifier; +import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; +import dev.dsf.bpe.v2.variables.Target; import dev.dsf.fhir.validation.ResourceValidator; import dev.dsf.fhir.validation.ResourceValidatorImpl; import dev.dsf.fhir.validation.ValidationSupportRule; @@ -57,17 +57,18 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); private static final PingProcessPluginDefinition def = new PingProcessPluginDefinition(); + private static final PingStatusGenerator pingStatusGenerator = new PingStatusGenerator(def.getResourceVersion()); @ClassRule public static final ValidationSupportRule validationRule = new ValidationSupportRule(def.getResourceVersion(), def.getResourceReleaseDate(), - Arrays.asList("dsf-task-base-1.0.0.xml", "dsf-extension-error.xml", "dsf-extension-ping-status.xml", + Arrays.asList("dsf-task-2.0.0.xml", "dsf-extension-error.xml", "dsf-extension-ping-status.xml", "dsf-task-ping.xml", "dsf-task-pong.xml", "dsf-task-start-ping.xml", "dsf-task-start-ping-autostart.xml", "dsf-task-stop-ping-autostart.xml", "dsf-task-cleanup-pong.xml"), - Arrays.asList("dsf-read-access-tag-1.0.0.xml", "dsf-bpmn-message-1.0.0.xml", "dsf-ping-1_0.xml", + Arrays.asList("dsf-read-access-tag-2.0.0.xml", "dsf-bpmn-message-2.0.0.xml", "dsf-ping-1_0.xml", "dsf-ping.xml", "dsf-ping-status-1_0.xml", "dsf-ping-status.xml"), - Arrays.asList("dsf-read-access-tag-1.0.0.xml", "dsf-bpmn-message-1.0.0.xml", "dsf-ping-1_0.xml", + Arrays.asList("dsf-read-access-tag-2.0.0.xml", "dsf-bpmn-message-2.0.0.xml", "dsf-ping-1_0.xml", "dsf-ping.xml", "dsf-ping-status-1_0.xml", "dsf-ping-status.xml", "dsf-pong-status-1_0.xml", "dsf-pong-status.xml", "dsf-network-speed-units.xml")); @@ -94,8 +95,7 @@ public void testTaskStartAutostartProcessProfileValidWithTargetEndpoints() .setValue(new StringType( "Endpoint?identifier=http://dsf.dev/sid/endpoint-identifier|endpoint.target.org")) .getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()).setVersion(def.getResourceVersion()); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -109,8 +109,7 @@ public void testTaskStartAutostartProcessProfileValidTimerInterval() { Task task = createValidTaskStartAutostartProcess(); task.addInput().setValue(new StringType("PT24H")).getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TIMER_INTERVAL.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.TIMER_INTERVAL.getValue()).setVersion(def.getResourceVersion()); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -125,7 +124,7 @@ public void testTaskStartAutostartProcessProfileNotValidTimerInterval() Task task = createValidTaskStartAutostartProcess(); task.addInput().setValue(new StringType("invalid_duration")).getType().addCoding() .setSystem(CodeSystem.DsfPing.URL).setCode(CodeSystem.DsfPing.Code.TIMER_INTERVAL.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setVersion(def.getResourceVersion()); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -151,7 +150,7 @@ private Task createValidTaskStartAutostartProcess() task.addInput().setValue(new StringType(ConstantsPing.PROFILE_DSF_TASK_START_PING_AUTOSTART_MESSAGE_NAME)) .getType().addCoding(BpmnMessage.messageName()); - task.addInput(DownloadResourceSizeGenerator.create(0)); + task.addInput(DownloadResourceSizeGenerator.create(0, def.getResourceVersion())); return task; } @@ -205,7 +204,7 @@ public void testTaskStartPingProcessProfileValidWithErrorMessages() { Task task = createValidTaskStartPingProcess(); - ProcessError.toTaskOutput(processErrors(4)).forEach(task::addOutput); + ProcessError.toTaskOutput(processErrors(4), def.getResourceVersion()).forEach(task::addOutput); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -233,8 +232,7 @@ public void testTaskStartPingProcessProfileValidWithTargetEndpoints() .setValue(new StringType( "Endpoint?identifier=http://dsf.dev/sid/endpoint-identifier|endpoint.target.org")) .getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue()).setVersion(def.getResourceVersion()); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -290,7 +288,7 @@ public String getCorrelationKey() Task task = createValidTaskStartPingProcess(); task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType() .addCoding(BpmnMessage.businessKey()); - task.addOutput(PingStatusGenerator + task.addOutput(pingStatusGenerator .createPingStatusOutput(target, CodeSystem.DsfPingStatus.Code.PONG_MISSING, processErrors(5)).get()); ValidationResult result = resourceValidator.validate(task); @@ -458,7 +456,7 @@ public static Task createValidTaskStartPingProcess() .addCoding(BpmnMessage.messageName()); task.addInput().setValue(new DecimalType(1)).getType().addCoding().setSystem(CodeSystem.DsfPing.URL) .setCode(CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setVersion(def.getResourceVersion()); return task; } @@ -547,8 +545,9 @@ public String getCorrelationKey() Task task = createValidTaskPing(); task.addOutput(createPongStatusOutput(target, CodeSystem.DsfPingStatus.Code.PONG_SENT)); - task.addInput(DownloadResourceSizeGenerator.create(1000)); - task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary")); + task.addInput(DownloadResourceSizeGenerator.create(1000, def.getResourceVersion())); + task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary", + def.getResourceVersion())); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -580,8 +579,7 @@ public static Task createValidTaskPing() .setValue(new Reference().setType(ResourceType.Endpoint.name()) .setIdentifier(EndpointIdentifier.withValue("endpoint.target.org"))) .getType().addCoding().setSystem(CodeSystem.DsfPing.URL) - .setCode(CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue()) - .setVersion(PingProcessPluginDefinition.RESOURCE_VERSION); + .setCode(CodeSystem.DsfPing.Code.ENDPOINT_IDENTIFIER.getValue()).setVersion(def.getResourceVersion()); return task; } @@ -603,9 +601,10 @@ public void testTaskPongValidWithReferenceAndDownloadedDurationMillisAndDownload { Task task = createValidTaskPong(); - task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary")); - task.addInput(DownloadedBytesGenerator.create(1000)); - task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000))); + task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary", + def.getResourceVersion())); + task.addInput(DownloadedBytesGenerator.create(1000, def.getResourceVersion())); + task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000), def.getResourceVersion())); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -619,11 +618,12 @@ public void testTaskPongValidWithMultipleErrorMessages() { Task task = createValidTaskPong(); - task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary")); - task.addInput(DownloadedBytesGenerator.create(1000)); - task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000))); - task.addInput(ErrorInputComponentGenerator.create(processErrors(1).get(0))); - task.addInput(ErrorInputComponentGenerator.create(processErrors(1).get(0))); + task.addInput(DownloadResourceReferenceGenerator.create("https://test.endpoint.org/fhir/Binary", + def.getResourceVersion())); + task.addInput(DownloadedBytesGenerator.create(1000, def.getResourceVersion())); + task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000), def.getResourceVersion())); + task.addInput(ErrorInputComponentGenerator.create(processErrors(1).get(0), def.getResourceVersion())); + task.addInput(ErrorInputComponentGenerator.create(processErrors(1).get(0), def.getResourceVersion())); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -686,8 +686,8 @@ private Task createValidTaskCleanupPong() task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType() .addCoding(BpmnMessage.businessKey()); - task.addInput(DownloadedBytesGenerator.create(1000)); - task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000))); + task.addInput(DownloadedBytesGenerator.create(1000, def.getResourceVersion())); + task.addInput(DownloadedDurationGenerator.create(Duration.ofMillis(1000), def.getResourceVersion())); return task; } @@ -763,17 +763,17 @@ private String fillPlaceholders(String xml) private Task.TaskOutputComponent createPingStatusOutput(Target target, CodeSystem.DsfPingStatus.Code statusCode, BigDecimal downloadSpeed, BigDecimal uploadSpeed, CodeSystem.DsfPingUnits.Code unit) { - return PingStatusGenerator + return pingStatusGenerator .createPingStatusOutput(target, statusCode, null, downloadSpeed, unit, uploadSpeed, unit).get(); } private Task.TaskOutputComponent createPongStatusOutput(Target target, CodeSystem.DsfPingStatus.Code statusCode) { - return PingStatusGenerator.createPongStatusOutput(target, statusCode, null).get(); + return pingStatusGenerator.createPongStatusOutput(target, statusCode, null).get(); } private Task.TaskOutputComponent createPingErrorOutput(ProcessError processError) { - return ProcessError.toTaskOutput(processError); + return ProcessError.toTaskOutput(processError, def.getResourceVersion()); } } From 64c50760797055e5a438f03def7fbbe097cf0efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 14:58:09 +0200 Subject: [PATCH 51/68] Is now dev.dsf.bpe.v2.ProcessPluginDefinition --- ...essPluginDefinition => dev.dsf.bpe.v2.ProcessPluginDefinition} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/META-INF/services/{dev.dsf.bpe.v1.ProcessPluginDefinition => dev.dsf.bpe.v2.ProcessPluginDefinition} (100%) diff --git a/src/main/resources/META-INF/services/dev.dsf.bpe.v1.ProcessPluginDefinition b/src/main/resources/META-INF/services/dev.dsf.bpe.v2.ProcessPluginDefinition similarity index 100% rename from src/main/resources/META-INF/services/dev.dsf.bpe.v1.ProcessPluginDefinition rename to src/main/resources/META-INF/services/dev.dsf.bpe.v2.ProcessPluginDefinition From 91e0481b86ccf2ea5a382bbb41b6c9be7934e508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 15:53:31 +0200 Subject: [PATCH 52/68] Format and sort --- .../dev/dsf/bpe/message/SendStartPing.java | 9 ++++---- .../bpe/service/GenerateAndStoreResource.java | 16 ++++++-------- ...adResourceAndMeasureSpeedInSubProcess.java | 11 +++++----- .../dsf/bpe/service/ping/LogAndSaveError.java | 3 +-- .../bpe/service/ping/LogAndSaveSendError.java | 3 +-- .../ping/LogAndSaveUploadErrorPing.java | 3 ++- .../dev/dsf/bpe/service/ping/SavePong.java | 6 +++--- .../bpe/service/ping/SelectPingTargets.java | 21 ++++++++++--------- .../pong/LogAndSaveUploadErrorPong.java | 3 +-- 9 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendStartPing.java b/src/main/java/dev/dsf/bpe/message/SendStartPing.java index ae02aa8a..b1c8557b 100644 --- a/src/main/java/dev/dsf/bpe/message/SendStartPing.java +++ b/src/main/java/dev/dsf/bpe/message/SendStartPing.java @@ -24,8 +24,9 @@ public List getAdditionalInputParameters(ProcessPluginApi ap List additionalInputParameters = new ArrayList<>(); variables.getStartTask().getInput().stream().filter(Task.ParameterComponent::hasType) - .filter(i -> i.getType().getCoding().stream().anyMatch(c -> CodeSystem.DsfPing.URL.equals(c.getSystem()) - && CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue().equals(c.getCode()))) + .filter(i -> i.getType().getCoding().stream() + .anyMatch(c -> CodeSystem.DsfPing.URL.equals(c.getSystem()) + && CodeSystem.DsfPing.Code.TARGET_ENDPOINTS.getValue().equals(c.getCode()))) .forEach(additionalInputParameters::add); variables.getStartTask().getInput().stream().filter(this::isDownloadResourceSizeParameter) @@ -36,8 +37,8 @@ public List getAdditionalInputParameters(ProcessPluginApi ap private boolean isDownloadResourceSizeParameter(ParameterComponent parameterComponent) { - return parameterComponent.getType().getCoding().stream().anyMatch( - t -> CodeSystem.DsfPing.URL.equals(t.getSystem()) + return parameterComponent.getType().getCoding().stream() + .anyMatch(t -> CodeSystem.DsfPing.URL.equals(t.getSystem()) && CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES.getValue().equals(t.getCode())); } diff --git a/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java b/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java index e2aef6d6..6f881e0e 100644 --- a/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java +++ b/src/main/java/dev/dsf/bpe/service/GenerateAndStoreResource.java @@ -144,8 +144,7 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - errorRemote); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), errorRemote); } } else if (e.getCause() instanceof ConnectTimeoutException) @@ -156,8 +155,7 @@ else if (e.getCause() instanceof ConnectTimeoutException) variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - errorRemote); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), errorRemote); } } else if (e.getCause() instanceof HttpHostConnectException) @@ -168,8 +166,7 @@ else if (e.getCause() instanceof HttpHostConnectException) variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - errorRemote); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), errorRemote); } } else @@ -180,8 +177,7 @@ else if (e.getCause() instanceof HttpHostConnectException) variables.setJsonVariable(ExecutionVariables.resourceUploadError.name(), error); if (ConstantsPing.PROCESS_NAME_PONG.equals(process)) { - variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), - errorRemote); + variables.setJsonVariable(ExecutionVariables.resourceUploadErrorRemote.name(), errorRemote); } logger.error("Unexpected error: {}", e.getMessage()); } @@ -268,8 +264,8 @@ private void setDownloadResourceSizeBytes(Variables variables, long resourceSize private IdType storeBinary(ProcessPluginApi api, RandomByteInputStream downloadResourceContent) { - return api.getDsfClientProvider().getLocal().withMinimalReturn().createBinary( - downloadResourceContent, ConstantsPing.DOWNLOAD_RESOURCE_MIME_TYPE, + return api.getDsfClientProvider().getLocal().withMinimalReturn().createBinary(downloadResourceContent, + ConstantsPing.DOWNLOAD_RESOURCE_MIME_TYPE, api.getOrganizationProvider().getLocalOrganization().get().getIdElement().getValue()); } diff --git a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java index e467a277..bfb28103 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java +++ b/src/main/java/dev/dsf/bpe/service/ping/DownloadResourceAndMeasureSpeedInSubProcess.java @@ -54,16 +54,17 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound @Override public ServiceTaskErrorHandler getErrorHandler() { - return new DefaultServiceTaskErrorHandler() { + return new DefaultServiceTaskErrorHandler() + { @Override public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) { logger.error("Unexpected error while downloading resource and measuring speed.", exception); String correlationKey = variables.getTarget().getCorrelationKey(); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - variables, correlationKey); - return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + ErrorListUtils.add(new ProcessError(ConstantsPing.PROCESS_NAME_PING, + CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), variables, correlationKey); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, + ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); } }; } diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java index 22a63004..a4bac513 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveError.java @@ -21,8 +21,7 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro { Target target = variables.getTarget(); - ProcessError error = variables - .getVariableLocal(ExecutionVariables.resourceDownloadError.name()); + ProcessError error = variables.getVariableLocal(ExecutionVariables.resourceDownloadError.name()); ErrorListUtils.add(error, variables, target.getCorrelationKey()); diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java index b32bdb16..7fae1245 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveSendError.java @@ -23,8 +23,7 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro { String correlationKey = variables.getTarget().getCorrelationKey(); ProcessError error = variables.getVariableLocal(ExecutionVariables.error.name()); - CodeSystem.DsfPingStatus.Code status = variables - .getVariableLocal(ExecutionVariables.statusCode.name()); + CodeSystem.DsfPingStatus.Code status = variables.getVariableLocal(ExecutionVariables.statusCode.name()); Objects.requireNonNull(status, "status"); ErrorListUtils.add(error, variables, correlationKey); diff --git a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java index 3f66ed3a..c31c4259 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java +++ b/src/main/java/dev/dsf/bpe/service/ping/LogAndSaveUploadErrorPing.java @@ -30,7 +30,8 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro @Override public ServiceTaskErrorHandler getErrorHandler() { - return new DefaultServiceTaskErrorHandler() { + return new DefaultServiceTaskErrorHandler() + { @Override public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) { diff --git a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java index 4e3faf92..363c9037 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java @@ -39,9 +39,9 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound .getFirstInputParameterValue(pong, CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.DOWNLOADED_DURATION_MILLIS.getValue(), org.hl7.fhir.r4.model.Duration.class); - optDownloadedDuration.ifPresent( - duration -> variables.setJsonVariable(ExecutionVariables.uploadedDuration.correlatedValue(correlationKey), - Duration.ofMillis(duration.getValue().longValue()))); + optDownloadedDuration.ifPresent(duration -> variables.setJsonVariable( + ExecutionVariables.uploadedDuration.correlatedValue(correlationKey), + Duration.ofMillis(duration.getValue().longValue()))); Optional optDownloadedBytes = api.getTaskHelper().getFirstInputParameterValue(pong, CodeSystem.DsfPing.URL, CodeSystem.DsfPing.Code.DOWNLOADED_BYTES.getValue(), DecimalType.class); diff --git a/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java b/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java index df1b9879..137747bb 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SelectPingTargets.java @@ -75,15 +75,16 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound @Override public ServiceTaskErrorHandler getErrorHandler() { - return new DefaultServiceTaskErrorHandler() { + return new DefaultServiceTaskErrorHandler() + { @Override public Exception handleException(ProcessPluginApi api, Variables variables, Exception exception) { logger.error("Unexpected error while selecting ping targets.", exception); - ErrorListUtils.add( - new ProcessError(ConstantsPing.PROCESS_NAME_PING, CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), - variables); - return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); + ErrorListUtils.add(new ProcessError(ConstantsPing.PROCESS_NAME_PING, + CodeSystem.DsfPingError.Concept.LOCAL_UNKNOWN, null), variables); + return new ErrorBoundaryEvent(ConstantsPing.BPMN_ERROR_CODE_UNEXPECTED_ERROR, + ConstantsPing.BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR); } }; } @@ -102,7 +103,8 @@ private Stream searchForEndpoints(ProcessPluginApi api, UriComponents return searchForEndpoints(api, searchParameters, 1, 0); } - private Stream searchForEndpoints(ProcessPluginApi api, UriComponents searchParameters, int page, int currentTotal) + private Stream searchForEndpoints(ProcessPluginApi api, UriComponents searchParameters, int page, + int currentTotal) { if (searchParameters.getPathSegments().isEmpty()) return Stream.empty(); @@ -115,8 +117,8 @@ private Stream searchForEndpoints(ProcessPluginApi api, UriComponents queryParameters.putAll(searchParameters.getQueryParams()); queryParameters.put("_page", Collections.singletonList(String.valueOf(page))); - Bundle searchResult = api.getDsfClientProvider().getLocal() - .searchWithStrictHandling(resourceType.get(), queryParameters); + Bundle searchResult = api.getDsfClientProvider().getLocal().searchWithStrictHandling(resourceType.get(), + queryParameters); if (searchResult.getTotal() > currentTotal + searchResult.getEntry().size()) return Stream.concat(toEndpoints(searchResult), @@ -158,8 +160,7 @@ private Predicate isLocalEndpoint(ProcessPluginApi api) private Stream allEndpoints(ProcessPluginApi api, int page, int currentTotal) { - Bundle searchResult = api.getDsfClientProvider().getLocal().searchWithStrictHandling( - Endpoint.class, + Bundle searchResult = api.getDsfClientProvider().getLocal().searchWithStrictHandling(Endpoint.class, Map.of("status", Collections.singletonList("active"), "identifier", Collections.singletonList("http://dsf.dev/sid/endpoint-identifier|"), "_page", Collections.singletonList(String.valueOf(page)))); diff --git a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java index 301f9e07..8e857191 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java +++ b/src/main/java/dev/dsf/bpe/service/pong/LogAndSaveUploadErrorPong.java @@ -21,8 +21,7 @@ public void execute(ProcessPluginApi processPluginApi, Variables variables) thro ProcessError error = variables.getVariable(ExecutionVariables.resourceUploadError.name()); ErrorListUtils.add(error, variables); - ProcessError errorRemote = variables - .getVariable(ExecutionVariables.resourceUploadErrorRemote.name()); + ProcessError errorRemote = variables.getVariable(ExecutionVariables.resourceUploadErrorRemote.name()); ErrorListUtils.addRemote(errorRemote, variables); logger.info("Error while storing binary resource for download: {}", error.concept().getDisplay()); From 985167d2f1f30dc031965a14d06ad8ac840a7ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 16:00:59 +0200 Subject: [PATCH 53/68] API v2 changes: - Java 25 - Add dsf-bpe-process-api-v2-impl test dependency as ProcessAuthorizationHelperImpl has moved there from dsf-fhir-validation - Add resource filtering to replace placeholders in plugin.properties --- pom.xml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c40835f2..4a6a5ad2 100644 --- a/pom.xml +++ b/pom.xml @@ -12,8 +12,8 @@ 2026-07-05T12:00:00+02:00 UTF-8 - 17 - 17 + 25 + 25 2.1.0 7.0.8 @@ -83,6 +83,12 @@ ${dsf.version} test + + dev.dsf + dsf-bpe-process-api-v2-impl + ${dsf.version} + test + junit junit @@ -92,6 +98,22 @@ + + + src/main/resources + false + + plugin.properties + + + + src/main/resources + true + + plugin.properties + + + org.apache.maven.plugins From fff4febf89d82a8a9994c70f98aeed91a39bacc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 16:05:28 +0200 Subject: [PATCH 54/68] Add error message for unexpected errors occurring during the process and added a constant for error code and message when no pong target can be found --- src/main/java/dev/dsf/bpe/ConstantsPing.java | 4 ++++ src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/dsf/bpe/ConstantsPing.java b/src/main/java/dev/dsf/bpe/ConstantsPing.java index cca333b8..905e8b82 100644 --- a/src/main/java/dev/dsf/bpe/ConstantsPing.java +++ b/src/main/java/dev/dsf/bpe/ConstantsPing.java @@ -64,6 +64,10 @@ private ConstantsPing() public static final String PONG_TIMEOUT_DURATION_DEFAULT_VALUE = "PT30S"; public static final String BPMN_ERROR_CODE_UNEXPECTED_ERROR = "unexpected-error"; + public static final String BPMN_ERROR_MESSAGE_UNEXPECTED_ERROR = "An unexpected error has occurred"; + + public static final String BPMN_ERROR_CODE_TARGET_NOT_ALLOWED = "target_not_allowed"; + public static final String BPMN_ERROR_MESSAGE_TARGET_NOT_ALLOWED = "target_not_allowed"; public static final String POTENTIAL_FIX_URL_BASE = "https://dsf.dev/s"; public static final String POTENTIAL_FIX_URL_ERROR_HTTP = POTENTIAL_FIX_URL_BASE + "/error-http"; diff --git a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java index 13976f18..4202abd8 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java +++ b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java @@ -1,5 +1,8 @@ package dev.dsf.bpe.service.pong; +import static dev.dsf.bpe.ConstantsPing.BPMN_ERROR_CODE_TARGET_NOT_ALLOWED; +import static dev.dsf.bpe.ConstantsPing.BPMN_ERROR_MESSAGE_TARGET_NOT_ALLOWED; + import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +36,7 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound logger.warn( "Pong response target (organization {}, endpoint {}) not found locally or not active, not sending pong", targetOrganizationIdentifierValue, targetEndpointIdentifierValue); - return new ErrorBoundaryEvent("target_not_allowed", null ); + return new ErrorBoundaryEvent(BPMN_ERROR_CODE_TARGET_NOT_ALLOWED, BPMN_ERROR_MESSAGE_TARGET_NOT_ALLOWED); }); variables.setTarget(variables.createTarget(targetOrganizationIdentifierValue, targetEndpointIdentifierValue, From 4c1a9103131c30fbb7ddf64eb85954a1f7798283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 16:56:17 +0200 Subject: [PATCH 55/68] API v2 changes: - add meta.profile to all FHIR resources - add dsf-meta-2.0.0 StructureDefinition to validation context as the DSF ActivityDefinition profile has this profile set as the profile for ActivityDefinition.meta which needs to be validated --- src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java | 3 ++- .../resources/fhir/ActivityDefinition/dsf-ping-autostart.xml | 1 + src/main/resources/fhir/ActivityDefinition/dsf-ping.xml | 1 + src/main/resources/fhir/ActivityDefinition/dsf-pong.xml | 1 + src/main/resources/fhir/CodeSystem/dsf-ping-error.xml | 1 + src/main/resources/fhir/CodeSystem/dsf-ping-status.xml | 1 + src/main/resources/fhir/CodeSystem/dsf-ping.xml | 1 + .../resources/fhir/StructureDefinition/dsf-extension-error.xml | 1 + .../fhir/StructureDefinition/dsf-extension-ping-status.xml | 1 + .../fhir/StructureDefinition/dsf-task-cleanup-pong.xml | 3 ++- src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml | 3 ++- src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml | 3 ++- .../fhir/StructureDefinition/dsf-task-start-ping-autostart.xml | 3 ++- .../resources/fhir/StructureDefinition/dsf-task-start-ping.xml | 3 ++- .../fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml | 3 ++- src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml | 1 + src/main/resources/fhir/ValueSet/dsf-ping-status.xml | 1 + src/main/resources/fhir/ValueSet/dsf-ping.xml | 1 + src/main/resources/fhir/ValueSet/dsf-pong-status.xml | 1 + .../dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java | 3 ++- 20 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java index 4202abd8..76aa306e 100644 --- a/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java +++ b/src/main/java/dev/dsf/bpe/service/pong/SelectPongTarget.java @@ -36,7 +36,8 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound logger.warn( "Pong response target (organization {}, endpoint {}) not found locally or not active, not sending pong", targetOrganizationIdentifierValue, targetEndpointIdentifierValue); - return new ErrorBoundaryEvent(BPMN_ERROR_CODE_TARGET_NOT_ALLOWED, BPMN_ERROR_MESSAGE_TARGET_NOT_ALLOWED); + return new ErrorBoundaryEvent(BPMN_ERROR_CODE_TARGET_NOT_ALLOWED, + BPMN_ERROR_MESSAGE_TARGET_NOT_ALLOWED); }); variables.setTarget(variables.createTarget(targetOrganizationIdentifierValue, targetEndpointIdentifierValue, diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml b/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml index 1ac37a1e..1b6a1e12 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml b/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml index 367348ad..61446486 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml b/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml index efde8372..b114ba71 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml b/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml index fc7862be..9d868173 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml b/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml index 8dfaf7e5..5d10fff9 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping.xml b/src/main/resources/fhir/CodeSystem/dsf-ping.xml index 100877d6..52319c75 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml b/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml index 6476c0fa..2e0e7c62 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml b/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml index 5d42cc76..7de26869 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml index aa0dbfda..707d8269 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml index 245253da..23a47b73 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml index e57266cb..a427160f 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml index 0666b67d..ff7b4203 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml index a04e9815..d78bf065 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml index bc6a7b1b..10066e91 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml @@ -1,5 +1,6 @@ + @@ -18,7 +19,7 @@ - + diff --git a/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml b/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml index 647e36fe..4f95b86f 100644 --- a/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml +++ b/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/ValueSet/dsf-ping-status.xml b/src/main/resources/fhir/ValueSet/dsf-ping-status.xml index 0729a89a..aa85bfe9 100644 --- a/src/main/resources/fhir/ValueSet/dsf-ping-status.xml +++ b/src/main/resources/fhir/ValueSet/dsf-ping-status.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/ValueSet/dsf-ping.xml b/src/main/resources/fhir/ValueSet/dsf-ping.xml index 0fef6dbf..38c412e6 100644 --- a/src/main/resources/fhir/ValueSet/dsf-ping.xml +++ b/src/main/resources/fhir/ValueSet/dsf-ping.xml @@ -1,5 +1,6 @@ + diff --git a/src/main/resources/fhir/ValueSet/dsf-pong-status.xml b/src/main/resources/fhir/ValueSet/dsf-pong-status.xml index 09860584..8b2736a5 100644 --- a/src/main/resources/fhir/ValueSet/dsf-pong-status.xml +++ b/src/main/resources/fhir/ValueSet/dsf-pong-status.xml @@ -1,5 +1,6 @@ + diff --git a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java index b61d0415..52b80fff 100644 --- a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java +++ b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java @@ -29,7 +29,8 @@ public class ActivityDefinitionProfileTest @ClassRule public static final ValidationSupportRule validationRule = new ValidationSupportRule(def.getVersion(), def.getReleaseDate(), - Arrays.asList("dsf-activity-definition-2.0.0.xml", "dsf-extension-process-authorization-2.0.0.xml", + Arrays.asList("dsf-meta-2.0.0.xml", "dsf-activity-definition-2.0.0.xml", + "dsf-extension-process-authorization-2.0.0.xml", "dsf-extension-process-authorization-organization-2.0.0.xml", "dsf-extension-process-authorization-organization-practitioner-2.0.0.xml", "dsf-extension-process-authorization-parent-organization-role-2.0.0.xml", From 7bc1ec149ad6cfb552f45b863a3d22479aef577a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 17:35:15 +0200 Subject: [PATCH 56/68] Profiles should not have their versions appended and StructureDefinition resources always have http://dsf.dev/fhir/StructureDefinition/structure-definition as their profile not http://dsf.dev/fhir/StructureDefinition/task even if they are StructureDefinitions for Task resources --- .../resources/fhir/ActivityDefinition/dsf-ping-autostart.xml | 2 +- src/main/resources/fhir/ActivityDefinition/dsf-ping.xml | 2 +- src/main/resources/fhir/ActivityDefinition/dsf-pong.xml | 2 +- src/main/resources/fhir/CodeSystem/dsf-ping-error.xml | 2 +- src/main/resources/fhir/CodeSystem/dsf-ping-status.xml | 2 +- src/main/resources/fhir/CodeSystem/dsf-ping.xml | 2 +- .../resources/fhir/StructureDefinition/dsf-extension-error.xml | 2 +- .../fhir/StructureDefinition/dsf-extension-ping-status.xml | 2 +- .../fhir/StructureDefinition/dsf-task-cleanup-pong.xml | 2 +- src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml | 2 +- src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml | 2 +- .../fhir/StructureDefinition/dsf-task-start-ping-autostart.xml | 2 +- .../resources/fhir/StructureDefinition/dsf-task-start-ping.xml | 2 +- .../fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml | 2 +- src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml | 2 +- src/main/resources/fhir/ValueSet/dsf-ping-status.xml | 2 +- src/main/resources/fhir/ValueSet/dsf-ping.xml | 2 +- src/main/resources/fhir/ValueSet/dsf-pong-status.xml | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml b/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml index 1b6a1e12..764006a2 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-ping-autostart.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml b/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml index 61446486..2a66448d 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-ping.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml b/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml index b114ba71..6737cc91 100644 --- a/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml +++ b/src/main/resources/fhir/ActivityDefinition/dsf-pong.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml b/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml index 9d868173..4da0fb83 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping-error.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml b/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml index 5d10fff9..a40b872d 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping-status.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/CodeSystem/dsf-ping.xml b/src/main/resources/fhir/CodeSystem/dsf-ping.xml index 52319c75..ec29715c 100644 --- a/src/main/resources/fhir/CodeSystem/dsf-ping.xml +++ b/src/main/resources/fhir/CodeSystem/dsf-ping.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml b/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml index 2e0e7c62..28cc2cec 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-extension-error.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml b/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml index 7de26869..e6a9a12c 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-extension-ping-status.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml index 707d8269..188af93d 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-cleanup-pong.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml index 23a47b73..7795a118 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-ping.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml index a427160f..f0544f2c 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-pong.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml index ff7b4203..df8c364d 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping-autostart.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml index d78bf065..684e622d 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-start-ping.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml b/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml index 10066e91..1f995ea5 100644 --- a/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml +++ b/src/main/resources/fhir/StructureDefinition/dsf-task-stop-ping-autostart.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml b/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml index 4f95b86f..682d8705 100644 --- a/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml +++ b/src/main/resources/fhir/ValueSet/dsf-network-speed-units.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ValueSet/dsf-ping-status.xml b/src/main/resources/fhir/ValueSet/dsf-ping-status.xml index aa85bfe9..a7103782 100644 --- a/src/main/resources/fhir/ValueSet/dsf-ping-status.xml +++ b/src/main/resources/fhir/ValueSet/dsf-ping-status.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ValueSet/dsf-ping.xml b/src/main/resources/fhir/ValueSet/dsf-ping.xml index 38c412e6..da239c81 100644 --- a/src/main/resources/fhir/ValueSet/dsf-ping.xml +++ b/src/main/resources/fhir/ValueSet/dsf-ping.xml @@ -1,6 +1,6 @@ - + diff --git a/src/main/resources/fhir/ValueSet/dsf-pong-status.xml b/src/main/resources/fhir/ValueSet/dsf-pong-status.xml index 8b2736a5..8adc166d 100644 --- a/src/main/resources/fhir/ValueSet/dsf-pong-status.xml +++ b/src/main/resources/fhir/ValueSet/dsf-pong-status.xml @@ -1,6 +1,6 @@ - + From 0d10da4f17cf3dc7e3dc21260676e5728ff79617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 30 Jun 2026 17:39:20 +0200 Subject: [PATCH 57/68] Needs to conform to BPMN diagram where this is used as the implementation for a MessageIntermediateThrowEvent --- src/main/java/dev/dsf/bpe/message/SendStartPing.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendStartPing.java b/src/main/java/dev/dsf/bpe/message/SendStartPing.java index b1c8557b..4fa4f68c 100644 --- a/src/main/java/dev/dsf/bpe/message/SendStartPing.java +++ b/src/main/java/dev/dsf/bpe/message/SendStartPing.java @@ -8,14 +8,14 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.v2.ProcessPluginApi; -import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.MessageIntermediateThrowEvent; import dev.dsf.bpe.v2.activity.task.BusinessKeyStrategies; import dev.dsf.bpe.v2.activity.task.BusinessKeyStrategy; import dev.dsf.bpe.v2.activity.values.SendTaskValues; import dev.dsf.bpe.v2.variables.Target; import dev.dsf.bpe.v2.variables.Variables; -public class SendStartPing implements MessageSendTask +public class SendStartPing implements MessageIntermediateThrowEvent { @Override public List getAdditionalInputParameters(ProcessPluginApi api, Variables variables, From 20af652e67e941651b3c604c300172d6d59b43e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Thu, 2 Jul 2026 14:54:37 +0200 Subject: [PATCH 58/68] Remove unused imports --- src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java | 1 - src/main/java/dev/dsf/bpe/message/SendPingMessage.java | 2 -- src/main/java/dev/dsf/bpe/spring/config/PingConfig.java | 4 ---- .../util/task/input/generator/DownloadedBytesGenerator.java | 2 -- .../task/input/generator/DownloadedDurationGenerator.java | 1 - 5 files changed, 10 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java index b750ad11..57bcffac 100644 --- a/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java +++ b/src/main/java/dev/dsf/bpe/message/CleanupPongMessage.java @@ -3,7 +3,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; diff --git a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java index b9747c9e..571176b8 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Identifier; @@ -15,7 +14,6 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.ConstantsPing; import dev.dsf.bpe.ExecutionVariables; -import dev.dsf.bpe.PingProcessPluginDefinition; import dev.dsf.bpe.util.task.SendTaskErrorConverter; import dev.dsf.bpe.util.task.input.generator.DownloadResourceReferenceGenerator; import dev.dsf.bpe.util.task.input.generator.DownloadResourceSizeGenerator; diff --git a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java index bfbd9680..f179d073 100644 --- a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java +++ b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java @@ -2,16 +2,12 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.listener.PingPongProcessPluginDeploymentStateListener; import dev.dsf.bpe.listener.SetCorrelationKeyListener; diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java index e4cce434..c20ce9ce 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedBytesGenerator.java @@ -4,8 +4,6 @@ import org.hl7.fhir.r4.model.Task; import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.PingProcessPluginDefinition; -import dev.dsf.bpe.v2.ProcessPluginApi; public final class DownloadedBytesGenerator { diff --git a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java index 5f50b9cc..c9bf2e7e 100644 --- a/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java +++ b/src/main/java/dev/dsf/bpe/util/task/input/generator/DownloadedDurationGenerator.java @@ -5,7 +5,6 @@ import org.hl7.fhir.r4.model.Task; import dev.dsf.bpe.CodeSystem; -import dev.dsf.bpe.PingProcessPluginDefinition; public final class DownloadedDurationGenerator { From 0367850114a57ce3e1e1a6a5a8831c8db364a124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Mon, 6 Jul 2026 11:08:32 +0200 Subject: [PATCH 59/68] Spring UriComponents and UriComponentsBuilder are no longer available to the class loader for process plugins at runtime. Therefore, shade them into the jar --- pom.xml | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 4a6a5ad2..4025ab65 100644 --- a/pom.xml +++ b/pom.xml @@ -53,27 +53,6 @@ org.springframework spring-web ${spring.version} - provided - - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - 2.20.0 - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-annotations - - @@ -149,7 +128,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.6.1 + 3.6.2 package @@ -157,18 +136,27 @@ shade - false - com.fasterxml.jackson.datatype:jackson-datatype-jsr310 - - ** - + *:* - META-INF/MANIFEST.MF + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + META-INF/*.MF + META-INF/NOTICE + META-INF/versions/9/module-info.class + META-INF/notice.txt + META-INF/spring/aot.factories + false + true + + + + From 76b43c411fedf21cafa1a8584cb35d317d6f75a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Mon, 6 Jul 2026 11:13:26 +0200 Subject: [PATCH 60/68] Added execution listeners that set a string version of status code variables because JUEL cannot evaluate expressions that treat variables set by Variables#setJsonVariable as their deserialized form. For example, calling setJsonVariable(myObject) and calling ${myObject.myMethod()} in the JUEL expression will throw an exception because JUEL only sees the JsonHolder object (which holds myObject in serialized form), not the deserialized object itself --- .../java/dev/dsf/bpe/ExecutionVariables.java | 1 + .../listener/PingStatusGatewayListener.java | 27 +++++++ .../listener/PongStatusGatewayListener.java | 27 +++++++ .../dev/dsf/bpe/spring/config/PingConfig.java | 4 +- src/main/resources/bpe/ping.bpmn | 26 ++++--- src/main/resources/bpe/pong.bpmn | 72 ++++++++++--------- 6 files changed, 113 insertions(+), 44 deletions(-) create mode 100644 src/main/java/dev/dsf/bpe/listener/PingStatusGatewayListener.java create mode 100644 src/main/java/dev/dsf/bpe/listener/PongStatusGatewayListener.java diff --git a/src/main/java/dev/dsf/bpe/ExecutionVariables.java b/src/main/java/dev/dsf/bpe/ExecutionVariables.java index a606a5f7..766ee71d 100644 --- a/src/main/java/dev/dsf/bpe/ExecutionVariables.java +++ b/src/main/java/dev/dsf/bpe/ExecutionVariables.java @@ -9,6 +9,7 @@ public enum ExecutionVariables downloadResource, downloadResourceReference, statusCode, + statusCodeString, error, errorLocal, errorRemote, diff --git a/src/main/java/dev/dsf/bpe/listener/PingStatusGatewayListener.java b/src/main/java/dev/dsf/bpe/listener/PingStatusGatewayListener.java new file mode 100644 index 00000000..923ac20f --- /dev/null +++ b/src/main/java/dev/dsf/bpe/listener/PingStatusGatewayListener.java @@ -0,0 +1,27 @@ +package dev.dsf.bpe.listener; + +import java.util.Objects; + +import dev.dsf.bpe.CodeSystem; +import dev.dsf.bpe.ExecutionVariables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ExecutionListener; +import dev.dsf.bpe.v2.variables.Variables; + +public class PingStatusGatewayListener implements ExecutionListener +{ + @Override + public void notify(ProcessPluginApi api, Variables variables) throws Exception + { + setPingStatusAsString(variables); + } + + private void setPingStatusAsString(Variables variables) + { + CodeSystem.DsfPingStatus.Code statusCode = variables.getVariableLocal(ExecutionVariables.statusCode.name()); + if (Objects.nonNull(statusCode)) + { + variables.setStringLocal(ExecutionVariables.statusCodeString.name(), statusCode.getValue()); + } + } +} diff --git a/src/main/java/dev/dsf/bpe/listener/PongStatusGatewayListener.java b/src/main/java/dev/dsf/bpe/listener/PongStatusGatewayListener.java new file mode 100644 index 00000000..d852feca --- /dev/null +++ b/src/main/java/dev/dsf/bpe/listener/PongStatusGatewayListener.java @@ -0,0 +1,27 @@ +package dev.dsf.bpe.listener; + +import java.util.Objects; + +import dev.dsf.bpe.CodeSystem; +import dev.dsf.bpe.ExecutionVariables; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.ExecutionListener; +import dev.dsf.bpe.v2.variables.Variables; + +public class PongStatusGatewayListener implements ExecutionListener +{ + @Override + public void notify(ProcessPluginApi api, Variables variables) throws Exception + { + setPongStatusAsString(variables); + } + + private void setPongStatusAsString(Variables variables) + { + CodeSystem.DsfPingStatus.Code statusCode = variables.getVariableLocal(ExecutionVariables.statusCode.name()); + if (Objects.nonNull(statusCode)) + { + variables.setStringLocal(ExecutionVariables.statusCodeString.name(), statusCode.getValue()); + } + } +} diff --git a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java index f179d073..d22d2008 100644 --- a/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java +++ b/src/main/java/dev/dsf/bpe/spring/config/PingConfig.java @@ -10,6 +10,8 @@ import dev.dsf.bpe.CodeSystem; import dev.dsf.bpe.listener.PingPongProcessPluginDeploymentStateListener; +import dev.dsf.bpe.listener.PingStatusGatewayListener; +import dev.dsf.bpe.listener.PongStatusGatewayListener; import dev.dsf.bpe.listener.SetCorrelationKeyListener; import dev.dsf.bpe.mail.AggregateErrorMailService; import dev.dsf.bpe.message.CleanupPongMessage; @@ -120,7 +122,7 @@ public static ActivityPrototypeBeanCreator activityPrototypeBeanCreator() DownloadResourceAndMeasureSpeedInSubProcess.class, Cleanup.class, LogAndSaveAndStoreError.class, LogAndSaveError.class, EstimateCleanupTimerDuration.class, SavePong.class, SetEndpointIdentifier.class, LogAndSaveSendError.class, SaveTimeoutError.class, LogAndSaveUploadErrorPing.class, - LogAndSaveUploadErrorPong.class); + LogAndSaveUploadErrorPong.class, PingStatusGatewayListener.class, PongStatusGatewayListener.class); } @Bean diff --git a/src/main/resources/bpe/ping.bpmn b/src/main/resources/bpe/ping.bpmn index 9cc5e928..f8bce8b9 100644 --- a/src/main/resources/bpe/ping.bpmn +++ b/src/main/resources/bpe/ping.bpmn @@ -42,7 +42,10 @@ Flow_1fjeq2h Flow_136htek - + + + + Flow_08vgmf6 Flow_1j54c2s Flow_101sqed @@ -122,7 +125,7 @@ - ${execution.hasVariable('statusCode') && (statusCode.getValue() == 'not-allowed' || statusCode.getValue() == 'not-reachable')} + ${execution.hasVariable('statusCodeString') && (statusCodeString == 'not-allowed' || statusCodeString == 'not-reachable')} @@ -290,10 +293,16 @@ Store = store on DSF FHIR server either as separate resource or output parameter + + + + + + @@ -323,24 +332,21 @@ Store = store on DSF FHIR server either as separate resource or output parameter - - - + + + - - + + - - - diff --git a/src/main/resources/bpe/pong.bpmn b/src/main/resources/bpe/pong.bpmn index 97574644..11c68b66 100644 --- a/src/main/resources/bpe/pong.bpmn +++ b/src/main/resources/bpe/pong.bpmn @@ -35,7 +35,10 @@ Flow_1o3n9u6 Flow_0fzmjzb - + + + + Flow_0fzmjzb Flow_0h8flp6 Flow_1bzjspe @@ -99,7 +102,7 @@ - ${execution.hasVariable('statusCode') && (statusCode.getValue() == 'not-reachable' || statusCode.getValue() == 'not-allowed')} + ${execution.hasVariable('statusCodeString') && (statusCodeString == 'not-reachable' || statusCodeString == 'not-allowed')} @@ -231,6 +234,9 @@ Store = store on DSF FHIR server either as separate resource or output parameter + + + @@ -241,13 +247,26 @@ Store = store on DSF FHIR server either as separate resource or output parameter + + + + + + + + + + + + + @@ -255,10 +274,28 @@ Store = store on DSF FHIR server either as separate resource or output parameter + + + + + + + + + + + + + + + + + + @@ -276,37 +313,6 @@ Store = store on DSF FHIR server either as separate resource or output parameter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 9ff28e5b996bb978aeb13b98c1743d6f52680cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Mon, 6 Jul 2026 11:37:27 +0200 Subject: [PATCH 61/68] Added named id's to all tasks to make debugging easier when the BPE throws an exception like "... has fatal error in step [activity id]" --- src/main/resources/bpe/ping.bpmn | 116 +++++++++++++++--------------- src/main/resources/bpe/pong.bpmn | 118 +++++++++++++++---------------- 2 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/main/resources/bpe/ping.bpmn b/src/main/resources/bpe/ping.bpmn index f8bce8b9..388beb43 100644 --- a/src/main/resources/bpe/ping.bpmn +++ b/src/main/resources/bpe/ping.bpmn @@ -38,7 +38,7 @@ Flow_0y9usku Flow_1lghrxh - + Flow_1fjeq2h Flow_136htek @@ -61,7 +61,7 @@ Flow_1ho1hys - + http://dsf.dev/bpe/Process/pong|#{version} @@ -81,11 +81,11 @@ Flow_13u1nzy Flow_1yt9547 - + Flow_1yt9547 Flow_1ncztgo - + http://dsf.dev/fhir/StructureDefinition/task-cleanup-pong|#{version} @@ -101,7 +101,7 @@ Flow_18wxsor Flow_0klalf8 - + Flow_0qif01p Flow_0jcfur3 @@ -117,32 +117,32 @@ Flow_03nx6rk Flow_0c6l9ff - + - + - - - + + + ${execution.hasVariable('statusCodeString') && (statusCodeString == 'not-allowed' || statusCodeString == 'not-reachable')} ${downloadResourceSizeBytes < 0} - - - - - + + + + + Flow_1ewmc79 Flow_1jwekqw - + - - + + Flow_101sqed Flow_0upu487 @@ -151,12 +151,12 @@ Flow_0qif01p Flow_18wxsor - - + + ${execution.hasVariable('resourceDownloadError')} - - + + Flow_1m5uggy @@ -164,13 +164,13 @@ Flow_1m5uggy - + Flow_0c6l9ff - + ping @@ -179,7 +179,7 @@ Flow_152nb9r Flow_1op4sei - + ping @@ -189,7 +189,7 @@ Flow_1mer14f Flow_0gubpgz - + Flow_0gubpgz Flow_1du5wys @@ -202,7 +202,7 @@ Flow_1qyomuj Flow_1c15ef2 - + Flow_1c15ef2 Flow_0j92st0 @@ -215,22 +215,22 @@ Flow_1hor4v7 - - - - - + + + + + ${downloadResourceSizeBytes < 0} - - - + + + Flow_0xy3953 Flow_0fxlsv3 - - + + Flow_0z3dgxw Flow_0ejw9k5 @@ -239,22 +239,22 @@ Flow_0z3dgxw Flow_1qyomuj - - + + ${execution.hasVariable('resourceUploadError')} - - - + + + Flow_1hor4v7 Flow_0xy3953 - + Flow_1mer14f - + Log = logger Save = save as execution variable @@ -287,7 +287,7 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + @@ -303,22 +303,22 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + - + - + @@ -328,11 +328,11 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + @@ -450,14 +450,14 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + - + @@ -467,7 +467,7 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + @@ -480,17 +480,17 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + - + diff --git a/src/main/resources/bpe/pong.bpmn b/src/main/resources/bpe/pong.bpmn index 11c68b66..5f13e123 100644 --- a/src/main/resources/bpe/pong.bpmn +++ b/src/main/resources/bpe/pong.bpmn @@ -10,7 +10,7 @@ Flow_10z0d4x Flow_08gidyv - + Flow_10z0d4x Flow_0vqsjzn @@ -20,7 +20,7 @@ Flow_0dp8f59 Flow_1o3n9u6 - + http://dsf.dev/bpe/Process/ping|#{version} @@ -66,11 +66,11 @@ Flow_0yujsot Flow_0x7t1ii - + Flow_1w3kcjh Flow_1jehvly - + pong @@ -81,7 +81,7 @@ Flow_0h8flp6 Flow_0zib7wr - + pong @@ -90,114 +90,114 @@ Flow_0x7t1ii Flow_033lqly - + Flow_17wqhp8 Flow_0gvrnxd - + ${downloadResourceSizeBytes < 0} - - - - + + + + ${execution.hasVariable('statusCodeString') && (statusCodeString == 'not-reachable' || statusCodeString == 'not-allowed')} - + ${downloadResourceSizeBytes < 0} - - - + + + Flow_1j5lf0u Flow_1oo1n55 - + Flow_1oo1n55 Flow_1fzloso - + Flow_1bgedez - - + + Flow_1eh8lho Flow_1n4fb8d Flow_1lfcycx - - - + + + Flow_1ttsk1o Flow_1eh8lho - - - + + + Flow_0pp3r2w Flow_0yujsot - - - + + + Flow_1xfk4ds Flow_1n4fb8d - - + + Flow_0zib7wr Flow_1bgedez - + Flow_19b3cp4 Flow_1j5lf0u - - + + Flow_1fzloso Flow_1gap0hi Flow_0qxt5zo - + Flow_0qxt5zo - - + + Flow_0vqsjzn Flow_0pp3r2w Flow_1w3kcjh - - - + + + ${execution.hasVariable('resourceDownloadError')} - + Flow_033lqly Flow_17wqhp8 Flow_15xatzp - - + + ${execution.hasVariable('resourceUploadError')} - + Flow_15xatzp Flow_0dp8f59 - + Log = logger Save = save as execution variable @@ -221,14 +221,14 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + @@ -253,25 +253,25 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + - + - + - + - + @@ -280,27 +280,27 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + - + - + - + - + - + @@ -313,7 +313,7 @@ Store = store on DSF FHIR server either as separate resource or output parameter - + From 71b9701827dc12db191f9037fe0b1952f377f4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Mon, 6 Jul 2026 13:12:14 +0200 Subject: [PATCH 62/68] Properly serializing records with jackson requires configuring jackson to auto-detect fields --- src/main/java/dev/dsf/bpe/ProcessError.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/dev/dsf/bpe/ProcessError.java b/src/main/java/dev/dsf/bpe/ProcessError.java index 6cdd05c5..434b9974 100644 --- a/src/main/java/dev/dsf/bpe/ProcessError.java +++ b/src/main/java/dev/dsf/bpe/ProcessError.java @@ -12,6 +12,9 @@ import org.hl7.fhir.r4.model.Task; import org.hl7.fhir.r4.model.UrlType; +import com.fasterxml.jackson.annotation.JsonAutoDetect; + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public record ProcessError(String process, CodeSystem.DsfPingError.Concept concept, String potentialFixUrl) implements Serializable { From 1b62fdfd3a1dd69cb83fceab305ccecb47351d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 7 Jul 2026 11:47:33 +0200 Subject: [PATCH 63/68] Using the wrong constructor made the task sender not use the getAdditionalInputParameters method from the SendPingMessage implementation --- src/main/java/dev/dsf/bpe/message/SendPingMessage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java index 571176b8..268543b4 100644 --- a/src/main/java/dev/dsf/bpe/message/SendPingMessage.java +++ b/src/main/java/dev/dsf/bpe/message/SendPingMessage.java @@ -61,7 +61,8 @@ public List getAdditionalInputParameters(ProcessPluginA @Override public TaskSender getTaskSender(ProcessPluginApi api, Variables variables, SendTaskValues sendTaskValues) { - return new DefaultTaskSender(api, variables, sendTaskValues, getBusinessKeyStrategy()) + return new DefaultTaskSender(api, variables, sendTaskValues, getBusinessKeyStrategy(), + target -> getAdditionalInputParameters(api, variables, sendTaskValues, target)) { @Override protected IdType doSend(Task task, String targetEndpointUrl) From 2d4ce303897d139e42742f3940a03a3d2575e052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 7 Jul 2026 14:20:42 +0200 Subject: [PATCH 64/68] Status code never gets set as a global variable so does not need to be removed. Trying to set status code to null causes a NullPointerException --- src/main/java/dev/dsf/bpe/service/ping/SavePong.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java index 363c9037..9128a682 100644 --- a/src/main/java/dev/dsf/bpe/service/ping/SavePong.java +++ b/src/main/java/dev/dsf/bpe/service/ping/SavePong.java @@ -31,7 +31,6 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound Target target = variables.getTarget(); logger.debug("Pong received from {}. Saving pong information...", target.getEndpointUrl()); String correlationKey = target.getCorrelationKey(); - variables.setJsonVariable("statusCode", null); Task pong = variables.getLatestTask(); From c543fda85ec87c06b8e3e55ab832d003e7fd3b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 7 Jul 2026 16:44:15 +0200 Subject: [PATCH 65/68] Constructor can now deal with null values as Variables#getVariable may return null which previously resulted in parsing errors in jackson --- src/main/java/dev/dsf/bpe/ProcessErrors.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dsf/bpe/ProcessErrors.java b/src/main/java/dev/dsf/bpe/ProcessErrors.java index 5c2891d7..6bd0f6a4 100644 --- a/src/main/java/dev/dsf/bpe/ProcessErrors.java +++ b/src/main/java/dev/dsf/bpe/ProcessErrors.java @@ -1,8 +1,8 @@ package dev.dsf.bpe; -import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Vector; import com.fasterxml.jackson.annotation.JsonCreator; @@ -21,7 +21,14 @@ public ProcessErrors() @JsonCreator public ProcessErrors(@JsonProperty("entries") Collection entries) { - this.entries = new ArrayList<>(entries); + if (Objects.nonNull(entries)) + { + this.entries = new Vector<>(entries); + } + else + { + this.entries = new Vector<>(); + } } @JsonProperty("entries") From 106e159ee6002de8add05bec8401f2acbd6ec38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Tue, 7 Jul 2026 17:29:21 +0200 Subject: [PATCH 66/68] - dsf-bpe-process-api-v2-impl is not a published dependency - Copied relevant classes from source - Updated impsort config to remove unused imports and handle unnamed variables --- pom.xml | 11 +- .../ActivityDefinitionProfileTest.java | 10 +- src/test/java/dev/dsf/fhir/profiles/All.java | 224 ++++++++ .../dev/dsf/fhir/profiles/Organization.java | 340 ++++++++++++ .../ProcessAuthorizationHelperImpl.java | 520 ++++++++++++++++++ .../fhir/profiles/RequesterFactoryImpl.java | 99 ++++ src/test/java/dev/dsf/fhir/profiles/Role.java | 450 +++++++++++++++ 7 files changed, 1639 insertions(+), 15 deletions(-) create mode 100644 src/test/java/dev/dsf/fhir/profiles/All.java create mode 100644 src/test/java/dev/dsf/fhir/profiles/Organization.java create mode 100644 src/test/java/dev/dsf/fhir/profiles/ProcessAuthorizationHelperImpl.java create mode 100644 src/test/java/dev/dsf/fhir/profiles/RequesterFactoryImpl.java create mode 100644 src/test/java/dev/dsf/fhir/profiles/Role.java diff --git a/pom.xml b/pom.xml index 4025ab65..1d7254d8 100644 --- a/pom.xml +++ b/pom.xml @@ -62,12 +62,6 @@ ${dsf.version} test - - dev.dsf - dsf-bpe-process-api-v2-impl - ${dsf.version} - test - junit junit @@ -200,9 +194,10 @@ net.revelc.code impsort-maven-plugin - 1.12.0 + 1.13.0 - 17 + 24 + true java.,javax.,org.,com. java,* diff --git a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java index 52b80fff..5f010d8e 100644 --- a/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java +++ b/src/test/java/dev/dsf/fhir/profiles/ActivityDefinitionProfileTest.java @@ -16,7 +16,6 @@ import ca.uhn.fhir.validation.ValidationResult; import dev.dsf.bpe.PingProcessPluginDefinition; import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper; -import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelperImpl; import dev.dsf.fhir.validation.ResourceValidator; import dev.dsf.fhir.validation.ResourceValidatorImpl; import dev.dsf.fhir.validation.ValidationSupportRule; @@ -68,8 +67,7 @@ public void testAutostartValid() throws Exception assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, practitionerRole -> true, - orgIdentifier -> true, organizationRole -> true)); + assertTrue(processAuthorizationHelper.isValid(ad, _ -> true, _ -> true, _ -> true, _ -> true)); } @Test @@ -84,8 +82,7 @@ public void testPingValid() throws Exception assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, practitionerRole -> true, - orgIdentifier -> true, organizationRole -> true)); + assertTrue(processAuthorizationHelper.isValid(ad, _ -> true, _ -> true, _ -> true, _ -> true)); } @Test @@ -100,7 +97,6 @@ public void testPongValid() throws Exception assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, practitionerRole -> true, - orgIdentifier -> true, organizationRole -> true)); + assertTrue(processAuthorizationHelper.isValid(ad, _ -> true, _ -> true, _ -> true, _ -> true)); } } diff --git a/src/test/java/dev/dsf/fhir/profiles/All.java b/src/test/java/dev/dsf/fhir/profiles/All.java new file mode 100644 index 00000000..cc466142 --- /dev/null +++ b/src/test/java/dev/dsf/fhir/profiles/All.java @@ -0,0 +1,224 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.fhir.profiles; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.OrganizationAffiliation; + +import dev.dsf.bpe.v2.constants.CodeSystems.ProcessAuthorization; +import dev.dsf.bpe.v2.service.process.Identity; +import dev.dsf.bpe.v2.service.process.OrganizationIdentity; +import dev.dsf.bpe.v2.service.process.PractitionerIdentity; +import dev.dsf.bpe.v2.service.process.Recipient; +import dev.dsf.bpe.v2.service.process.Requester; + +public class All implements Recipient, Requester +{ + private static final String EXTENSION_PROCESS_AUTHORIZATION_REQUESTER = "requester"; + private static final String EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT = "recipient"; + + private static final String EXTENSION_PROCESS_AUTHORIZATION_PRACTITIONER = "http://dsf.dev/fhir/StructureDefinition/extension-process-authorization-practitioner"; + + private final boolean localIdentity; + + private final String practitionerRoleSystem; + private final String practitionerRoleCode; + + public All(boolean localIdentity, String practitionerRoleSystem, String practitionerRoleCode) + { + this.localIdentity = localIdentity; + + this.practitionerRoleSystem = practitionerRoleSystem; + this.practitionerRoleCode = practitionerRoleCode; + } + + private boolean needsPractitionerRole() + { + return practitionerRoleSystem != null && practitionerRoleCode != null; + } + + @Override + public boolean isRequesterAuthorized(Identity requester, Stream requesterAffiliations) + { + return isAuthorized(requester); + } + + @Override + public boolean isRecipientAuthorized(Identity recipient, Stream recipientAffiliations) + { + return isAuthorized(recipient); + } + + private boolean isAuthorized(Identity identity) + { + return identity != null && identity.getOrganization() != null && identity.getOrganization().getActive() + && identity.isLocalIdentity() == localIdentity + && ((needsPractitionerRole() && hasPractitionerRole(getPractitionerRoles(identity))) + || (!needsPractitionerRole() && identity instanceof OrganizationIdentity)); + } + + private Set getPractitionerRoles(Identity identity) + { + if (identity instanceof PractitionerIdentity p) + return p.getPractionerRoles(); + else + return Set.of(); + } + + private boolean hasPractitionerRole(Set practitionerRoles) + { + return practitionerRoles.stream().anyMatch( + c -> practitionerRoleSystem.equals(c.getSystem()) && practitionerRoleCode.equals(c.getCode())); + } + + @Override + public Extension toRecipientExtension() + { + return new Extension().setUrl(EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT).setValue(toCoding(false)); + } + + @Override + public Extension toRequesterExtension() + { + return new Extension().setUrl(EXTENSION_PROCESS_AUTHORIZATION_REQUESTER) + .setValue(toCoding(needsPractitionerRole())); + } + + private Coding toCoding(boolean needsPractitionerRole) + { + Coding coding = getProcessAuthorizationCode(); + + if (needsPractitionerRole) + coding.addExtension().setUrl(EXTENSION_PROCESS_AUTHORIZATION_PRACTITIONER) + .setValue(new Coding(practitionerRoleSystem, practitionerRoleCode, null)); + + return coding; + } + + @Override + public Coding getProcessAuthorizationCode() + { + if (localIdentity) + { + if (needsPractitionerRole()) + return ProcessAuthorization.localAllPractitioner(); + else + return ProcessAuthorization.localAll(); + } + else + return ProcessAuthorization.remoteAll(); + } + + @Override + public boolean requesterMatches(Extension requesterExtension) + { + return matches(requesterExtension, EXTENSION_PROCESS_AUTHORIZATION_REQUESTER) + && hasMatchingPractitionerExtension(requesterExtension.getValue().getExtension()); + } + + @Override + public boolean recipientMatches(Extension recipientExtension) + { + return matches(recipientExtension, EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT); + } + + private boolean matches(Extension extension, String url) + { + return extension != null && url.equals(extension.getUrl()) && extension.hasValue() + && extension.getValue() instanceof Coding value && matches(value); + } + + private boolean hasMatchingPractitionerExtension(List extensions) + { + return needsPractitionerRole() ? extensions.stream().anyMatch(this::practitionerExtensionMatches) + : extensions.stream().noneMatch(this::practitionerExtensionMatches); + } + + private boolean practitionerExtensionMatches(Extension extension) + { + return EXTENSION_PROCESS_AUTHORIZATION_PRACTITIONER.equals(extension.getUrl()) && extension.hasValue() + && extension.getValue() instanceof Coding value && practitionerRoleMatches(value); + } + + private boolean practitionerRoleMatches(Coding coding) + { + return coding != null && coding.hasSystem() && coding.hasCode() + && practitionerRoleSystem.equals(coding.getSystem()) && practitionerRoleCode.equals(coding.getCode()); + } + + @Override + public boolean matches(Coding processAuthorizationCode) + { + if (localIdentity) + if (needsPractitionerRole()) + return ProcessAuthorization.isLocalAllPractitioner(processAuthorizationCode); + else + return ProcessAuthorization.isLocalAll(processAuthorizationCode); + else + return ProcessAuthorization.isRemoteAll(processAuthorizationCode); + } + + public static Optional fromRequester(Coding coding, Predicate practitionerRoleExists) + { + if (ProcessAuthorization.isLocalAll(coding)) + return Optional.of(new All(true, null, null)); + else if (ProcessAuthorization.isRemoteAll(coding)) + return Optional.of(new All(false, null, null)); + else if (ProcessAuthorization.isLocalAllPractitioner(coding)) + return fromPractitionerRequester(coding, practitionerRoleExists); + else + return Optional.empty(); + } + + private static Optional fromPractitionerRequester(Coding coding, + Predicate practitionerRoleExists) + { + if (coding != null && coding.hasExtension()) + { + List practitionerRoles = coding.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_PRACTITIONER.equals(e.getUrl())) + .collect(Collectors.toList()); + if (practitionerRoles.size() == 1) + { + Extension practitionerRole = practitionerRoles.get(0); + if (practitionerRole.hasValue() && practitionerRole.getValue() instanceof Coding value + && value.hasSystem() && value.hasCode() && practitionerRoleExists.test(coding)) + { + return Optional.of(new All(true, value.getSystem(), value.getCode())); + } + } + } + + return Optional.empty(); + } + + public static Optional fromRecipient(Coding coding) + { + if (ProcessAuthorization.isLocalAll(coding)) + return Optional.of(new All(true, null, null)); + else + // remote not allowed for recipient + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/test/java/dev/dsf/fhir/profiles/Organization.java b/src/test/java/dev/dsf/fhir/profiles/Organization.java new file mode 100644 index 00000000..f6cac40b --- /dev/null +++ b/src/test/java/dev/dsf/fhir/profiles/Organization.java @@ -0,0 +1,340 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.fhir.profiles; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.OrganizationAffiliation; + +import dev.dsf.bpe.v2.constants.CodeSystems.ProcessAuthorization; +import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; +import dev.dsf.bpe.v2.service.process.Identity; +import dev.dsf.bpe.v2.service.process.OrganizationIdentity; +import dev.dsf.bpe.v2.service.process.PractitionerIdentity; +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper; +import dev.dsf.bpe.v2.service.process.Recipient; +import dev.dsf.bpe.v2.service.process.Requester; + +public class Organization implements Recipient, Requester +{ + private final String organizationIdentifier; + private final boolean localIdentity; + + private final String practitionerRoleSystem; + private final String practitionerRoleCode; + + public Organization(boolean localIdentity, String organizationIdentifier, String practitionerRoleSystem, + String practitionerRoleCode) + { + Objects.requireNonNull(organizationIdentifier, "organizationIdentifier"); + if (organizationIdentifier.isBlank()) + throw new IllegalArgumentException("organizationIdentifier blank"); + + this.localIdentity = localIdentity; + this.organizationIdentifier = organizationIdentifier; + + this.practitionerRoleSystem = practitionerRoleSystem; + this.practitionerRoleCode = practitionerRoleCode; + } + + private boolean needsPractitionerRole() + { + return practitionerRoleSystem != null && practitionerRoleCode != null; + } + + @Override + public boolean isRequesterAuthorized(Identity requester, Stream requesterAffiliations) + { + return isAuthorized(requester); + } + + @Override + public boolean isRecipientAuthorized(Identity recipient, Stream recipientAffiliations) + { + return isAuthorized(recipient); + } + + private boolean isAuthorized(Identity identity) + { + return identity != null && identity.getOrganization() != null && identity.getOrganization().getActive() + && identity.isLocalIdentity() == localIdentity && hasOrganizationIdentifier(identity.getOrganization()) + && ((needsPractitionerRole() && hasPractitionerRole(getPractitionerRoles(identity))) + || (!needsPractitionerRole() && identity instanceof OrganizationIdentity)); + } + + private boolean hasOrganizationIdentifier(org.hl7.fhir.r4.model.Organization organization) + { + return organization.getIdentifier().stream().filter(Identifier::hasSystem).filter(Identifier::hasValue) + .filter(i -> OrganizationIdentifier.SID.equals(i.getSystem())) + .anyMatch(i -> organizationIdentifier.equals(i.getValue())); + } + + private Set getPractitionerRoles(Identity identity) + { + if (identity instanceof PractitionerIdentity p) + return p.getPractionerRoles(); + else + return Set.of(); + } + + private boolean hasPractitionerRole(Set practitionerRoles) + { + return practitionerRoles.stream().anyMatch( + c -> practitionerRoleSystem.equals(c.getSystem()) && practitionerRoleCode.equals(c.getCode())); + } + + @Override + public Extension toRecipientExtension() + { + return new Extension().setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT) + .setValue(toCoding(false)); + } + + @Override + public Extension toRequesterExtension() + { + return new Extension().setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_REQUESTER) + .setValue(toCoding(needsPractitionerRole())); + } + + private Coding toCoding(boolean needsPractitionerRole) + { + Identifier organization = OrganizationIdentifier.withValue(organizationIdentifier); + Coding coding = getProcessAuthorizationCode(); + + if (needsPractitionerRole) + { + Extension extension = coding.addExtension() + .setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER); + extension.addExtension( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_ORGANIZATION, + organization); + extension.addExtension( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_PRACTITIONER_ROLE, + new Coding(practitionerRoleSystem, practitionerRoleCode, null)); + } + else + { + coding.addExtension().setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION) + .setValue(organization); + } + + return coding; + } + + @Override + public Coding getProcessAuthorizationCode() + { + if (localIdentity) + { + if (needsPractitionerRole()) + return ProcessAuthorization.localOrganizationPractitioner(); + else + return ProcessAuthorization.localOrganization(); + } + else + return ProcessAuthorization.remoteOrganization(); + } + + @Override + public boolean requesterMatches(Extension requesterExtension) + { + return matches(requesterExtension, ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_REQUESTER, + needsPractitionerRole()); + } + + @Override + public boolean recipientMatches(Extension recipientExtension) + { + return matches(recipientExtension, ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT, false); + } + + private boolean matches(Extension extension, String url, boolean needsPractitionerRole) + { + return extension != null && url.equals(extension.getUrl()) && extension.hasValue() + && extension.getValue() instanceof Coding value && matches(value) && value.hasExtension() + && hasMatchingOrganizationExtension(value.getExtension(), needsPractitionerRole); + } + + private boolean hasMatchingOrganizationExtension(List extensions, boolean needsPractitionerRole) + { + return extensions.stream().anyMatch(organizationExtensionMatches(needsPractitionerRole)); + } + + private Predicate organizationExtensionMatches(boolean needsPractitionerRole) + { + if (needsPractitionerRole) + { + return extension -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER + .equals(extension.getUrl()) && !extension.hasValue() + && hasMatchingSubOrganizationExtension(extension.getExtension()) + && hasMatchingPractitionerExtension(extension.getExtension()); + } + else + { + return extension -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION + .equals(extension.getUrl()) && extension.hasValue() + && extension.getValue() instanceof Identifier value && organizationIdentifierMatches(value); + } + } + + private boolean organizationIdentifierMatches(Identifier identifier) + { + return identifier != null && identifier.hasSystem() && identifier.hasValue() + && OrganizationIdentifier.SID.equals(identifier.getSystem()) + && organizationIdentifier.equals(identifier.getValue()); + } + + private boolean hasMatchingSubOrganizationExtension(List extensions) + { + return extensions.stream().anyMatch(this::subOrganizationExtensionMatches); + } + + private boolean subOrganizationExtensionMatches(Extension extension) + { + return ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_ORGANIZATION + .equals(extension.getUrl()) && extension.hasValue() && extension.getValue() instanceof Identifier value + && organizationIdentifierMatches(value); + } + + private boolean hasMatchingPractitionerExtension(List extensions) + { + return extensions.stream().anyMatch(this::practitionerExtensionMatches); + } + + private boolean practitionerExtensionMatches(Extension extension) + { + return ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_PRACTITIONER_ROLE + .equals(extension.getUrl()) && extension.hasValue() && extension.getValue() instanceof Coding value + && practitionerRoleMatches(value); + } + + private boolean practitionerRoleMatches(Coding coding) + { + return coding != null && coding.hasSystem() && coding.hasCode() + && practitionerRoleSystem.equals(coding.getSystem()) && practitionerRoleCode.equals(coding.getCode()); + } + + @Override + public boolean matches(Coding processAuthorizationCode) + { + if (localIdentity) + if (needsPractitionerRole()) + return ProcessAuthorization.isLocalOrganizationPractitioner(processAuthorizationCode); + else + return ProcessAuthorization.isLocalOrganization(processAuthorizationCode); + else + return ProcessAuthorization.isRemoteOrganization(processAuthorizationCode); + } + + public static Optional fromRequester(Coding coding, Predicate practitionerRoleExists, + Predicate organizationWithIdentifierExists) + { + if (ProcessAuthorization.isLocalOrganization(coding)) + return Optional.ofNullable(from(true, coding, organizationWithIdentifierExists)); + else if (ProcessAuthorization.isRemoteOrganization(coding)) + return Optional.ofNullable(from(false, coding, organizationWithIdentifierExists)); + else if (ProcessAuthorization.isLocalOrganizationPractitioner(coding)) + return fromPractitionerRequester(coding, practitionerRoleExists, organizationWithIdentifierExists); + else + return Optional.empty(); + } + + public static Optional fromRecipient(Coding coding, + Predicate organizationWithIdentifierExists) + { + if (ProcessAuthorization.isLocalOrganization(coding)) + return Optional.ofNullable(from(true, coding, organizationWithIdentifierExists)); + else + return Optional.empty(); + } + + private static Organization from(boolean localIdentity, Coding coding, + Predicate organizationWithIdentifierExists) + { + if (coding != null && coding.hasExtension()) + { + List organizations = coding.getExtension().stream().filter(Extension::hasUrl).filter( + e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION.equals(e.getUrl())) + .collect(Collectors.toList()); + if (organizations.size() == 1) + { + Extension organization = organizations.get(0); + if (organization.hasValue() && organization.getValue() instanceof Identifier identifier + && OrganizationIdentifier.SID.equals(identifier.getSystem()) + && organizationWithIdentifierExists.test(identifier)) + { + return new Organization(localIdentity, identifier.getValue(), null, null); + } + } + } + + return null; + } + + private static Optional fromPractitionerRequester(Coding coding, + Predicate practitionerRoleExists, Predicate organizationWithIdentifierExists) + { + if (coding != null && coding.hasExtension()) + { + List organizationPractitioners = coding.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER + .equals(e.getUrl())) + .collect(Collectors.toList()); + if (organizationPractitioners.size() == 1) + { + Extension organizationPractitioner = organizationPractitioners.get(0); + List organizations = organizationPractitioner.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_ORGANIZATION + .equals(e.getUrl())) + .collect(Collectors.toList()); + List practitionerRoles = organizationPractitioner.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_ORGANIZATION_PRACTITIONER_PRACTITIONER_ROLE + .equals(e.getUrl())) + .collect(Collectors.toList()); + if (organizations.size() == 1 && practitionerRoles.size() == 1) + { + Extension organization = organizations.get(0); + Extension practitionerRole = practitionerRoles.get(0); + + if (organization.hasValue() && organization.getValue() instanceof Identifier organizationIdentifier + && practitionerRole.hasValue() + && practitionerRole.getValue() instanceof Coding practitionerRoleCoding + && OrganizationIdentifier.SID.equals(organizationIdentifier.getSystem()) + && organizationWithIdentifierExists.test(organizationIdentifier) + && practitionerRoleExists.test(practitionerRoleCoding)) + { + return Optional.of(new Organization(true, organizationIdentifier.getValue(), + practitionerRoleCoding.getSystem(), practitionerRoleCoding.getCode())); + } + } + } + } + + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/test/java/dev/dsf/fhir/profiles/ProcessAuthorizationHelperImpl.java b/src/test/java/dev/dsf/fhir/profiles/ProcessAuthorizationHelperImpl.java new file mode 100644 index 00000000..56630eb6 --- /dev/null +++ b/src/test/java/dev/dsf/fhir/profiles/ProcessAuthorizationHelperImpl.java @@ -0,0 +1,520 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.fhir.profiles; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.CanonicalType; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.StringType; + +import dev.dsf.bpe.v2.constants.CodeSystems.ProcessAuthorization; +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper; +import dev.dsf.bpe.v2.service.process.Recipient; +import dev.dsf.bpe.v2.service.process.Requester; + +public class ProcessAuthorizationHelperImpl implements ProcessAuthorizationHelper +{ + private static final class RecipientFactoryImpl implements RecipientFactory + { + @Override + public Recipient localAll() + { + return new All(true, null, null); + } + + @Override + public Recipient localOrganization(String organizationIdentifier) + { + return new Organization(true, organizationIdentifier, null, null); + } + + @Override + public Recipient localRole(String parentOrganizationIdentifier, String roleSystem, String roleCode) + { + return new Role(true, parentOrganizationIdentifier, roleSystem, roleCode, null, null); + } + } + + private static final class RequesterFactoryImpl implements RequesterFactory + { + @Override + public Requester localAll() + { + return all(true, null, null); + } + + @Override + public Requester localAllPractitioner(String practitionerRoleSystem, String practitionerRoleCode) + { + return all(true, practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteAll() + { + return all(false, null, null); + } + + private Requester all(boolean localIdentity, String userRoleSystem, String userRoleCode) + { + return new All(localIdentity, userRoleSystem, userRoleCode); + } + + @Override + public Requester localOrganization(String organizationIdentifier) + { + return organization(true, organizationIdentifier, null, null); + } + + @Override + public Requester localOrganizationPractitioner(String organizationIdentifier, String practitionerRoleSystem, + String practitionerRoleCode) + { + return organization(true, organizationIdentifier, practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteOrganization(String organizationIdentifier) + { + return organization(false, organizationIdentifier, null, null); + } + + private Requester organization(boolean localIdentity, String organizationIdentifier, + String practitionerRoleSystem, String practitionerRoleCode) + { + return new Organization(localIdentity, organizationIdentifier, practitionerRoleSystem, + practitionerRoleCode); + } + + @Override + public Requester localRole(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode) + { + return role(true, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, null, null); + } + + @Override + public Requester localRolePractitioner(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode, String practitionerRoleSystem, String practitionerRoleCode) + { + return role(true, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, + practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteRole(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode) + { + return role(false, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, null, null); + } + + private Requester role(boolean localIdentity, String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode, String practitionerRoleSystem, String practitionerRoleCode) + { + return new Role(localIdentity, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, + practitionerRoleSystem, practitionerRoleCode); + } + } + + private static final RecipientFactory RECIPIENT_FACTORY = new RecipientFactoryImpl(); + private static final RequesterFactory REQUESTER_FACTORY = new RequesterFactoryImpl(); + + @Override + public RecipientFactory getRecipientFactory() + { + return RECIPIENT_FACTORY; + } + + @Override + public RequesterFactory getRequesterFactory() + { + return REQUESTER_FACTORY; + } + + @Override + public ActivityDefinition add(ActivityDefinition activityDefinition, String messageName, String taskProfile, + Requester requester, Recipient recipient) + { + Objects.requireNonNull(activityDefinition, "activityDefinition"); + Objects.requireNonNull(messageName, "messageName"); + if (messageName.isBlank()) + throw new IllegalArgumentException("messageName blank"); + Objects.requireNonNull(taskProfile, "taskProfile"); + if (taskProfile.isBlank()) + throw new IllegalArgumentException("taskProfile blank"); + Objects.requireNonNull(requester, "requester"); + Objects.requireNonNull(recipient, "recipient"); + + Extension extension = getExtensionByMessageNameAndTaskProfile(activityDefinition, messageName, taskProfile); + if (!hasAuthorization(extension, requester)) + extension.addExtension(requester.toRequesterExtension()); + if (!hasAuthorization(extension, recipient)) + extension.addExtension(recipient.toRecipientExtension()); + + return activityDefinition; + } + + @Override + public ActivityDefinition add(ActivityDefinition activityDefinition, String messageName, String taskProfile, + Collection requesters, Collection recipients) + { + Objects.requireNonNull(activityDefinition, "activityDefinition"); + Objects.requireNonNull(messageName, "messageName"); + if (messageName.isBlank()) + throw new IllegalArgumentException("messageName blank"); + Objects.requireNonNull(taskProfile, "taskProfile"); + if (taskProfile.isBlank()) + throw new IllegalArgumentException("taskProfile blank"); + Objects.requireNonNull(requesters, "requesters"); + if (requesters.isEmpty()) + throw new IllegalArgumentException("requesters empty"); + Objects.requireNonNull(recipients, "recipients"); + if (recipients.isEmpty()) + throw new IllegalArgumentException("recipients empty"); + + Extension extension = getExtensionByMessageNameAndTaskProfile(activityDefinition, messageName, taskProfile); + requesters.stream().filter(r -> !hasAuthorization(extension, r)) + .forEach(r -> extension.addExtension(r.toRequesterExtension())); + recipients.stream().filter(r -> !hasAuthorization(extension, r)) + .forEach(r -> extension.addExtension(r.toRecipientExtension())); + + return activityDefinition; + } + + private Extension getExtensionByMessageNameAndTaskProfile(ActivityDefinition a, String messageName, + String taskProfile) + { + return a.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION.equals(e.getUrl())).filter(Extension::hasExtension) + .filter(e -> hasMessageName(e, messageName) && hasTaskProfileExact(e, taskProfile)).findFirst() + .orElseGet(() -> + { + Extension e = newExtension(messageName, taskProfile); + a.addExtension(e); + return e; + }); + } + + private boolean hasMessageName(Extension processAuthorization, String messageName) + { + return processAuthorization.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME.equals(e.getUrl())) + .filter(Extension::hasValue).filter(e -> e.getValue() instanceof StringType) + .map(e -> (StringType) e.getValue()).anyMatch(s -> messageName.equals(s.getValueAsString())); + } + + private boolean hasTaskProfileExact(Extension processAuthorization, String taskProfile) + { + return processAuthorization.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE.equals(e.getUrl())) + .filter(Extension::hasValue).filter(e -> e.getValue() instanceof CanonicalType) + .map(e -> (CanonicalType) e.getValue()).anyMatch(c -> taskProfile.equals(c.getValueAsString())); + } + + private Extension newExtension(String messageName, String taskProfile) + { + Extension e = new Extension(EXTENSION_PROCESS_AUTHORIZATION); + e.addExtension(newMessageName(messageName)); + e.addExtension(newTaskProfile(taskProfile)); + + return e; + } + + private Extension newMessageName(String messageName) + { + return new Extension(EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME).setValue(new StringType(messageName)); + } + + private Extension newTaskProfile(String taskProfile) + { + return new Extension(EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE).setValue(new CanonicalType(taskProfile)); + } + + private boolean hasAuthorization(Extension processAuthorization, Requester authorization) + { + return processAuthorization.getExtension().stream().anyMatch(authorization::requesterMatches); + } + + private boolean hasAuthorization(Extension processAuthorization, Recipient authorization) + { + return processAuthorization.getExtension().stream().anyMatch(authorization::recipientMatches); + } + + @Override + public boolean isValid(ActivityDefinition activityDefinition, Predicate profileExists, + Predicate practitionerRoleExists, Predicate organizationWithIdentifierExists, + Predicate organizationRoleExists) + { + if (activityDefinition == null) + return false; + + List processAuthorizations = activityDefinition.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION.equals(e.getUrl())).collect(Collectors.toList()); + + if (processAuthorizations.isEmpty()) + return false; + + return processAuthorizations.stream() + .map(e -> isProcessAuthorizationValid(e, profileExists, practitionerRoleExists, + organizationWithIdentifierExists, organizationRoleExists)) + .allMatch(v -> v) && messageNamesUnique(processAuthorizations); + } + + private boolean messageNamesUnique(List processAuthorizations) + { + return processAuthorizations.size() == processAuthorizations.stream().flatMap(e -> e.getExtension().stream() + .filter(mn -> EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME.equals(mn.getUrl())).map(Extension::getValue) + .map(v -> (StringType) v).map(StringType::getValueAsString).findFirst().stream()).distinct().count(); + } + + private boolean isProcessAuthorizationValid(Extension processAuthorization, Predicate profileExists, + Predicate practitionerRoleExists, Predicate organizationWithIdentifierExists, + Predicate organizationRoleExists) + { + if (processAuthorization == null || !EXTENSION_PROCESS_AUTHORIZATION.equals(processAuthorization.getUrl()) + || !processAuthorization.hasExtension()) + return false; + + List messageNames = new ArrayList<>(), taskProfiles = new ArrayList<>(), + requesters = new ArrayList<>(), recipients = new ArrayList<>(); + for (Extension extension : processAuthorization.getExtension()) + { + if (extension.hasUrl()) + { + switch (extension.getUrl()) + { + case EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME: + messageNames.add(extension); + break; + case EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE: + taskProfiles.add(extension); + break; + case EXTENSION_PROCESS_AUTHORIZATION_REQUESTER: + requesters.add(extension); + break; + case EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT: + recipients.add(extension); + break; + } + } + } + + if (messageNames.size() != 1 || taskProfiles.size() != 1 || requesters.isEmpty() || recipients.isEmpty()) + return false; + + return isMessageNameValid(messageNames.get(0)) && isTaskProfileValid(taskProfiles.get(0), profileExists) + && isRequestersValid(requesters, practitionerRoleExists, organizationWithIdentifierExists, + organizationRoleExists) + && isRecipientsValid(recipients, organizationWithIdentifierExists, organizationRoleExists); + } + + private boolean isMessageNameValid(Extension messageName) + { + if (messageName == null || !EXTENSION_PROCESS_AUTHORIZATION_MESSAGE_NAME.equals(messageName.getUrl())) + return false; + + return messageName.hasValue() && messageName.getValue() instanceof StringType value + && !value.getValueAsString().isBlank(); + } + + private boolean isTaskProfileValid(Extension taskProfile, Predicate profileExists) + { + if (taskProfile == null || !EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE.equals(taskProfile.getUrl())) + return false; + + return taskProfile.hasValue() && taskProfile.getValue() instanceof CanonicalType value + && profileExists.test(value); + } + + private boolean isRequestersValid(List requesters, Predicate practitionerRoleExists, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + return requesters.stream().allMatch(r -> isRequesterValid(r, practitionerRoleExists, + organizationWithIdentifierExists, organizationRoleExists)); + } + + private boolean isRequesterValid(Extension requester, Predicate practitionerRoleExists, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + if (requester == null || !EXTENSION_PROCESS_AUTHORIZATION_REQUESTER.equals(requester.getUrl())) + return false; + + if (requester.hasValue() && requester.getValue() instanceof Coding value) + { + return requesterFrom(value, practitionerRoleExists, organizationWithIdentifierExists, + organizationRoleExists).isPresent(); + } + + return false; + } + + private Optional requesterFrom(Coding coding, Predicate practitionerRoleExists, + Predicate organizationWithIdentifierExists, Predicate organizatioRoleExists) + { + switch (coding.getCode()) + { + case ProcessAuthorization.Codes.LOCAL_ALL: + case ProcessAuthorization.Codes.LOCAL_ALL_PRACTITIONER: + case ProcessAuthorization.Codes.REMOTE_ALL: + return All.fromRequester(coding, practitionerRoleExists); + + case ProcessAuthorization.Codes.LOCAL_ORGANIZATION: + case ProcessAuthorization.Codes.LOCAL_ORGANIZATION_PRACTITIONER: + case ProcessAuthorization.Codes.REMOTE_ORGANIZATION: + return Organization.fromRequester(coding, practitionerRoleExists, organizationWithIdentifierExists); + + case ProcessAuthorization.Codes.LOCAL_ROLE: + case ProcessAuthorization.Codes.LOCAL_ROLE_PRACTITIONER: + case ProcessAuthorization.Codes.REMOTE_ROLE: + return Role.fromRequester(coding, practitionerRoleExists, organizationWithIdentifierExists, + organizatioRoleExists); + } + + return Optional.empty(); + } + + private boolean isRecipientsValid(List recipients, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + return recipients.stream() + .allMatch(r -> isRecipientValid(r, organizationWithIdentifierExists, organizationRoleExists)); + } + + private boolean isRecipientValid(Extension recipient, Predicate organizationWithIdentifierExists, + Predicate organizationRoleExists) + { + if (recipient == null || !EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT.equals(recipient.getUrl())) + return false; + + if (recipient.hasValue() && recipient.getValue() instanceof Coding value) + { + return recipientFrom(value, organizationWithIdentifierExists, organizationRoleExists).isPresent(); + } + + return false; + } + + private Optional recipientFrom(Coding coding, Predicate organizationWithIdentifierExists, + Predicate organizationRoleExists) + { + return switch (coding.getCode()) + { + case ProcessAuthorization.Codes.LOCAL_ALL -> All.fromRecipient(coding); + + case ProcessAuthorization.Codes.LOCAL_ORGANIZATION -> Organization.fromRecipient(coding, + organizationWithIdentifierExists); + + case ProcessAuthorization.Codes.LOCAL_ROLE -> Role.fromRecipient(coding, organizationWithIdentifierExists, + organizationRoleExists); + + default -> Optional.empty(); + }; + } + + @Override + public Stream getRequesters(ActivityDefinition activityDefinition, String processUrl, + String processVersion, String messageName, Collection taskProfiles) + { + Optional authorizationExtension = getAuthorizationExtension(activityDefinition, processUrl, + processVersion, messageName, taskProfiles); + + if (authorizationExtension.isEmpty()) + return Stream.empty(); + else + return authorizationExtension.get().getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_REQUESTER.equals(e.getUrl())) + .filter(Extension::hasValue).filter(e -> e.getValue() instanceof Coding) + .map(e -> (Coding) e.getValue()) + .flatMap(coding -> requesterFrom(coding, _ -> true, _ -> true, _ -> true).stream()); + } + + @Override + public Stream getRecipients(ActivityDefinition activityDefinition, String processUrl, + String processVersion, String messageName, Collection taskProfiles) + { + Optional authorizationExtension = getAuthorizationExtension(activityDefinition, processUrl, + processVersion, messageName, taskProfiles); + + if (authorizationExtension.isEmpty()) + return Stream.empty(); + else + return authorizationExtension.get().getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT.equals(e.getUrl())) + .filter(Extension::hasValue).filter(e -> e.getValue() instanceof Coding) + .map(e -> (Coding) e.getValue()) + .flatMap(coding -> recipientFrom(coding, _ -> true, _ -> true).stream()); + } + + private Optional getAuthorizationExtension(ActivityDefinition activityDefinition, String processUrl, + String processVersion, String messageName, Collection taskProfiles) + { + if (activityDefinition == null || processUrl == null || processUrl.isBlank() || processVersion == null + || processVersion.isBlank() || messageName == null || messageName.isBlank() || taskProfiles == null) + return Optional.empty(); + + if (!processUrl.equals(activityDefinition.getUrl()) || !processVersion.equals(activityDefinition.getVersion())) + return Optional.empty(); + + Optional authorizationExtension = activityDefinition.getExtension().stream() + .filter(Extension::hasUrl).filter(e -> EXTENSION_PROCESS_AUTHORIZATION.equals(e.getUrl())) + .filter(Extension::hasExtension) + .filter(e -> hasMessageName(e, messageName) && hasTaskProfile(e, taskProfiles)).findFirst(); + return authorizationExtension; + } + + private boolean hasTaskProfile(Extension processAuthorization, Collection taskProfiles) + { + return taskProfiles.stream() + .anyMatch(taskProfile -> hasTaskProfileNotVersionSpecific(processAuthorization, taskProfile)); + } + + private boolean hasTaskProfileNotVersionSpecific(Extension processAuthorization, String taskProfile) + { + return processAuthorization.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> EXTENSION_PROCESS_AUTHORIZATION_TASK_PROFILE.equals(e.getUrl())) + .filter(Extension::hasValue).filter(e -> e.getValue() instanceof CanonicalType) + .map(e -> (CanonicalType) e.getValue()) + + // match if task profile is equal to value in activity definition + // or match if task profile is not version specific but value in activity definition is and non version + // specific profiles are same -> client does not care about version of task resource, may result in + // validation errors + .anyMatch(c -> taskProfile.equals(c.getValueAsString()) + || taskProfile.equals(getBase(c.getValueAsString()))); + } + + private static String getBase(String canonicalUrl) + { + if (canonicalUrl.contains("|")) + { + String[] split = canonicalUrl.split("\\|"); + return split[0]; + } + else + return canonicalUrl; + } +} diff --git a/src/test/java/dev/dsf/fhir/profiles/RequesterFactoryImpl.java b/src/test/java/dev/dsf/fhir/profiles/RequesterFactoryImpl.java new file mode 100644 index 00000000..72889314 --- /dev/null +++ b/src/test/java/dev/dsf/fhir/profiles/RequesterFactoryImpl.java @@ -0,0 +1,99 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.fhir.profiles; + +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper.RequesterFactory; +import dev.dsf.bpe.v2.service.process.Requester; + +public class RequesterFactoryImpl implements RequesterFactory +{ + @Override + public Requester localAll() + { + return all(true, null, null); + } + + @Override + public Requester localAllPractitioner(String practitionerRoleSystem, String practitionerRoleCode) + { + return all(true, practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteAll() + { + return all(false, null, null); + } + + private Requester all(boolean localIdentity, String userRoleSystem, String userRoleCode) + { + return new All(localIdentity, userRoleSystem, userRoleCode); + } + + @Override + public Requester localOrganization(String organizationIdentifier) + { + return organization(true, organizationIdentifier, null, null); + } + + @Override + public Requester localOrganizationPractitioner(String organizationIdentifier, String practitionerRoleSystem, + String practitionerRoleCode) + { + return organization(true, organizationIdentifier, practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteOrganization(String organizationIdentifier) + { + return organization(false, organizationIdentifier, null, null); + } + + private Requester organization(boolean localIdentity, String organizationIdentifier, String practitionerRoleSystem, + String practitionerRoleCode) + { + return new Organization(localIdentity, organizationIdentifier, practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester localRole(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode) + { + return role(true, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, null, null); + } + + @Override + public Requester localRolePractitioner(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode, String practitionerRoleSystem, String practitionerRoleCode) + { + return role(true, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, + practitionerRoleSystem, practitionerRoleCode); + } + + @Override + public Requester remoteRole(String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode) + { + return role(false, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, null, null); + } + + private Requester role(boolean localIdentity, String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizatioRoleCode, String practitionerRoleSystem, String practitionerRoleCode) + { + return new Role(localIdentity, parentOrganizationIdentifier, organizatioRoleSystem, organizatioRoleCode, + practitionerRoleSystem, practitionerRoleCode); + } +} diff --git a/src/test/java/dev/dsf/fhir/profiles/Role.java b/src/test/java/dev/dsf/fhir/profiles/Role.java new file mode 100644 index 00000000..ef5c44c3 --- /dev/null +++ b/src/test/java/dev/dsf/fhir/profiles/Role.java @@ -0,0 +1,450 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.fhir.profiles; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.OrganizationAffiliation; + +import dev.dsf.bpe.v2.constants.CodeSystems.ProcessAuthorization; +import dev.dsf.bpe.v2.constants.NamingSystems.OrganizationIdentifier; +import dev.dsf.bpe.v2.service.process.Identity; +import dev.dsf.bpe.v2.service.process.OrganizationIdentity; +import dev.dsf.bpe.v2.service.process.PractitionerIdentity; +import dev.dsf.bpe.v2.service.process.ProcessAuthorizationHelper; +import dev.dsf.bpe.v2.service.process.Recipient; +import dev.dsf.bpe.v2.service.process.Requester; + +public class Role implements Recipient, Requester +{ + private final boolean localIdentity; + private final String parentOrganizationIdentifier; + private final String organizationRoleSystem; + private final String organizationRoleCode; + + private final String practitionerRoleSystem; + private final String practitionerRoleCode; + + public Role(boolean localIdentity, String parentOrganizationIdentifier, String organizatioRoleSystem, + String organizationRoleCode, String practitionerRoleSystem, String practitionerRoleCode) + { + Objects.requireNonNull(parentOrganizationIdentifier, "parentOrganizationIdentifier"); + if (parentOrganizationIdentifier.isBlank()) + throw new IllegalArgumentException("parentOrganizationIdentifier blank"); + Objects.requireNonNull(organizatioRoleSystem, "organizatioRoleSystem"); + if (organizatioRoleSystem.isBlank()) + throw new IllegalArgumentException("organizatioRoleSystem blank"); + Objects.requireNonNull(organizationRoleCode, "organizationRoleCode"); + if (organizationRoleCode.isBlank()) + throw new IllegalArgumentException("organizationRoleCode blank"); + + this.localIdentity = localIdentity; + this.parentOrganizationIdentifier = parentOrganizationIdentifier; + this.organizationRoleSystem = organizatioRoleSystem; + this.organizationRoleCode = organizationRoleCode; + + this.practitionerRoleSystem = practitionerRoleSystem; + this.practitionerRoleCode = practitionerRoleCode; + } + + private boolean needsPractitionerRole() + { + return practitionerRoleSystem != null && practitionerRoleCode != null; + } + + @Override + public boolean isRequesterAuthorized(Identity requester, Stream requesterAffiliations) + { + return isAuthorized(requester, requesterAffiliations); + } + + @Override + public boolean isRecipientAuthorized(Identity recipient, Stream recipientAffiliations) + { + return isAuthorized(recipient, recipientAffiliations); + } + + private boolean isAuthorized(Identity identity, Stream affiliations) + { + return identity != null && identity.getOrganization() != null && identity.getOrganization().getActive() + && identity.isLocalIdentity() == localIdentity && affiliations != null + && hasParentOrganizationMemberRole(identity.getOrganization(), affiliations) + && ((needsPractitionerRole() && hasPractitionerRole(getPractitionerRoles(identity))) + || (!needsPractitionerRole() && identity instanceof OrganizationIdentity)); + } + + private boolean hasParentOrganizationMemberRole(org.hl7.fhir.r4.model.Organization recipientOrganization, + Stream affiliations) + { + return affiliations + + // check affiliation active + .filter(OrganizationAffiliation::getActive) + + // check parent-organization identifier + .filter(OrganizationAffiliation::hasOrganization).filter(a -> a.getOrganization().hasIdentifier()) + .filter(a -> a.getOrganization().getIdentifier().hasSystem()) + .filter(a -> a.getOrganization().getIdentifier().hasValue()) + .filter(a -> OrganizationIdentifier.SID.equals(a.getOrganization().getIdentifier().getSystem())) + .filter(a -> parentOrganizationIdentifier.equals(a.getOrganization().getIdentifier().getValue())) + + // check member identifier + .filter(OrganizationAffiliation::hasParticipatingOrganization) + .filter(a -> a.getParticipatingOrganization().hasIdentifier()) + .filter(a -> a.getParticipatingOrganization().getIdentifier().hasSystem()) + .filter(a -> a.getParticipatingOrganization().getIdentifier().hasValue()).filter(a -> + { + final Identifier memberIdentifier = a.getParticipatingOrganization().getIdentifier(); + return recipientOrganization.getIdentifier().stream().filter(Identifier::hasSystem) + .filter(Identifier::hasValue) + .anyMatch(i -> i.getSystem().equals(memberIdentifier.getSystem()) + && i.getValue().equals(memberIdentifier.getValue())); + }) + + // check role + .filter(OrganizationAffiliation::hasCode).flatMap(a -> a.getCode().stream()) + .filter(CodeableConcept::hasCoding).flatMap(c -> c.getCoding().stream()).filter(Coding::hasSystem) + .filter(Coding::hasCode).anyMatch( + c -> c.getSystem().equals(organizationRoleSystem) && c.getCode().equals(organizationRoleCode)); + } + + private Set getPractitionerRoles(Identity identity) + { + if (identity instanceof PractitionerIdentity p) + return p.getPractionerRoles(); + else + return Set.of(); + } + + private boolean hasPractitionerRole(Set practitionerRoles) + { + return practitionerRoles.stream().anyMatch( + c -> practitionerRoleSystem.equals(c.getSystem()) && practitionerRoleCode.equals(c.getCode())); + } + + @Override + public Extension toRecipientExtension() + { + return new Extension().setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT) + .setValue(toCoding(false)); + } + + @Override + public Extension toRequesterExtension() + { + return new Extension().setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_REQUESTER) + .setValue(toCoding(needsPractitionerRole())); + } + + private Coding toCoding(boolean needsPractitionerRole) + { + Identifier parentOrganization = OrganizationIdentifier.withValue(parentOrganizationIdentifier); + Extension parentOrganizationExt = new Extension( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PARENT_ORGANIZATION, + parentOrganization); + + Coding organizationRole = new Coding(organizationRoleSystem, organizationRoleCode, null); + Extension organizationRoleExt = new Extension( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_ORGANIZATION_ROLE, + organizationRole); + + Coding coding = getProcessAuthorizationCode(); + + if (needsPractitionerRole) + { + Extension practitionerRoleExt = new Extension( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER_PRACTITIONER_ROLE, + new Coding(practitionerRoleSystem, practitionerRoleCode, null)); + + coding.addExtension().setUrl( + ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER) + .addExtension(parentOrganizationExt).addExtension(organizationRoleExt) + .addExtension(practitionerRoleExt); + } + else + { + coding.addExtension() + .setUrl(ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE) + .addExtension(parentOrganizationExt).addExtension(organizationRoleExt); + } + + return coding; + } + + @Override + public Coding getProcessAuthorizationCode() + { + if (localIdentity) + { + if (needsPractitionerRole()) + return ProcessAuthorization.localRolePractitioner(); + else + return ProcessAuthorization.localRole(); + } + else + return ProcessAuthorization.remoteRole(); + } + + @Override + public boolean requesterMatches(Extension requesterExtension) + { + return matches(requesterExtension, ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_REQUESTER, + needsPractitionerRole()); + } + + @Override + public boolean recipientMatches(Extension recipientExtension) + { + return matches(recipientExtension, ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_RECIPIENT, false); + } + + private boolean matches(Extension extension, String url, boolean needsPractitionerRole) + { + return extension != null && url.equals(extension.getUrl()) && extension.hasValue() + && extension.getValue() instanceof Coding value && matches(value) && value.hasExtension() + && hasMatchingParentOrganizationRoleExtension(value.getExtension(), needsPractitionerRole); + } + + private boolean hasMatchingParentOrganizationRoleExtension(List extension, boolean needsPractitionerRole) + { + return extension.stream().anyMatch(parentOrganizationRoleExtensionMatches(needsPractitionerRole)); + } + + private Predicate parentOrganizationRoleExtensionMatches(boolean needsPractitionerRole) + { + if (needsPractitionerRole) + { + return extension -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER + .equals(extension.getUrl()) && extension.hasExtension() + && hasMatchingParentOrganizationExtension(extension.getExtension()) + && hasMatchingOrganizationRoleExtension(extension.getExtension()) + && hasMatchingPractitionerRoleExtension(extension.getExtension()); + } + else + { + return extension -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE + .equals(extension.getUrl()) && extension.hasExtension() + && hasMatchingParentOrganizationExtension(extension.getExtension()) + && hasMatchingOrganizationRoleExtension(extension.getExtension()); + } + } + + private boolean hasMatchingParentOrganizationExtension(List extensions) + { + return extensions.stream().anyMatch(this::parentOrganizationExtensionMatches); + } + + private boolean parentOrganizationExtensionMatches(Extension extension) + { + return ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PARENT_ORGANIZATION + .equals(extension.getUrl()) && extension.hasValue() && extension.getValue() instanceof Identifier value + && parentOrganizationIdentifierMatches(value); + } + + private boolean parentOrganizationIdentifierMatches(Identifier identifier) + { + return identifier != null && identifier.hasSystem() && identifier.hasValue() + && OrganizationIdentifier.SID.equals(identifier.getSystem()) + && parentOrganizationIdentifier.equals(identifier.getValue()); + } + + private boolean hasMatchingOrganizationRoleExtension(List extensions) + { + return extensions.stream().anyMatch(this::organizationRoleExtensionMatches); + } + + private boolean organizationRoleExtensionMatches(Extension extension) + { + return ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_ORGANIZATION_ROLE + .equals(extension.getUrl()) && extension.hasValue() && extension.getValue() instanceof Coding value + && organizationRoleMatches(value); + } + + private boolean organizationRoleMatches(Coding coding) + { + return coding != null && coding.hasSystem() && coding.hasCode() + && organizationRoleSystem.equals(coding.getSystem()) && organizationRoleCode.equals(coding.getCode()); + } + + private boolean hasMatchingPractitionerRoleExtension(List extensions) + { + return extensions.stream().anyMatch(this::practitionerRoleExtensionMatches); + } + + private boolean practitionerRoleExtensionMatches(Extension extension) + { + return ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER_PRACTITIONER_ROLE + .equals(extension.getUrl()) && extension.hasValue() && extension.getValue() instanceof Coding value + && practitionerRoleMatches(value); + } + + private boolean practitionerRoleMatches(Coding coding) + { + return coding != null && coding.hasSystem() && coding.hasCode() + && practitionerRoleSystem.equals(coding.getSystem()) && practitionerRoleCode.equals(coding.getCode()); + } + + @Override + public boolean matches(Coding processAuthorizationCode) + { + if (localIdentity) + if (needsPractitionerRole()) + return ProcessAuthorization.isLocalRolePractitioner(processAuthorizationCode); + else + return ProcessAuthorization.isLocalRole(processAuthorizationCode); + else + return ProcessAuthorization.isRemoteRole(processAuthorizationCode); + } + + public static Optional fromRequester(Coding coding, Predicate practitionerRoleExists, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + if (ProcessAuthorization.isLocalRole(coding)) + return Optional.ofNullable(from(true, coding, organizationWithIdentifierExists, organizationRoleExists)); + else if (ProcessAuthorization.isRemoteRole(coding)) + return Optional.ofNullable(from(false, coding, organizationWithIdentifierExists, organizationRoleExists)); + else if (ProcessAuthorization.isLocalRolePractitioner(coding)) + return fromPractitionerRequester(coding, practitionerRoleExists, organizationWithIdentifierExists, + organizationRoleExists); + else + return Optional.empty(); + } + + public static Optional fromRecipient(Coding coding, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + if (ProcessAuthorization.isLocalRole(coding)) + return Optional.ofNullable(from(true, coding, organizationWithIdentifierExists, organizationRoleExists)); + else + return Optional.empty(); + } + + private static Role from(boolean localIdentity, Coding coding, + Predicate organizationWithIdentifierExists, Predicate organizationRoleExists) + { + if (coding != null && coding.hasExtension()) + { + List parentOrganizationRoles = coding.getExtension().stream().filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE + .equals(e.getUrl())) + .collect(Collectors.toList()); + + if (parentOrganizationRoles.size() == 1) + { + Extension parentOrganizationRole = parentOrganizationRoles.get(0); + List parentOrganizations = parentOrganizationRole.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PARENT_ORGANIZATION + .equals(e.getUrl())) + .collect(Collectors.toList()); + List organizationRoles = parentOrganizationRole.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_ORGANIZATION_ROLE + .equals(e.getUrl())) + .collect(Collectors.toList()); + + if (parentOrganizations.size() == 1 && organizationRoles.size() == 1) + { + Extension parentOrganization = parentOrganizations.get(0); + Extension organizationRole = organizationRoles.get(0); + + if (parentOrganization.hasValue() + && parentOrganization.getValue() instanceof Identifier parentOrganizationIdentifier + && organizationRole.hasValue() + && organizationRole.getValue() instanceof Coding organizationRoleCoding + && OrganizationIdentifier.SID.equals(parentOrganizationIdentifier.getSystem()) + && organizationWithIdentifierExists.test(parentOrganizationIdentifier) + && organizationRoleExists.test(organizationRoleCoding)) + { + return new Role(localIdentity, parentOrganizationIdentifier.getValue(), + organizationRoleCoding.getSystem(), organizationRoleCoding.getCode(), null, null); + } + } + } + } + + return null; + } + + private static Optional fromPractitionerRequester(Coding coding, + Predicate practitionerRoleExists, Predicate organizationWithIdentifierExists, + Predicate organizationRoleExists) + { + if (coding != null && coding.hasExtension()) + { + List parentOrganizationRolePractitioners = coding.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER + .equals(e.getUrl())) + .collect(Collectors.toList()); + + if (parentOrganizationRolePractitioners.size() == 1) + { + Extension parentOrganizationRolePractitioner = parentOrganizationRolePractitioners.get(0); + List parentOrganizations = parentOrganizationRolePractitioner.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PARENT_ORGANIZATION + .equals(e.getUrl())) + .collect(Collectors.toList()); + List organizationRoles = parentOrganizationRolePractitioner.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_ORGANIZATION_ROLE + .equals(e.getUrl())) + .collect(Collectors.toList()); + List practitionerRoles = parentOrganizationRolePractitioner.getExtension().stream() + .filter(Extension::hasUrl) + .filter(e -> ProcessAuthorizationHelper.EXTENSION_PROCESS_AUTHORIZATION_PARENT_ORGANIZATION_ROLE_PRACTITIONER_PRACTITIONER_ROLE + .equals(e.getUrl())) + .collect(Collectors.toList()); + + if (parentOrganizations.size() == 1 && organizationRoles.size() == 1 && practitionerRoles.size() == 1) + { + Extension parentOrganization = parentOrganizations.get(0); + Extension organizationRole = organizationRoles.get(0); + Extension practitionerRole = practitionerRoles.get(0); + + if (parentOrganization.hasValue() + && parentOrganization.getValue() instanceof Identifier parentOrganizationIdentifier + && organizationRole.hasValue() + && organizationRole.getValue() instanceof Coding organizationRoleCoding + && practitionerRole.hasValue() + && practitionerRole.getValue() instanceof Coding practitionerRoleCoding + && OrganizationIdentifier.SID.equals(parentOrganizationIdentifier.getSystem()) + && organizationWithIdentifierExists.test(parentOrganizationIdentifier) + && organizationRoleExists.test(organizationRoleCoding) + && practitionerRoleExists.test(practitionerRoleCoding)) + { + return Optional.of(new Role(true, parentOrganizationIdentifier.getValue(), + organizationRoleCoding.getSystem(), organizationRoleCoding.getCode(), + practitionerRoleCoding.getSystem(), practitionerRoleCoding.getCode())); + } + } + } + } + + return Optional.empty(); + } +} \ No newline at end of file From d9a45f2af59607b28511f71e91af16fa4a321857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 8 Jul 2026 11:14:32 +0200 Subject: [PATCH 67/68] Closes #48. - Copied description from GitHub wiki page and added Markdown files in the doc directory to maven resource filtering to always generate a description with the current version (I will forget otherwise) - Added copy-and-rename-maven-plugin to always have the current configuration generated by the DSF maven plugin in the jar file (I will forget otherwise) --- pom.xml | 26 ++++ src/main/resources/doc/description.md | 42 ++++++ src/main/resources/doc/license.md | 202 ++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 src/main/resources/doc/description.md create mode 100644 src/main/resources/doc/license.md diff --git a/pom.xml b/pom.xml index 1d7254d8..8c1e18d0 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,14 @@ plugin.properties + + src/main/resources/doc + true + + *.md + + doc + @@ -102,6 +110,24 @@ maven-surefire-plugin 3.5.4 + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0.1 + + + copy-plugin-documentation + prepare-package + + rename + + + target/ConfigDoc_dev.dsf.bpe.spring.config.md + target/classes/doc/configuration.md + + + + org.apache.maven.plugins maven-jar-plugin diff --git a/src/main/resources/doc/description.md b/src/main/resources/doc/description.md new file mode 100644 index 00000000..8e814588 --- /dev/null +++ b/src/main/resources/doc/description.md @@ -0,0 +1,42 @@ +# Ping Pong Process ${project.version} Description + +The Ping Pong process allows testing connections to other (remote) DSF FHIR Endpoints. The following connections are tested: +- local DSF FHIR Server -> local BPE +- local BPE -> remote DSF FHIR Server +- remote DSF FHIR Server -> local DSF FHIR Server +- remote DSF FHIR Server -> remote BPE +- remote BPE -> local DSF FHIR Server +- local DSF FHIR Server -> remote DSF FHIR Server + +The Ping Pong process's output paremters will link to a page which contains troubleshooting tips if any connection fails for known reasons. In order to test connections between DSF FHIR Servers, the process creates a Binary resource containing random data. Sending a reference to this resource to another DSF FHIR Server causes the server to verify the existence of the referenced resource on the requesting DSF FHIR Server, thus testing the connection. This allows the process to also be used to measure connection speeds as the Binary resource gets downloaded during execution and deleted before the process finishes. This means the process also tests the ability to transfer data, which can be helpful to make sure the DSF installation is properly set up in preparation for other process plugins involving data transfers. + +Troubleshooting tips and network speeds can be found in the outputs of the completed process. They are named `potential-fix`, `download-speed-from-remote` and `upload-speed-to-remote` respectively. + + + + + Ping Pong Process Collaboration Diagram + + + +### Autostart Process +The ping pong process plugin includes an autostart process which allows automatically starting the ping process on an interval. + +# Ping-Pong: Ping +The **ping** process is used to ping other DSF FHIR Endpoints. It contains the following steps: +1. If requested, generate a Binary resource and store it on the local DSF FHIR Server +2. Send a ping message to all requested endpoints, containing a reference to the generated Binary resource +3. Wait for responses via pong messages +4. Download the Binary resource referenced in the pong message and measure network speed +5. Send a cleanup message to all endpoints +6. Delete the Binary resource generated in 1. +7. Store results and errors in the start task as output parameters + +# Ping-Pong: Pong +The **pong** process is used to respond to incoming ping requests. It contains the following steps: +1. Download the Binary resource referenced in the ping message and measure network speed +2. If requested, generate a Binary resource and store it on the local DSF FHIR Server +3. Send a pong message to the requesting endpoint, containing a reference to the generated Binary resource, network speed and all errors that occured during execution so far +4. Wait for cleanup message +5. Delete the Binary resource generated in 2. +6. Store results and errors in the ping task as output parameters \ No newline at end of file diff --git a/src/main/resources/doc/license.md b/src/main/resources/doc/license.md new file mode 100644 index 00000000..dc8b2392 --- /dev/null +++ b/src/main/resources/doc/license.md @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. From 4d0585662823d97802243e62122c616d0b34d4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hringer?= Date: Wed, 8 Jul 2026 11:28:20 +0200 Subject: [PATCH 68/68] API v2 changes: - Update to Java 25 --- .github/workflows/maven-build.yml | 4 ++-- .github/workflows/maven-publish.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 881ed900..ff6e78a4 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@v1 with: - java-version: 17 + java-version: 25 - name: Build with Maven env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 91d39400..96718608 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -21,10 +21,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@v1 with: - java-version: 17 + java-version: 25 - name: Publish with Maven env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}