How to set external terminology validation

It’s definitely as you suggested, with http://snomed.info/sct in the terminology id. Now it’s working for me!
Many thanks for your time Ian!

Ooops!! Well spotted.

Have you tried querying that data back?

Yes, I have been able to query the data!

1 Like

Can you post the AQL? Just curious!!

I have done it like this:

Query<Record2<UUID, String>> query = Query.buildNativeQuery("select  e/ehr_id/value, o/data[at0001]/events[at0002]/data[at0003]/items[at0004]/value/defining_code/code_string from EHR e contains COMPOSITION a [openEHR-EHR-COMPOSITION.externalterm.v0] contains OBSERVATION o [openEHR-EHR-OBSERVATION.externalterm.v0]", UUID.class, String.class);`
List<Record2<UUID, String>> result = openEhrClient.aqlEndpoint().execute(query);
result.forEach(res->{System.out.println(res.value1() + " "+ res.value2());});
1 Like

@Alex_Paris @ian.mcnicoll
Currently, docker compose is used to start the EHRBase and related docker images. Should I rebuild the EHRBase docker image(s) if set the variable to true?

Without rebuilding the EHRBase docker image(s), the start process of EHRBase failed (i.e., Application run failed) and gave me some exception messages like:

... Factory method 'externalTerminologyValidator' threw exception with message: At least one external terminology provider must be defined if 'validation.external-validation.enabled' is set to 'true'

Thanks

Can you post your complete example, i.e. command or docker-compose file used?
Technically, you should not need to rebuild. And the error indicates that the setting went through just fine, but is missing an external terminology provider in the config.

1 Like

Thanks, @jake.smolka

.env.ehrbase

SERVER_NODENAME=local.ehrbase.org
SECURITY_AUTHUSER=ehrbase-user
SECURITY_AUTHPASSWORD=SuperSecretPassword
SECURITY_AUTHADMINUSER=ehrbase-admin
SECURITY_AUTHADMINPASSWORD=EvenMoreSecretPassword
SECURITY_OAUTH2USERROLE=USER
SECURITY_OAUTH2ADMINROLE=ADMIN
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE=env,health,info,metrics,prometheus
MANAGEMENT_ENDPOINTS_WEB_BASEPATH=/management
# Modified by Reference: github.com/crs4/openEHR-tool
MANAGEMENT_ENDPOINT_ENV_ENABLED=false
MANAGEMENT_ENDPOINT_HEALTH_ENABLED=false
MANAGEMENT_ENDPOINT_HEALTH_DATASOURCE_ENABLED=false
MANAGEMENT_ENDPOINT_INFO_ENABLED=false
MANAGEMENT_ENDPOINT_METRICS_ENABLED=false
MANAGEMENT_ENDPOINT_PROMETHEUS_ENABLED=false
MANAGEMENT_ENDPOINT_HEALTH_PROBES_ENABLED=false
# MANAGEMENT_ENDPOINT_ENV_SHOWVALUES=ALWAYS
# ADMIN_API_ACTIVE=true
# ADMINAPI_ALLOWDELETEALL=true
VALIDATION_EXTERNAL_TERMINOLOGY_ENABLED=true

Related snippet of application.yml in the ehrbase v2.6.0 folder (absolute path: ~/ehrbase-2.6.0/configuration/src/main/resources):

# External Terminology Validation Properties
validation:
  external-terminology:
    enabled: true
    fail-on-error: true
    provider:
     fhir-server-1:
       type: fhir
       url: https://example.com/fhir

Snippet of docker-compose.yml:

#
# Minimal setup for a running EHRbase. Contains the server component as well as the required postgres instance.
#
services:

  #
  # EHRBase container. see `.env.ehrbase` for configuration details.
  #
  ehrbase:
    #image: ${EHRBASE_IMAGE:-ehrbase/ehrbase:next}
    image: ehrbase/ehrbase:2.6.0
    env_file:
      - .env.ehrbase
    environment:
...

Should I set all the External Terminology Validation Properties in the .env.ehrbase file rather than the application.yml? Like the following:

# External Terminology Validation Properties
VALIDATION_EXTERNAL_TERMINOLOGY_ENABLED=true
VALIDATION_EXTERNAL_TERMINOLOGY_FAIL_ON_ERROR=true
VALIDATION_EXTERNAL_TERMINOLOGY_PROVIDER_NAME=fhir-server-1
VALIDATION_EXTERNAL_TERMINOLOGY_PROVIDER_TYPE=FHIR
VALIDATION_EXTERNAL_TERMINOLOGY_PROVIDER_URL=https://example.com/fhir

Ok - so the issue here is that you need to change this setting to point to an actual FHIR service .

The setting in the .opt is just a virtual URI

<terminology_id>
              <value>//fhir.hl7.org/ValueSet/$expand?url=https://example.com/fhir/ValueSet/valueset-exmaple</value>
            </terminology_id>

Basivally this part //fhir.hl7.org just says this is some kind of FHIR Terminology service - it does not point to an actual service.

What you have to do is setup your Ehrbase instance to point to the physical FHIR service

url: https://example.com/fhir

to something like

url: https://r4.ontoserver.csiro.au/fhir

EhrBase should then be able to replace the 'virtual part of the .opt uri with the actual endpoint

https://r4.ontoserver.csiro.au/fhir/ValueSet/$validate?url=https://example.com/fhir/ValueSet/valueset-exmaple which is what is actually sent to the server

Yes, I did as you suggested. “https://example.com/fhir” is just a dummy url for the actual FHIR server base URL.

I might be wrong but to add this setting to .env.ehrbase try these lines

VALIDATION_EXTERNAL_TERMINOLOGY_FHIR_SERVER_1_TYPE = fhir
VALIDATION_EXTERNAL_TERMINOLOGY_FHIR_SERVER_1_URL = https://example.com/fhir

This is standard Spring boot ‘speak’!!

1 Like

It seems that the cause of the Exceptions is a misspelling of the variable names in the env file. The following is the spelling of variable names from the official documentation.

# Configure FHIR Terminology Validation Server
VALIDATION_EXTERNALTERMINOLOGY_ENABLED=true
# If set it must match a spring.security.oauth2.client.registration.[client_name] that needs to be configured
VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_OAUTH2CLIENT=fhir-terminology-client
VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_TYPE=FHIR
VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_URL=http://fhir.localtest.me/fhir/

Now, the docker images can be started successfully although the Get an example Composition from a template (from the UI of the openEHR tool) still doesn’t work (i.e., retrieving the valueset).

In addition, I’m wondering how to the provider name in the variable name. @ian.mcnicoll I should try your naming method.

...
  provider:
      fhir-server-1:
...

I’m sorry. The following naming doesn’t work:

VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_FHIR_SERVER_1_TYPE=FHIR
VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_FHIR_SERVER_1_URL=http://fhir.localtest.me/fhir/

Working version:

VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_WHATEVERNAME1_TYPE=FHIR
VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_WHATEVERNAME1_URL=http://fhir.localtest.me/fhir/

My setting in the .opt is fine for the tab “form” in the on-line Archetype Designer.

image
Successfully reading the expanded valueset (a local valueset for smoking status) from my FHIR Terminology server.

Yes - but that is because AD also resolves the ‘virtual Terminology service’ in the .opt to an actual server, from a setting provided.

1 Like

The following naming for the provider name is OK but likely meaningless:

VALIDATION_EXTERNALTERMINOLOGY_PROVIDER_FHIRTERMINOLOGYSERVER_NAME=fhir-server-1

Hi, @jake.smolka. Now, the provider has been successfully set (the EHRBase can be started smoothly without any errors/exceptions). Also, the message about the operation GET an example Composition … (from the openEHR tool) is shown as successful without any error/exception messages. Furthermore, the same is true for the GET operation performed directly in the EHRBase Swagger-UI (status code: 200); in the example Composition generated, it just complains that there is No example for termínology:

      <items xsi:type="ELEMENT" archetype_node_id="at0089">
        <name>
          <value>Example Coded Element Name</value>
        </name>
        <value xsi:type="DV_CODED_TEXT">
          <value>No example for termínology '//fhir.hl7.org/ValueSet/$expand?url=https://example.com/fhir/ValueSet/valueset-exmaple' available</value>
          <defining_code>
            <terminology_id>
              <value>//fhir.hl7.org/ValueSet/$expand?url=https://example.com/fhir/ValueSet/valueset-exmaple</value>
            </terminology_id>
            <code_string>42</code_string>
          </defining_code>
        </value>
      </items>

Is there any other relevant settings to get coded elements in an example Composition populated?
Thanks.

This issue seems to be related to the following codes in the openEHR_SDK’s ExampleGeneratorConfig.java :

...
public class ExampleGeneratorConfig {
...
        static void handleCodePhrase(CodePhrase value, WebTemplateNode node, WebTemplateNode parent) {

            Optional<WebTemplateInput> codeIn = getInput(node, "code");

            selectInputValue(codeIn, 0.)
                    .map(c ->
                            Pair.of(codeIn.map(WebTemplateInput::getTerminology).orElse(null), c.getValue()))
                    .or(() -> {
                        Optional<OpenEHRTerminology> ehrTerminology = OpenEHRTerminology.lookup(parent, node.getId());

                        String codeString;
                        String terminology;
                        if (ehrTerminology.isPresent()) {
                            var terms = ehrTerminology.get().getAllTerms();

                            if (terms.isEmpty()) {
                                switch (ehrTerminology.get().openEHRGroup) {
                                    case "languages":
                                        terminology = "openehr";
                                        codeString = "de";
                                        break;
                                    default:
                                        terminology = "TODO";
                                        codeString = "TODO";
                                }
                            } else {
                                int i = determineIndex(0., terms.size());
                                var term = terms.get(i);

                                codeString = term.getCodeString();
                                terminology = term.getTerminologyId();
                            }

                        } else {
                            terminology =
                                    codeIn.map(WebTemplateInput::getTerminology).orElse(null);
                            if ("snomed-ct".equalsIgnoreCase(terminology)) {
                                codeString = "254626006";
                            } else {
                                codeString = "42";
                            }
                        }

                        return Optional.of(Pair.of(terminology, codeString));
                    })
                    .ifPresent(t -> {
                        value.setCodeString(t.getRight());
                        value.setTerminologyId(new TerminologyId(
                                Optional.ofNullable(t.getLeft()).orElse(null)));
                    });
        }
1 Like

@linforest EHRbase uses the openEHR_SDK to generate examples based on templates. However for terminology we only support a snomed-ct example for now. No FHIR terminology support for example generation.

I believe it could be useful to extend the example generation in the future with more terminology support, but, for now, keep in mind this only generates a basic example structure.

So we have this on our radar and evaluate it, could you open an Enhancement issue here Issues · ehrbase/openEHR_SDK · GitHub?

1 Like

Hi, Alex. Great to hear from you. I understand its status now. Thank you so much for your reply. And I’ll try to open an issue on this.

BTW, you know, there are dozens of such coded elements in one of my templates so it’s quite time-consuming and verbose to manually author even a single example Composition instance. Indeed that would be pretty helpful and efficient if the generator got improved with more terminology support, especially for FHIR Terminology Service.

1 Like