Ks 20211209 xml to java (#3236)

* try xml -> json

* Change from xml serialization to json serialization.  Also fix a deadlock in how the validation cache is used.

* changelog

* back out logback
change

* Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_7_0/3236-change-validation-from-xml-to-java.yaml

Co-authored-by: Tadgh <tadgh@cs.toronto.edu>

Co-authored-by: Tadgh <tadgh@cs.toronto.edu>
This commit is contained in:
Ken Stevens 2021-12-11 19:29:52 -05:00 committed by GitHub
parent bd89cf022b
commit d561577a9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 4 deletions

View File

@ -96,12 +96,12 @@ public class ValidationContext<T> extends BaseValidationContext<T> implements IV
IEncoder encoder = new IEncoder() {
@Override
public String encode() {
return theContext.newXmlParser().encodeResourceToString(theResource);
return theContext.newJsonParser().encodeResourceToString(theResource);
}
@Override
public EncodingEnum getEncoding() {
return EncodingEnum.XML;
return EncodingEnum.JSON;
}
};
return new ValidationContext<>(theContext, theResource, encoder, options);

View File

@ -0,0 +1,3 @@
---
type: perf
title: "Improved validation performance by switching validation serialization from XML to JSON."

View File

@ -22,7 +22,6 @@
<code value="encounter-diagnosis"/>
<display value="Encounter Diagnosis"/>
</coding>
<!-- and also a SNOMED CT coding -->
<coding>
<system value="http://snomed.info/sct"/>
<code value="439401001"/>

View File

@ -141,7 +141,7 @@ public class CachingValidationSupport extends BaseValidationSupportWrapper imple
@Override
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) {
String key = "isCodeSystemSupported " + theSystem;
Boolean retVal = loadFromCache(myCache, key, t -> super.isCodeSystemSupported(theValidationSupportContext, theSystem));
Boolean retVal = loadFromCacheReentrantSafe(myCache, key, t -> super.isCodeSystemSupported(theValidationSupportContext, theSystem));
assert retVal != null;
return retVal;
}
@ -188,6 +188,27 @@ public class CachingValidationSupport extends BaseValidationSupportWrapper imple
return result.orElse(null);
}
/**
* The Caffeine cache uses ConcurrentHashMap which is not reentrant, so if we get unlucky and the hashtable
* needs to grow at the same time as we are in a reentrant cache lookup, the thread will deadlock. Use this
* method in place of loadFromCache in situations where a cache lookup calls another cache lookup within its lambda
*/
@Nullable
private <S, T> T loadFromCacheReentrantSafe(Cache<S, Object> theCache, S theKey, Function<S, T> theLoader) {
ourLog.trace("Reentrant fetch from cache: {}", theKey);
Optional<T> result = (Optional<T>) theCache.getIfPresent(theKey);
if (result != null && result.isPresent()) {
return result.get();
}
T value = theLoader.apply(theKey);
assert value != null;
theCache.put(theKey, Optional.of(value));
return value;
}
private <S, T> T loadFromCacheWithAsyncRefresh(Cache<S, Object> theCache, S theKey, Function<S, T> theLoader) {
T retVal = (T) theCache.getIfPresent(theKey);
if (retVal == null) {