Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit df912a5

Browse files
authored
Merge pull request #7 from num-codex/insert_workaround
Insert workaround
2 parents f97d0da + b28b03b commit df912a5

16 files changed

Lines changed: 494 additions & 42 deletions

File tree

codex-process-data-transfer/pom.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@
6262
<outputDirectory>../codex-processes-ap1-docker-test-setup/crr/bpe/app/process</outputDirectory>
6363
</configuration>
6464
</execution>
65+
<execution>
66+
<id>copy-hapi-fhir-client/crr</id>
67+
<phase>package</phase>
68+
<goals>
69+
<goal>copy</goal>
70+
</goals>
71+
<configuration>
72+
<artifactItems>
73+
<artifactItem>
74+
<groupId>ca.uhn.hapi.fhir</groupId>
75+
<artifactId>hapi-fhir-client</artifactId>
76+
<version>${hapi.version}</version>
77+
</artifactItem>
78+
</artifactItems>
79+
<outputDirectory>../codex-processes-ap1-docker-test-setup/crr/bpe/app/plugin</outputDirectory>
80+
</configuration>
81+
</execution>
6582
<execution>
6683
<id>copy-process-plugin-to-docker-test-setup/dic</id>
6784
<phase>package</phase>
@@ -79,6 +96,23 @@
7996
<outputDirectory>../codex-processes-ap1-docker-test-setup/dic/bpe/app/process</outputDirectory>
8097
</configuration>
8198
</execution>
99+
<execution>
100+
<id>copy-hapi-fhir-client/dic</id>
101+
<phase>package</phase>
102+
<goals>
103+
<goal>copy</goal>
104+
</goals>
105+
<configuration>
106+
<artifactItems>
107+
<artifactItem>
108+
<groupId>ca.uhn.hapi.fhir</groupId>
109+
<artifactId>hapi-fhir-client</artifactId>
110+
<version>${hapi.version}</version>
111+
</artifactItem>
112+
</artifactItems>
113+
<outputDirectory>../codex-processes-ap1-docker-test-setup/dic/bpe/app/plugin</outputDirectory>
114+
</configuration>
115+
</execution>
82116
<execution>
83117
<id>copy-process-plugin-to-docker-test-setup/gth</id>
84118
<phase>package</phase>
@@ -110,13 +144,27 @@
110144
</includes>
111145
<followSymlinks>false</followSymlinks>
112146
</fileset>
147+
<fileset>
148+
<directory>../codex-processes-ap1-docker-test-setup/crr/bpe/app/plugin</directory>
149+
<includes>
150+
<include>hapi-fhir-client-${hapi.version}.jar</include>
151+
</includes>
152+
<followSymlinks>false</followSymlinks>
153+
</fileset>
113154
<fileset>
114155
<directory>../codex-processes-ap1-docker-test-setup/dic/bpe/app/process</directory>
115156
<includes>
116157
<include>${project.artifactId}-${project.version}.jar</include>
117158
</includes>
118159
<followSymlinks>false</followSymlinks>
119160
</fileset>
161+
<fileset>
162+
<directory>../codex-processes-ap1-docker-test-setup/dic/bpe/app/plugin</directory>
163+
<includes>
164+
<include>hapi-fhir-client-${hapi.version}.jar</include>
165+
</includes>
166+
<followSymlinks>false</followSymlinks>
167+
</fileset>
120168
<fileset>
121169
<directory>../codex-processes-ap1-docker-test-setup/gth/bpe/app/process</directory>
122170
<includes>

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FhirClientFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424

