diff --git a/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java b/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java index 62e702f..3d367bc 100644 --- a/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java +++ b/src/main/java/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGenerator.java @@ -22,21 +22,6 @@ package dev.dnpm.etl.processor.pseudonym; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; import dev.dnpm.etl.processor.config.GPasConfigProperties; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.ConnectException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Base64; -import java.util.HashMap; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import org.apache.commons.lang3.StringUtils; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; @@ -54,35 +39,39 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryListener; -import org.springframework.retry.RetryPolicy; -import org.springframework.retry.backoff.ExponentialBackOffPolicy; -import org.springframework.retry.policy.SimpleRetryPolicy; import org.springframework.retry.support.RetryTemplate; -import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Base64; + public class GpasPseudonymGenerator implements Generator { private final static FhirContext r4Context = FhirContext.forR4(); private final String gPasUrl; private final String psnTargetDomain; private final HttpHeaders httpHeader; - private final RetryTemplate retryTemplate = defaultTemplate(); + private final RetryTemplate retryTemplate; private final Logger log = LoggerFactory.getLogger(GpasPseudonymGenerator.class); private SSLContext customSslContext; private RestTemplate restTemplate; - public GpasPseudonymGenerator(GPasConfigProperties gpasCfg) { + public GpasPseudonymGenerator(GPasConfigProperties gpasCfg, RetryTemplate retryTemplate) { + this.retryTemplate = retryTemplate; this.gPasUrl = gpasCfg.getUri(); this.psnTargetDomain = gpasCfg.getTarget(); @@ -202,31 +191,6 @@ public class GpasPseudonymGenerator implements Generator { return headers; } - protected RetryTemplate defaultTemplate() { - RetryTemplate retryTemplate = new RetryTemplate(); - ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); - backOffPolicy.setInitialInterval(1000); - backOffPolicy.setMultiplier(1.25); - retryTemplate.setBackOffPolicy(backOffPolicy); - HashMap, Boolean> retryableExceptions = new HashMap<>(); - retryableExceptions.put(RestClientException.class, true); - retryableExceptions.put(ConnectException.class, true); - RetryPolicy retryPolicy = new SimpleRetryPolicy(3, retryableExceptions); - retryTemplate.setRetryPolicy(retryPolicy); - - retryTemplate.registerListener(new RetryListener() { - @Override - public void onError(RetryContext context, - RetryCallback callback, Throwable throwable) { - log.warn("HTTP Error occurred: {}. Retrying {}", throwable.getMessage(), - context.getRetryCount()); - RetryListener.super.onError(context, callback, throwable); - } - }); - - return retryTemplate; - } - /** * Read SSL root certificate and return SSLContext * diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt index 92965a6..71911fc 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt @@ -35,13 +35,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.retry.RetryCallback +import org.springframework.retry.RetryContext +import org.springframework.retry.RetryListener import org.springframework.retry.policy.SimpleRetryPolicy import org.springframework.retry.support.RetryTemplate import org.springframework.retry.support.RetryTemplateBuilder import org.springframework.scheduling.annotation.EnableScheduling import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.provisioning.InMemoryUserDetailsManager -import org.springframework.security.provisioning.UserDetailsManager import reactor.core.publisher.Sinks import kotlin.time.Duration.Companion.seconds import kotlin.time.toJavaDuration @@ -62,8 +64,8 @@ class AppConfiguration { @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS") @Bean - fun gpasPseudonymGenerator(configProperties: GPasConfigProperties): Generator { - return GpasPseudonymGenerator(configProperties) + fun gpasPseudonymGenerator(configProperties: GPasConfigProperties, retryTemplate: RetryTemplate): Generator { + return GpasPseudonymGenerator(configProperties, retryTemplate) } @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "BUILDIN", matchIfMissing = true) @@ -75,8 +77,8 @@ class AppConfiguration { @ConditionalOnProperty(value = ["app.pseudonymizer"], havingValue = "GPAS") @ConditionalOnMissingBean @Bean - fun gpasPseudonymGeneratorOnDeprecatedProperty(configProperties: GPasConfigProperties): Generator { - return GpasPseudonymGenerator(configProperties) + fun gpasPseudonymGeneratorOnDeprecatedProperty(configProperties: GPasConfigProperties, retryTemplate: RetryTemplate): Generator { + return GpasPseudonymGenerator(configProperties, retryTemplate) } @ConditionalOnProperty(value = ["app.pseudonymizer"], havingValue = "BUILDIN") @@ -114,8 +116,17 @@ class AppConfiguration { fun retryTemplate(): RetryTemplate { return RetryTemplateBuilder() .notRetryOn(IllegalArgumentException::class.java) - .fixedBackoff(5.seconds.toJavaDuration()) + .exponentialBackoff(2.seconds.toJavaDuration(), 1.25, 5.seconds.toJavaDuration()) .customPolicy(SimpleRetryPolicy(3)) + .withListener(object : RetryListener { + override fun onError( + context: RetryContext, + callback: RetryCallback, + throwable: Throwable + ) { + logger.warn("Error occured: {}. Retrying {}", throwable.message, context.retryCount) + } + }) .build() }