2525
public class FhirClientFactory
2626
{
27-
private static final String condition = "{\"resourceType\":\"Condition\",\"meta\":{\"profile\":[\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/chronic-lung-diseases\"]},\"clinicalStatus\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/condition-clinical\",\"code\":\"active\",\"display\":\"Active\"}]},\"verificationStatus\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/condition-ver-status\",\"code\":\"confirmed\",\"display\":\"Confirmed\"},{\"system\":\"http://snomed.info/sct\",\"code\":\"410605003\",\"display\":\"Confirmed present (qualifier value)\"}]},\"category\":[{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"418112009\",\"display\":\"Pulmonary medicine\"}]}],\"code\":{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"413839001\",\"display\":\"Chronic lung disease\"}]},\"recordedDate\":\"2020-11-10T15:50:41+01:00\"}";
27+
private static final String condition = "{\"resourceType\":\"Condition\",\"meta\":{\"profile\":[\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/chronic-lung-diseases\"]},\"clinicalStatus\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/condition-clinical\",\"code\":\"active\",\"display\":\"Active\"}]},\"verificationStatus\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/condition-ver-status\",\"code\":\"confirmed\",\"display\":\"Confirmed\"},{\"system\":\"http://snomed.info/sct\",\"code\":\"410605003\",\"display\":\"Confirmed present (qualifier value)\"}]},\"category\":[{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"418112009\",\"display\":\"Pulmonary medicine\"}]}],\"code\":{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"413839001\",\"display\":\"Chronic lung disease\"}]},\"recordedDate\":\"2020-11-10T15:50:41.000+01:00\"}";
2828
private static final String patient = "{\"resourceType\":\"Patient\",\"meta\":{\"profile\":[\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/Patient\"]},\"extension\":[{\"url\":\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/ethnic-group\",\"valueCoding\":{\"system\":\"http://snomed.info/sct\",\"code\":\"186019001\",\"display\":\"Other ethnic, mixed origin\"}},{\"url\":\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/age\",\"extension\":[{\"url\":\"dateTimeOfDocumentation\",\"valueDateTime\":\"2020-10-01\"},{\"url\":\"age\",\"valueAge\":{\"value\":67,\"unit\":\"years\",\"system\":\"http://unitsofmeasure.org\",\"code\":\"a\"}}]}],\"birthDate\":\"1953-09-30\"}";
29-
private static final String observation = "{\"resourceType\":\"Observation\",\"meta\":{\"profile\":[\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/sars-cov-2-rt-pcr\"]},\"identifier\":[{\"type\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/v2-0203\",\"code\":\"OBI\"}]}}],\"status\":\"final\",\"category\":[{\"coding\":[{\"system\":\"http://loinc.org\",\"code\":\"26436-6\"},{\"system\":\"http://terminology.hl7.org/CodeSystem/observation-category\",\"code\":\"laboratory\"}]}],\"code\":{\"coding\":[{\"system\":\"http://loinc.org\",\"code\":\"94500-6\",\"display\":\"SARS-CoV-2 (COVID-19) RNA [Presence] in Respiratory specimen by NAA with probe detection\"}],\"text\":\"SARS-CoV-2-RNA (PCR)\"},\"effectiveDateTime\":\"2020-11-10T15:50:41+01:00\",\"valueCodeableConcept\":{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"260373001\",\"display\":\"Detected (qualifier value)\"}],\"text\":\"SARS-CoV-2-RNA positiv\"}}";
29+
private static final String observation = "{\"resourceType\":\"Observation\",\"meta\":{\"profile\":[\"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/sars-cov-2-rt-pcr\"]},\"identifier\":[{\"type\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/v2-0203\",\"code\":\"OBI\"}]}}],\"status\":\"final\",\"category\":[{\"coding\":[{\"system\":\"http://loinc.org\",\"code\":\"26436-6\"},{\"system\":\"http://terminology.hl7.org/CodeSystem/observation-category\",\"code\":\"laboratory\"}]}],\"code\":{\"coding\":[{\"system\":\"http://loinc.org\",\"code\":\"94500-6\",\"display\":\"SARS-CoV-2 (COVID-19) RNA [Presence] in Respiratory specimen by NAA with probe detection\"}],\"text\":\"SARS-CoV-2-RNA (PCR)\"},\"effectiveDateTime\":\"2020-11-10T15:50:41.000+01:00\",\"valueCodeableConcept\":{\"coding\":[{\"system\":\"http://snomed.info/sct\",\"code\":\"260373001\",\"display\":\"Detected (qualifier value)\"}],\"text\":\"SARS-CoV-2-RNA positiv\"}}";
3030

3131
private static final Logger logger = LoggerFactory.getLogger(FhirClientFactory.class);
3232

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FhirClientImpl.java

Lines changed: 208 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.EnumSet;
1111
import java.util.List;
1212
import java.util.Objects;
13+
import java.util.Optional;
1314
import java.util.function.Function;
1415
import java.util.regex.Matcher;
1516
import java.util.regex.Pattern;
@@ -20,8 +21,18 @@
2021
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
2122
import org.hl7.fhir.r4.model.Bundle.BundleType;
2223
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
24+
import org.hl7.fhir.r4.model.Condition;
25+
import org.hl7.fhir.r4.model.Consent;
26+
import org.hl7.fhir.r4.model.DiagnosticReport;
2327
import org.hl7.fhir.r4.model.DomainResource;
28+
import org.hl7.fhir.r4.model.IdType;
29+
import org.hl7.fhir.r4.model.Immunization;
30+
import org.hl7.fhir.r4.model.MedicationStatement;
31+
import org.hl7.fhir.r4.model.Observation;
2432
import org.hl7.fhir.r4.model.Patient;
33+
import org.hl7.fhir.r4.model.Procedure;
34+
import org.hl7.fhir.r4.model.Reference;
35+
import org.hl7.fhir.r4.model.Resource;
2536
import org.slf4j.Logger;
2637
import org.slf4j.LoggerFactory;
2738

@@ -352,13 +363,17 @@ public PseudonymList getPseudonymsWithNewData(DateWithPrecision exportFrom, Date
352363
.flatMap(this::getPatients);
353364

354365
return new PseudonymList(patients
355-
.map(p -> p.getIdentifier().stream()
356-
.filter(i -> i.hasSystem() && i.hasValue()
357-
&& ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM.equals(i.getSystem()))
358-
.map(i -> i.getValue()).findFirst().orElse(null))
366+
.map(p -> getPseudonym(p, ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM).orElse(null))
359367
.filter(p -> p != null).distinct().collect(Collectors.toList()));
360368
}
361369

370+
private Optional<String> getPseudonym(Patient p, String namingSystem)
371+
{
372+
return p.getIdentifier().stream()
373+
.filter(i -> i.hasSystem() && i.hasValue() && namingSystem.equals(i.getSystem())).map(i -> i.getValue())
374+
.findFirst();
375+
}
376+
362377
private Stream<Patient> getPatients(Bundle bundle)
363378
{
364379
Stream<Patient> patients = getPatientsFromBundle(bundle);
@@ -433,26 +448,19 @@ private Stream<DomainResource> getNewDataWithIdentifierReferenceSupport(String p
433448
private Stream<DomainResource> getNewDataWithoutIdentifierReferenceSupport(String pseudonym,
434449
DateWithPrecision exportFrom, Date exportTo)
435450
{
436-
Bundle patientBundle = (Bundle) clientFactory.getFhirStoreClient().search().forResource(Patient.class)
437-
.where(Patient.IDENTIFIER.exactly()
438-
.systemAndIdentifier(ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM, pseudonym))
439-
.execute();
440-
441-
if (logger.isDebugEnabled())
442-
logger.debug("Patient search-bundle result: {}",
443-
fhirContext.newJsonParser().encodeResourceToString(patientBundle));
444-
445-
if (patientBundle.getTotal() != 1 || !(patientBundle.getEntryFirstRep().getResource() instanceof Patient))
451+
Optional<Patient> localPatient = findPatientInLocalFhirStore(
452+
ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_DIC_PSEUDONYM, pseudonym);
453+
if (localPatient.isEmpty())
446454
{
447455
logger.warn(
448456
"Error while retrieving patient for pseudonym {}, result bundle total not 1 or first entry not patient",
449457
pseudonym);
450458
throw new RuntimeException("Error while retrieving patient for pseudonym " + pseudonym);
451459
}
452460

453-
Patient patient = (Patient) patientBundle.getEntryFirstRep().getResource();
454461

455-
Bundle searchBundle = getSearchBundleWithPatientId(patient.getIdElement().getIdPart(), exportFrom, exportTo);
462+
Bundle searchBundle = getSearchBundleWithPatientId(localPatient.get().getIdElement().getIdPart(), exportFrom,
463+
exportTo);
456464

457465
if (logger.isDebugEnabled())
458466
logger.debug("Executing Search-Bundle: {}",
@@ -464,11 +472,26 @@ private Stream<DomainResource> getNewDataWithoutIdentifierReferenceSupport(Strin
464472
if (logger.isDebugEnabled())
465473
logger.debug("Search-Bundle result: {}", fhirContext.newJsonParser().encodeResourceToString(resultBundle));
466474

467-
return Stream.concat(Stream.of(patient),
475+
return Stream.concat(Stream.of(localPatient.get()),
468476
resultBundle.getEntry().stream().filter(e -> e.hasResource() && e.getResource() instanceof Bundle)
469477
.map(e -> (Bundle) e.getResource()).flatMap(this::getDomainResources));
470478
}
471479

480+
private Optional<Patient> findPatientInLocalFhirStore(String system, String pseudonym)
481+
{
482+
Bundle patientBundle = (Bundle) clientFactory.getFhirStoreClient().search().forResource(Patient.class)
483+
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier(system, pseudonym)).execute();
484+
485+
if (logger.isDebugEnabled())
486+
logger.debug("Patient search-bundle result: {}",
487+
fhirContext.newJsonParser().encodeResourceToString(patientBundle));
488+
489+
if (patientBundle.getTotal() != 1 || !(patientBundle.getEntryFirstRep().getResource() instanceof Patient))
490+
return Optional.empty();
491+
else
492+
return Optional.of((Patient) patientBundle.getEntryFirstRep().getResource());
493+
}
494+
472495
private Stream<DomainResource> getDomainResources(Bundle bundle)
473496
{
474497
Stream<DomainResource> domainResources = getDomainResourcesFromBundle(bundle);
@@ -501,7 +524,175 @@ private Stream<DomainResource> doGetDomainResources(String nextUrl, int subTotal
501524
@Override
502525
public void storeBundle(Bundle bundle)
503526
{
527+
if (logger.isDebugEnabled())
528+
logger.debug("Bundle: {}", fhirContext.newJsonParser().encodeResourceToString(bundle));
529+
530+
if (clientFactory.supportsIdentifierReferenceSearch())
531+
clientFactory.getFhirStoreClient().transaction().withBundle(bundle)
532+
.withAdditionalHeader(Constants.HEADER_PREFER, "handling=strict").execute();
533+
else
534+
storeBundleWithoutLogicalReferencesSupport(bundle);
535+
}
536+
537+
private void storeBundleWithoutLogicalReferencesSupport(Bundle bundle)
538+
{
539+
modifyBundle(bundle);
540+
504541
clientFactory.getFhirStoreClient().transaction().withBundle(bundle)
505542
.withAdditionalHeader(Constants.HEADER_PREFER, "handling=strict").execute();
506543
}
544+
545+
private void modifyBundle(Bundle bundle)
546+
{
547+
// bundle has patient
548+
// - db has patient by pseudonym -> update references, modify conditions
549+
// - db does not have patient -> remove patient condition
550+
// bundle has no patient, select from first resource by ref
551+
// - db has patient by pseudonym -> update references, modify conditions
552+
// - error
553+
554+
Optional<Patient> bundlePatient = bundle.getEntry().stream()
555+
.filter(e -> e.hasResource() && e.getResource() instanceof Patient).map(e -> (Patient) e.getResource())
556+
.findFirst();
557+
558+
if (bundlePatient.isPresent())
559+
{
560+
Optional<String> pseudonym = getPseudonym(bundlePatient.get(),
561+
ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM);
562+
563+
if (pseudonym.isEmpty())
564+
throw new RuntimeException("Patient has no pseudonym");
565+
566+
Optional<Patient> localPatient = findPatientInLocalFhirStore(
567+
ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM, pseudonym.get());
568+
if (localPatient.isPresent())
569+
{
570+
String localPatientid = localPatient.get().getIdElement().getIdPart();
571+
modifyBundleWithPatientId(bundle, pseudonym.get(), localPatientid);
572+
}
573+
else
574+
{
575+
String tempId = bundlePatient.get().getIdElement().getIdPart();
576+
modifyBundleWithTempPatientId(bundle, pseudonym.get(), tempId);
577+
}
578+
}
579+
else
580+
{
581+
Optional<String> pseudonym = bundle.getEntry().stream().filter(e -> e.hasResource())
582+
.map(e -> e.getResource()).map(this::getSubject).filter(r -> r.hasIdentifier())
583+
.map(r -> r.getIdentifier())
584+
.filter(i -> ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM.equals(i.getSystem()))
585+
.map(i -> i.getValue()).findFirst();
586+
587+
if (pseudonym.isEmpty())
588+
throw new RuntimeException("Patient has no pseudonym");
589+
590+
Optional<Patient> localPatient = findPatientInLocalFhirStore(
591+
ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM, pseudonym.get());
592+
if (localPatient.isPresent())
593+
{
594+
String localPatientid = localPatient.get().getIdElement().getIdPart();
595+
modifyBundleWithPatientId(bundle, pseudonym.get(), localPatientid);
596+
}
597+
else
598+
{
599+
logger.warn(
600+
"Bundle does not contain Patient, and Patient with pseudonym {} not found in local fhir store",
601+
pseudonym.get());
602+
throw new RuntimeException(
603+
"Bundle has no patient and local fhir store has no patient with pseudonym " + pseudonym.get());
604+
}
605+
}
606+
607+
if (logger.isDebugEnabled())
608+
logger.debug("Modified bundle: {}", fhirContext.newJsonParser().encodeResourceToString(bundle));
609+
}
610+
611+
private void modifyBundleWithTempPatientId(Bundle bundle, String pseudonym, String tempId)
612+
{
613+
bundle.getEntry().stream().filter(e -> e.hasResource() && !(e.getResource() instanceof Patient)).forEach(e ->
614+
{
615+
setSubject(e.getResource(), new Reference(tempId));
616+
modifyConditionalUpdateUrl(e, pseudonym, "");
617+
});
618+
}
619+
620+
private void modifyBundleWithPatientId(Bundle bundle, String pseudonym, String patientId)
621+
{
622+
bundle.getEntry().stream().filter(e -> e.hasResource() && !(e.getResource() instanceof Patient)).forEach(e ->
623+
{
624+
setSubject(e.getResource(), new Reference(new IdType("Patient", patientId)));
625+
modifyConditionalUpdateUrl(e, pseudonym, "&patient=Patient/" + patientId);
626+
});
627+
}
628+
629+
private void modifyConditionalUpdateUrl(BundleEntryComponent entry, String pseudonym, String replacement)
630+
{
631+
String url = entry.getRequest().getUrl();
632+
String newUrl = url.replace(
633+
"&patient:identifier=" + ConstantsDataTransfer.NAMING_SYSTEM_NUM_CODEX_CRR_PSEUDONYM + "|" + pseudonym,
634+
replacement);
635+
entry.getRequest().setUrl(newUrl);
636+
}
637+
638+
private Resource setSubject(Resource resource, Reference patientRef)
639+
{
640+
if (resource instanceof Condition)
641+
{
642+
((Condition) resource).setSubject(patientRef);
643+
return resource;
644+
}
645+
else if (resource instanceof Consent)
646+
{
647+
((Consent) resource).setPatient(patientRef);
648+
return resource;
649+
}
650+
else if (resource instanceof DiagnosticReport)
651+
{
652+
((DiagnosticReport) resource).setSubject(patientRef);
653+
return resource;
654+
}
655+
else if (resource instanceof Immunization)
656+
{
657+
((Immunization) resource).setPatient(patientRef);
658+
return resource;
659+
}
660+
else if (resource instanceof MedicationStatement)
661+
{
662+
((MedicationStatement) resource).setSubject(patientRef);
663+
return resource;
664+
}
665+
else if (resource instanceof Observation)
666+
{
667+
((Observation) resource).setSubject(patientRef);
668+
return resource;
669+
}
670+
else if (resource instanceof Procedure)
671+
{
672+
((Procedure) resource).setSubject(patientRef);
673+
return resource;
674+
}
675+
else
676+
throw new RuntimeException("Resource of type " + resource.getResourceType().name() + " not supported");
677+
}
678+
679+
private Reference getSubject(Resource resource)
680+
{
681+
if (resource instanceof Condition)
682+
return ((Condition) resource).getSubject();
683+
else if (resource instanceof Consent)
684+
return ((Consent) resource).getPatient();
685+
else if (resource instanceof DiagnosticReport)
686+
return ((DiagnosticReport) resource).getSubject();
687+
else if (resource instanceof Immunization)
688+
return ((Immunization) resource).getPatient();
689+
else if (resource instanceof MedicationStatement)
690+
return ((MedicationStatement) resource).getSubject();
691+
else if (resource instanceof Observation)
692+
return ((Observation) resource).getSubject();
693+
else if (resource instanceof Procedure)
694+
return ((Procedure) resource).getSubject();
695+
else
696+
throw new RuntimeException("Resource of type " + resource.getResourceType().name() + " not supported");
697+
}
507698
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/client/FttpClientFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
import java.security.cert.X509Certificate;
1515
import java.security.interfaces.RSAPrivateCrtKey;
1616
import java.security.spec.InvalidKeySpecException;
17-
import java.util.Base64;
1817
import java.util.Optional;
1918
import java.util.UUID;
2019
import java.util.regex.Matcher;
2120
import java.util.regex.Pattern;
2221

22+
import org.apache.commons.codec.binary.Hex;
2323
import org.slf4j.Logger;
2424
import org.slf4j.LoggerFactory;
2525

@@ -51,7 +51,7 @@ public Optional<String> getCrrPseudonym(String dicSourceAndPseudonym)
5151
{
5252
MessageDigest digest = MessageDigest.getInstance("SHA-256");
5353
byte[] sha256Hash = digest.digest(original.getBytes(StandardCharsets.UTF_8));
54-
return Optional.of(Base64.getEncoder().encodeToString(sha256Hash));
54+
return Optional.of(Hex.encodeHexString(sha256Hash));
5555
}
5656
catch (NoSuchAlgorithmException e)
5757
{

0 commit comments

Comments
 (0)