cds hooks allow arbitrary strings for extensions (#6026)
* changes to context booter and basecdsservicejson * cleanup CdsHooksContextBooter * javadocs * change JsonNode to CdsHooksExtension * failing test for service extensions... * fix extension serialization * fix extension serialization * failing test for request extensions not getting parsed... * try adding a custom deserializer for extension * try adding a custom deserializer for extension * try adding a custom deserializer for extension * wire up CdsServiceRegistryImpl * fix wiring object mapper * merge master * get hook in deserializer * create CdsServiceRequestJsonDeserializer.. * spotless * fix for cds service feedback for CdsHooksControllerTest.java * spotless * cleanup... * spotless... * docs * enable tests for CdsHooksContextBooterTest * more cleanup... * refactor CdsServiceRequestJsonDeserializer * apply suggestion * spotless.... * fix checkstyle... * spotless * split custom extension classes into its own package for tests * add changelog * Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6023-fix-allowing-arbitrary-json-for-cds-hooks-extensions.yaml Co-authored-by: Ken Stevens <khstevens@gmail.com> * Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6023-fix-allowing-arbitrary-json-for-cds-hooks-extensions.yaml Co-authored-by: Ken Stevens <khstevens@gmail.com> * Update hapi-fhir-server-cds-hooks/src/main/java/ca/uhn/hapi/fhir/cdshooks/api/json/CdsHooksExtension.java Co-authored-by: Ken Stevens <khstevens@gmail.com> * fix comments * rename * fix the comment * spotless * version bump to 7.3.9-SNAPSHOT --------- Co-authored-by: Ken Stevens <khstevens@gmail.com>
This commit is contained in:
parent
3ffb695b6b
commit
ce0160e7f9
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-bom</artifactId>
|
<artifactId>hapi-fhir-bom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>HAPI FHIR BOM</name>
|
<name>HAPI FHIR BOM</name>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-cli</artifactId>
|
<artifactId>hapi-fhir-cli</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
type: change
|
||||||
|
issue: 6024
|
||||||
|
title: "Previously, CDS hook extensions needed to be encoded as strings. This has been changed so that extensions are now properly provided as inline JSON."
|
|
@ -11,7 +11,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
package ca.uhn.hapi.fhir.cdshooks.api;
|
package ca.uhn.hapi.fhir.cdshooks.api;
|
||||||
|
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
@ -72,4 +74,6 @@ public @interface CdsService {
|
||||||
* An arbitrary string which will be used to store stringify JSON
|
* An arbitrary string which will be used to store stringify JSON
|
||||||
*/
|
*/
|
||||||
String extension() default "";
|
String extension() default "";
|
||||||
|
|
||||||
|
Class<? extends CdsHooksExtension> extensionClass() default CdsHooksExtension.class;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public interface ICdsServiceRegistry {
|
||||||
* @param theCdsServiceFeedbackJson the request
|
* @param theCdsServiceFeedbackJson the request
|
||||||
* @return the response
|
* @return the response
|
||||||
*/
|
*/
|
||||||
String callFeedback(String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson);
|
CdsServiceFeedbackJson callFeedback(String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new CDS Service with the endpoint.
|
* Register a new CDS Service with the endpoint.
|
||||||
|
@ -86,4 +86,12 @@ public interface ICdsServiceRegistry {
|
||||||
* @param theServiceId the id of the service to be removed
|
* @param theServiceId the id of the service to be removed
|
||||||
*/
|
*/
|
||||||
void unregisterService(String theServiceId, String theModuleId);
|
void unregisterService(String theServiceId, String theModuleId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get registered CDS service with service ID
|
||||||
|
* @param theServiceId the id of the service to be retrieved
|
||||||
|
* @return CdsServiceJson
|
||||||
|
* @throws IllegalArgumentException if a CDS service with provided serviceId is not found
|
||||||
|
*/
|
||||||
|
CdsServiceJson getCdsServiceJson(String theServiceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,29 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see <a href=" https://cds-hooks.hl7.org/1.0/#extensions">For reading more about Extension support in CDS hooks</a>
|
* @see <a href=" https://cds-hooks.hl7.org/1.0/#extensions">For reading more about Extension support in CDS hooks</a>
|
||||||
|
* Example can be found <a href="https://build.fhir.org/ig/HL7/davinci-crd/deviations.html#configuration-options-extension">here</a>
|
||||||
*/
|
*/
|
||||||
public abstract class BaseCdsServiceJson implements IModelJson {
|
public abstract class BaseCdsServiceJson implements IModelJson {
|
||||||
|
|
||||||
@JsonProperty(value = "extension", required = true)
|
@JsonProperty(value = "extension")
|
||||||
String myExtension;
|
CdsHooksExtension myExtension;
|
||||||
|
|
||||||
public String getExtension() {
|
private Class<? extends CdsHooksExtension> myExtensionClass;
|
||||||
|
|
||||||
|
public CdsHooksExtension getExtension() {
|
||||||
return myExtension;
|
return myExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseCdsServiceJson setExtension(String theExtension) {
|
public BaseCdsServiceJson setExtension(CdsHooksExtension theExtension) {
|
||||||
this.myExtension = theExtension;
|
this.myExtension = theExtension;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setExtensionClass(Class<? extends CdsHooksExtension> theClass) {
|
||||||
|
this.myExtensionClass = theClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends CdsHooksExtension> getExtensionClass() {
|
||||||
|
return myExtensionClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.api.json;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.api.IModelJson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users can define CDS Hooks extensions by extending this class.
|
||||||
|
* Implementors can extend this class for defining their custom extensions.
|
||||||
|
*/
|
||||||
|
public class CdsHooksExtension implements IModelJson {}
|
|
@ -98,13 +98,15 @@ public class CdsHooksConfig {
|
||||||
CdsPrefetchSvc theCdsPrefetchSvc,
|
CdsPrefetchSvc theCdsPrefetchSvc,
|
||||||
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY) ObjectMapper theObjectMapper,
|
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY) ObjectMapper theObjectMapper,
|
||||||
ICdsCrServiceFactory theCdsCrServiceFactory,
|
ICdsCrServiceFactory theCdsCrServiceFactory,
|
||||||
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory) {
|
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory,
|
||||||
|
FhirContext theFhirContext) {
|
||||||
return new CdsServiceRegistryImpl(
|
return new CdsServiceRegistryImpl(
|
||||||
theCdsHooksContextBooter,
|
theCdsHooksContextBooter,
|
||||||
theCdsPrefetchSvc,
|
theCdsPrefetchSvc,
|
||||||
theObjectMapper,
|
theObjectMapper,
|
||||||
theCdsCrServiceFactory,
|
theCdsCrServiceFactory,
|
||||||
theCrDiscoveryServiceFactory);
|
theCrDiscoveryServiceFactory,
|
||||||
|
theFhirContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
@ -94,13 +94,12 @@ public class CdsHooksController {
|
||||||
path = "{cds_hook}/feedback",
|
path = "{cds_hook}/feedback",
|
||||||
method = {RequestMethod.POST},
|
method = {RequestMethod.POST},
|
||||||
consumes = {MediaType.APPLICATION_JSON_VALUE})
|
consumes = {MediaType.APPLICATION_JSON_VALUE})
|
||||||
public ResponseEntity<String> cdsServiceFeedback(
|
public ResponseEntity<CdsServiceFeedbackJson> cdsServiceFeedback(
|
||||||
@PathVariable("cds_hook") String theCdsHook,
|
@PathVariable("cds_hook") String theCdsHook,
|
||||||
@RequestBody CdsServiceFeedbackJson theCdsServiceFeedbackJson) {
|
@RequestBody CdsServiceFeedbackJson theCdsServiceFeedbackJson) {
|
||||||
String json = myCdsServiceRegistry.callFeedback(theCdsHook, theCdsServiceFeedbackJson);
|
CdsServiceFeedbackJson response = myCdsServiceRegistry.callFeedback(theCdsHook, theCdsServiceFeedbackJson);
|
||||||
|
|
||||||
return ResponseEntity.status(200)
|
return ResponseEntity.status(200)
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.body(json);
|
.body(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.serializer;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import ca.uhn.fhir.serializer.FhirResourceDeserializer;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestContextJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.CdsServiceRegistryImpl;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CdsServiceRequestJsonDeserializer extends StdDeserializer<CdsServiceRequestJson> {
|
||||||
|
|
||||||
|
private final CdsServiceRegistryImpl myCdsServiceRegistry;
|
||||||
|
private final ObjectMapper myObjectMapper;
|
||||||
|
private final FhirContext myFhirContext;
|
||||||
|
private final IParser myParser;
|
||||||
|
|
||||||
|
public CdsServiceRequestJsonDeserializer(CdsServiceRegistryImpl theCdsServiceRegistry, FhirContext theFhirContext) {
|
||||||
|
super(CdsServiceRequestJson.class);
|
||||||
|
myCdsServiceRegistry = theCdsServiceRegistry;
|
||||||
|
myFhirContext = theFhirContext;
|
||||||
|
myParser = myFhirContext.newJsonParser().setPrettyPrint(true);
|
||||||
|
// We create a new ObjectMapper instead of using the one from the ApplicationContext to avoid an infinite loop
|
||||||
|
// during deserialization.
|
||||||
|
myObjectMapper = new ObjectMapper();
|
||||||
|
configureObjectMapper(myObjectMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CdsServiceRequestJson deserialize(JsonParser theJsonParser, DeserializationContext theDeserializationContext)
|
||||||
|
throws IOException {
|
||||||
|
final JsonNode cdsServiceRequestJsonNode = theJsonParser.getCodec().readTree(theJsonParser);
|
||||||
|
final JsonNode hookNode = cdsServiceRequestJsonNode.get("hook");
|
||||||
|
final JsonNode extensionNode = cdsServiceRequestJsonNode.get("extension");
|
||||||
|
final JsonNode requestContext = cdsServiceRequestJsonNode.get("context");
|
||||||
|
final CdsServiceRequestJson cdsServiceRequestJson =
|
||||||
|
myObjectMapper.treeToValue(cdsServiceRequestJsonNode, CdsServiceRequestJson.class);
|
||||||
|
if (extensionNode != null) {
|
||||||
|
CdsHooksExtension myRequestExtension = deserializeExtension(hookNode.textValue(), extensionNode.toString());
|
||||||
|
cdsServiceRequestJson.setExtension(myRequestExtension);
|
||||||
|
}
|
||||||
|
if (requestContext != null) {
|
||||||
|
LinkedHashMap<String, Object> map =
|
||||||
|
myObjectMapper.readValue(requestContext.toString(), LinkedHashMap.class);
|
||||||
|
cdsServiceRequestJson.setContext(deserializeRequestContext(map));
|
||||||
|
}
|
||||||
|
return cdsServiceRequestJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureObjectMapper(ObjectMapper theObjectMapper) {
|
||||||
|
SimpleModule module = new SimpleModule();
|
||||||
|
module.addDeserializer(IBaseResource.class, new FhirResourceDeserializer(myFhirContext));
|
||||||
|
theObjectMapper.registerModule(module);
|
||||||
|
// set this as we will need to ignore properties which are not defined by specific implementation.
|
||||||
|
theObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CdsHooksExtension deserializeExtension(String theServiceId, String theExtension) throws JsonProcessingException {
|
||||||
|
final CdsServiceJson cdsServicesJson = myCdsServiceRegistry.getCdsServiceJson(theServiceId);
|
||||||
|
Class<? extends CdsHooksExtension> extensionClass = cdsServicesJson.getExtensionClass();
|
||||||
|
if (extensionClass == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return myObjectMapper.readValue(theExtension, extensionClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
CdsServiceRequestContextJson deserializeRequestContext(LinkedHashMap<String, Object> theMap)
|
||||||
|
throws JsonProcessingException {
|
||||||
|
final CdsServiceRequestContextJson cdsServiceRequestContextJson = new CdsServiceRequestContextJson();
|
||||||
|
for (Map.Entry<String, Object> entry : theMap.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
// Convert LinkedHashMap entries to Resources
|
||||||
|
if (value instanceof LinkedHashMap) {
|
||||||
|
String json = myObjectMapper.writeValueAsString(value);
|
||||||
|
IBaseResource resource = myParser.parseResource(json);
|
||||||
|
cdsServiceRequestContextJson.put(key, resource);
|
||||||
|
} else {
|
||||||
|
cdsServiceRequestContextJson.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cdsServiceRequestContextJson;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
@ -85,7 +86,8 @@ public class CdsHooksContextBooter {
|
||||||
cdsServiceJson.setHook(annotation.hook());
|
cdsServiceJson.setHook(annotation.hook());
|
||||||
cdsServiceJson.setDescription(annotation.description());
|
cdsServiceJson.setDescription(annotation.description());
|
||||||
cdsServiceJson.setTitle(annotation.title());
|
cdsServiceJson.setTitle(annotation.title());
|
||||||
cdsServiceJson.setExtension(validateJson(annotation.extension()));
|
cdsServiceJson.setExtension(serializeExtensions(annotation.extension(), annotation.extensionClass()));
|
||||||
|
cdsServiceJson.setExtensionClass(annotation.extensionClass());
|
||||||
for (CdsServicePrefetch prefetch : annotation.prefetch()) {
|
for (CdsServicePrefetch prefetch : annotation.prefetch()) {
|
||||||
cdsServiceJson.addPrefetch(prefetch.value(), prefetch.query());
|
cdsServiceJson.addPrefetch(prefetch.value(), prefetch.query());
|
||||||
cdsServiceJson.addSource(prefetch.value(), prefetch.source());
|
cdsServiceJson.addSource(prefetch.value(), prefetch.source());
|
||||||
|
@ -104,14 +106,13 @@ public class CdsHooksContextBooter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String validateJson(String theExtension) {
|
CdsHooksExtension serializeExtensions(String theExtension, Class<? extends CdsHooksExtension> theClass) {
|
||||||
if (StringUtils.isEmpty(theExtension)) {
|
if (StringUtils.isEmpty(theExtension)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final ObjectMapper mapper = new ObjectMapper();
|
final ObjectMapper mapper = new ObjectMapper();
|
||||||
mapper.readTree(theExtension);
|
return mapper.readValue(theExtension, theClass);
|
||||||
return theExtension;
|
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
final String message = String.format("Invalid JSON: %s", e.getMessage());
|
final String message = String.format("Invalid JSON: %s", e.getMessage());
|
||||||
ourLog.debug(message);
|
ourLog.debug(message);
|
||||||
|
|
|
@ -131,4 +131,11 @@ public class CdsServiceCache {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdsServiceJson getCdsServiceJson(String theString) {
|
||||||
|
return myCdsServiceJson.getServices().stream()
|
||||||
|
.filter(x -> x.getId().equals(theString))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,21 +20,26 @@
|
||||||
package ca.uhn.hapi.fhir.cdshooks.svc;
|
package ca.uhn.hapi.fhir.cdshooks.svc;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsMethod;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsMethod;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceMethod;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceMethod;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.serializer.CdsServiceRequestJsonDeserializer;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
|
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
|
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchSvc;
|
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchSvc;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import jakarta.annotation.Nonnull;
|
import jakarta.annotation.Nonnull;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
@ -59,10 +64,18 @@ public class CdsServiceRegistryImpl implements ICdsServiceRegistry {
|
||||||
CdsPrefetchSvc theCdsPrefetchSvc,
|
CdsPrefetchSvc theCdsPrefetchSvc,
|
||||||
ObjectMapper theObjectMapper,
|
ObjectMapper theObjectMapper,
|
||||||
ICdsCrServiceFactory theCdsCrServiceFactory,
|
ICdsCrServiceFactory theCdsCrServiceFactory,
|
||||||
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory) {
|
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory,
|
||||||
|
FhirContext theFhirContext) {
|
||||||
myCdsHooksContextBooter = theCdsHooksContextBooter;
|
myCdsHooksContextBooter = theCdsHooksContextBooter;
|
||||||
myCdsPrefetchSvc = theCdsPrefetchSvc;
|
myCdsPrefetchSvc = theCdsPrefetchSvc;
|
||||||
myObjectMapper = theObjectMapper;
|
myObjectMapper = theObjectMapper;
|
||||||
|
// registering this deserializer here instead of
|
||||||
|
// CdsHooksObjectMapperFactory to avoid circular
|
||||||
|
// dependency
|
||||||
|
SimpleModule module = new SimpleModule();
|
||||||
|
module.addDeserializer(
|
||||||
|
CdsServiceRequestJson.class, new CdsServiceRequestJsonDeserializer(this, theFhirContext));
|
||||||
|
myObjectMapper.registerModule(module);
|
||||||
myCdsCrServiceFactory = theCdsCrServiceFactory;
|
myCdsCrServiceFactory = theCdsCrServiceFactory;
|
||||||
myCrDiscoveryServiceFactory = theCrDiscoveryServiceFactory;
|
myCrDiscoveryServiceFactory = theCrDiscoveryServiceFactory;
|
||||||
}
|
}
|
||||||
|
@ -82,61 +95,14 @@ public class CdsServiceRegistryImpl implements ICdsServiceRegistry {
|
||||||
ICdsServiceMethod serviceMethod = (ICdsServiceMethod) getCdsServiceMethodOrThrowException(theServiceId);
|
ICdsServiceMethod serviceMethod = (ICdsServiceMethod) getCdsServiceMethodOrThrowException(theServiceId);
|
||||||
myCdsPrefetchSvc.augmentRequest(theCdsServiceRequestJson, serviceMethod);
|
myCdsPrefetchSvc.augmentRequest(theCdsServiceRequestJson, serviceMethod);
|
||||||
Object response = serviceMethod.invoke(myObjectMapper, theCdsServiceRequestJson, theServiceId);
|
Object response = serviceMethod.invoke(myObjectMapper, theCdsServiceRequestJson, theServiceId);
|
||||||
|
|
||||||
return encodeServiceResponse(theServiceId, response);
|
return encodeServiceResponse(theServiceId, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CdsServiceResponseJson encodeServiceResponse(String theServiceId, Object result) {
|
|
||||||
String json;
|
|
||||||
if (result instanceof String) {
|
|
||||||
json = (String) result;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
json = myObjectMapper.writeValueAsString(result);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new ConfigurationException(
|
|
||||||
Msg.code(2389) + "Failed to json serialize Cds service response of type "
|
|
||||||
+ result.getClass().getName() + " when calling CDS Hook Service " + theServiceId,
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return myObjectMapper.readValue(json, CdsServiceResponseJson.class);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new ConfigurationException(
|
|
||||||
Msg.code(2390) + "Failed to json deserialize Cds service response of type "
|
|
||||||
+ result.getClass().getName() + " when calling CDS Hook Service " + theServiceId
|
|
||||||
+ ". Json: " + json,
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private ICdsMethod getCdsServiceMethodOrThrowException(String theId) {
|
|
||||||
ICdsMethod retval = myServiceCache.getServiceMethod(theId);
|
|
||||||
if (retval == null) {
|
|
||||||
throw new ResourceNotFoundException(
|
|
||||||
Msg.code(2391) + "No service with id " + theId + " is registered on this server");
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private ICdsMethod getCdsFeedbackMethodOrThrowException(String theId) {
|
|
||||||
ICdsMethod retval = myServiceCache.getFeedbackMethod(theId);
|
|
||||||
if (retval == null) {
|
|
||||||
throw new ResourceNotFoundException(
|
|
||||||
Msg.code(2392) + "No feedback service with id " + theId + " is registered on this server");
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String callFeedback(String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson) {
|
public CdsServiceFeedbackJson callFeedback(String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson) {
|
||||||
ICdsMethod feedbackMethod = getCdsFeedbackMethodOrThrowException(theServiceId);
|
ICdsMethod feedbackMethod = getCdsFeedbackMethodOrThrowException(theServiceId);
|
||||||
Object response = feedbackMethod.invoke(myObjectMapper, theCdsServiceFeedbackJson, theServiceId);
|
Object response = feedbackMethod.invoke(myObjectMapper, theCdsServiceFeedbackJson, theServiceId);
|
||||||
|
return encodeFeedbackResponse(theServiceId, response);
|
||||||
return encodeFeedbackResponse(theServiceId, theCdsServiceFeedbackJson, response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -146,6 +112,9 @@ public class CdsServiceRegistryImpl implements ICdsServiceRegistry {
|
||||||
CdsServiceJson theCdsServiceJson,
|
CdsServiceJson theCdsServiceJson,
|
||||||
boolean theAllowAutoFhirClientPrefetch,
|
boolean theAllowAutoFhirClientPrefetch,
|
||||||
String theModuleId) {
|
String theModuleId) {
|
||||||
|
if (theCdsServiceJson.getExtensionClass() == null) {
|
||||||
|
theCdsServiceJson.setExtensionClass(CdsHooksExtension.class);
|
||||||
|
}
|
||||||
myServiceCache.registerDynamicService(
|
myServiceCache.registerDynamicService(
|
||||||
theServiceId, theServiceFunction, theCdsServiceJson, theAllowAutoFhirClientPrefetch, theModuleId);
|
theServiceId, theServiceFunction, theCdsServiceJson, theAllowAutoFhirClientPrefetch, theModuleId);
|
||||||
}
|
}
|
||||||
|
@ -171,25 +140,100 @@ public class CdsServiceRegistryImpl implements ICdsServiceRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String encodeFeedbackResponse(
|
@Override
|
||||||
String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson, Object response) {
|
public CdsServiceJson getCdsServiceJson(String theServiceId) {
|
||||||
if (response instanceof String) {
|
CdsServiceJson cdsServiceJson = myServiceCache.getCdsServiceJson(theServiceId);
|
||||||
return (String) response;
|
if (cdsServiceJson == null) {
|
||||||
|
throw new IllegalArgumentException(Msg.code(2536) + "No service with " + theServiceId + " is registered.");
|
||||||
|
}
|
||||||
|
return cdsServiceJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private ICdsMethod getCdsServiceMethodOrThrowException(String theId) {
|
||||||
|
ICdsMethod retval = myServiceCache.getServiceMethod(theId);
|
||||||
|
if (retval == null) {
|
||||||
|
throw new ResourceNotFoundException(
|
||||||
|
Msg.code(2391) + "No service with id " + theId + " is registered on this server");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
CdsServiceResponseJson encodeServiceResponse(String theServiceId, Object result) {
|
||||||
|
if (result instanceof String) {
|
||||||
|
return buildResponseFromString(theServiceId, result, (String) result);
|
||||||
} else {
|
} else {
|
||||||
try {
|
return buildResponseFromImplementation(theServiceId, result);
|
||||||
// Try to json encode the response
|
|
||||||
return myObjectMapper.writeValueAsString(response);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
try {
|
|
||||||
ourLog.warn("Failed to deserialize response from {} feedback method", theServiceId, e);
|
|
||||||
// Just send back what we received
|
|
||||||
return myObjectMapper.writeValueAsString(theCdsServiceFeedbackJson);
|
|
||||||
} catch (JsonProcessingException f) {
|
|
||||||
ourLog.error("Failed to deserialize request parameter to {} feedback method", theServiceId, e);
|
|
||||||
// Okay then...
|
|
||||||
return "{}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private ICdsMethod getCdsFeedbackMethodOrThrowException(String theId) {
|
||||||
|
ICdsMethod retval = myServiceCache.getFeedbackMethod(theId);
|
||||||
|
if (retval == null) {
|
||||||
|
throw new ResourceNotFoundException(
|
||||||
|
Msg.code(2392) + "No feedback service with id " + theId + " is registered on this server");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
CdsServiceFeedbackJson encodeFeedbackResponse(String theServiceId, Object theResponse) {
|
||||||
|
if (theResponse instanceof String) {
|
||||||
|
return buildFeedbackFromString(theServiceId, (String) theResponse);
|
||||||
|
} else {
|
||||||
|
return buildFeedbackFromImplementation(theServiceId, theResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CdsServiceResponseJson buildResponseFromImplementation(String theServiceId, Object theResult) {
|
||||||
|
try {
|
||||||
|
return (CdsServiceResponseJson) theResult;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
Msg.code(2389)
|
||||||
|
+ "Failed to cast Cds service response to CdsServiceResponseJson when calling CDS Hook Service "
|
||||||
|
+ theServiceId + ". The type "
|
||||||
|
+ theResult.getClass().getName()
|
||||||
|
+ " cannot be casted to CdsServiceResponseJson",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CdsServiceResponseJson buildResponseFromString(String theServiceId, Object theResult, String theJson) {
|
||||||
|
try {
|
||||||
|
return myObjectMapper.readValue(theJson, CdsServiceResponseJson.class);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
Msg.code(2390) + "Failed to json deserialize Cds service response of type "
|
||||||
|
+ theResult.getClass().getName() + " when calling CDS Hook Service " + theServiceId
|
||||||
|
+ ". Json: " + theJson,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CdsServiceFeedbackJson buildFeedbackFromImplementation(String theServiceId, Object theResponse) {
|
||||||
|
try {
|
||||||
|
return (CdsServiceFeedbackJson) theResponse;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ClassCastException(
|
||||||
|
Msg.code(2537) + "Failed to cast feedback response CdsServiceFeedbackJson for service "
|
||||||
|
+ theServiceId + ". " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CdsServiceFeedbackJson buildFeedbackFromString(String theServiceId, String theResponse) {
|
||||||
|
try {
|
||||||
|
return myObjectMapper.readValue(theResponse, CdsServiceFeedbackJson.class);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(Msg.code(2538) + "Failed to serialize json Cds Feedback response for service "
|
||||||
|
+ theServiceId + ". " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setServiceCache(CdsServiceCache theCdsServiceCache) {
|
||||||
|
myServiceCache = theCdsServiceCache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseCardJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig;
|
import ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.config.TestCdsHooksConfig;
|
import ca.uhn.hapi.fhir.cdshooks.config.TestCdsHooksConfig;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.RequestExtension;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchFhirClientSvc;
|
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchFhirClientSvc;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
@ -21,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
@ -30,6 +32,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
@ -67,7 +70,9 @@ public class CdsHooksControllerTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
myMockMvc = MockMvcBuilders.standaloneSetup(new CdsHooksController(myCdsHooksRegistry)).build();
|
myMockMvc = MockMvcBuilders.standaloneSetup(new CdsHooksController(myCdsHooksRegistry))
|
||||||
|
.setMessageConverters(new MappingJackson2HttpMessageConverter(myObjectMapper))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -82,25 +87,29 @@ public class CdsHooksControllerTest {
|
||||||
.andExpect(jsonPath("services[2].title").value(GreeterCdsService.TEST_HOOK_TITLE))
|
.andExpect(jsonPath("services[2].title").value(GreeterCdsService.TEST_HOOK_TITLE))
|
||||||
.andExpect(jsonPath("services[2].id").value(GreeterCdsService.TEST_HOOK_STRING_ID))
|
.andExpect(jsonPath("services[2].id").value(GreeterCdsService.TEST_HOOK_STRING_ID))
|
||||||
.andExpect(jsonPath("services[2].prefetch." + GreeterCdsService.TEST_HOOK_PREFETCH_USER_KEY).value(GreeterCdsService.TEST_HOOK_PREFETCH_USER_QUERY))
|
.andExpect(jsonPath("services[2].prefetch." + GreeterCdsService.TEST_HOOK_PREFETCH_USER_KEY).value(GreeterCdsService.TEST_HOOK_PREFETCH_USER_QUERY))
|
||||||
.andExpect(jsonPath("services[2].prefetch." + GreeterCdsService.TEST_HOOK_PREFETCH_PATIENT_KEY).value(GreeterCdsService.TEST_HOOK_PREFETCH_PATIENT_QUERY));
|
.andExpect(jsonPath("services[2].prefetch." + GreeterCdsService.TEST_HOOK_PREFETCH_PATIENT_KEY).value(GreeterCdsService.TEST_HOOK_PREFETCH_PATIENT_QUERY))
|
||||||
|
.andExpect(jsonPath("services[5].extension.example-client-conformance").value("http://hooks.example.org/fhir/102/Conformance/patientview"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testExampleFeedback() throws Exception {
|
void testExampleFeedback() throws Exception {
|
||||||
CdsServiceFeedbackJson request = new CdsServiceFeedbackJson();
|
// setup
|
||||||
|
final CdsServiceFeedbackJson request = new CdsServiceFeedbackJson();
|
||||||
request.setCard(TEST_HOOK_INSTANCE);
|
request.setCard(TEST_HOOK_INSTANCE);
|
||||||
request.setOutcome(CdsServiceFeebackOutcomeEnum.accepted);
|
request.setOutcome(CdsServiceFeebackOutcomeEnum.accepted);
|
||||||
request.setOutcomeTimestamp(OUTCOME_TIMESTAMP);
|
request.setOutcomeTimestamp(OUTCOME_TIMESTAMP);
|
||||||
|
final String requestBody = myObjectMapper.writeValueAsString(request);
|
||||||
String requestBody = myObjectMapper.writeValueAsString(request);
|
// execute
|
||||||
|
final MvcResult actual = myMockMvc
|
||||||
myMockMvc
|
|
||||||
.perform(post(CdsHooksController.BASE + "/example-service/feedback").contentType(MediaType.APPLICATION_JSON).content(requestBody))
|
.perform(post(CdsHooksController.BASE + "/example-service/feedback").contentType(MediaType.APPLICATION_JSON).content(requestBody))
|
||||||
.andDo(print())
|
.andDo(print())
|
||||||
.andExpect(status().is2xxSuccessful())
|
.andExpect(status().is2xxSuccessful())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("message").value("Thank you for your feedback dated " + OUTCOME_TIMESTAMP + "!"))
|
.andReturn();
|
||||||
;
|
// validate
|
||||||
|
final CdsServiceFeedbackJson cdsServiceFeedbackJson = myObjectMapper.readValue(actual.getResponse().getContentAsString(), CdsServiceFeedbackJson.class);
|
||||||
|
assertThat(cdsServiceFeedbackJson.getAcceptedSuggestions()).hasSize(1);
|
||||||
|
assertThat(cdsServiceFeedbackJson).usingRecursiveComparison().ignoringFields("myAcceptedSuggestions").isEqualTo(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -127,8 +136,14 @@ public class CdsHooksControllerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCallHelloUniverse() throws Exception {
|
void testCallHelloUniverse() throws Exception {
|
||||||
|
RequestExtension requestExtension = new RequestExtension();
|
||||||
|
requestExtension.setConfigItem("request-config-item");
|
||||||
|
|
||||||
CdsServiceRequestJson request = new CdsServiceRequestJson();
|
CdsServiceRequestJson request = new CdsServiceRequestJson();
|
||||||
|
request.setExtension(requestExtension);
|
||||||
request.setFhirServer(TEST_FHIR_SERVER);
|
request.setFhirServer(TEST_FHIR_SERVER);
|
||||||
|
request.setHook(HelloWorldService.TEST_HOOK_UNIVERSE_ID);
|
||||||
|
|
||||||
|
|
||||||
String requestBody = myObjectMapper.writeValueAsString(request);
|
String requestBody = myObjectMapper.writeValueAsString(request);
|
||||||
|
|
||||||
|
@ -139,7 +154,7 @@ public class CdsHooksControllerTest {
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("cards[0].summary").value("Hello Universe!"))
|
.andExpect(jsonPath("cards[0].summary").value("Hello Universe!"))
|
||||||
.andExpect(jsonPath("cards[0].indicator").value("critical"))
|
.andExpect(jsonPath("cards[0].indicator").value("critical"))
|
||||||
;
|
.andExpect(jsonPath("cards[0].extension.example-config-item").value("request-config-item"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -163,21 +178,24 @@ public class CdsHooksControllerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testHelloWorldFeedback() throws Exception {
|
void testHelloWorldFeedback() throws Exception {
|
||||||
CdsServiceFeedbackJson request = new CdsServiceFeedbackJson();
|
// setup
|
||||||
|
final CdsServiceFeedbackJson request = new CdsServiceFeedbackJson();
|
||||||
request.setCard(TEST_HOOK_INSTANCE);
|
request.setCard(TEST_HOOK_INSTANCE);
|
||||||
request.setOutcome(CdsServiceFeebackOutcomeEnum.accepted);
|
request.setOutcome(CdsServiceFeebackOutcomeEnum.accepted);
|
||||||
request.setOutcomeTimestamp(OUTCOME_TIMESTAMP);
|
request.setOutcomeTimestamp(OUTCOME_TIMESTAMP);
|
||||||
|
|
||||||
String requestBody = myObjectMapper.writeValueAsString(request);
|
String requestBody = myObjectMapper.writeValueAsString(request);
|
||||||
|
|
||||||
TestServerAppCtx.ourHelloWorldService.setExpectedCount(1);
|
TestServerAppCtx.ourHelloWorldService.setExpectedCount(1);
|
||||||
myMockMvc
|
// execute
|
||||||
|
MvcResult actual = myMockMvc
|
||||||
.perform(post(CdsHooksController.BASE + "/" + HelloWorldService.TEST_HOOK_WORLD_ID + "/feedback").contentType(MediaType.APPLICATION_JSON).content(requestBody))
|
.perform(post(CdsHooksController.BASE + "/" + HelloWorldService.TEST_HOOK_WORLD_ID + "/feedback").contentType(MediaType.APPLICATION_JSON).content(requestBody))
|
||||||
.andDo(print())
|
.andDo(print())
|
||||||
.andExpect(status().is2xxSuccessful())
|
.andExpect(status().is2xxSuccessful())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("message").value("Thank you for your feedback dated " + OUTCOME_TIMESTAMP + "!"))
|
.andReturn();
|
||||||
;
|
// validate
|
||||||
|
final CdsServiceFeedbackJson cdsServiceFeedbackJson = myObjectMapper.readValue(actual.getResponse().getContentAsString(), CdsServiceFeedbackJson.class);
|
||||||
|
assertThat(cdsServiceFeedbackJson.getAcceptedSuggestions()).hasSize(1);
|
||||||
|
assertThat(cdsServiceFeedbackJson).usingRecursiveComparison().ignoringFields("myAcceptedSuggestions").isEqualTo(request);
|
||||||
TestServerAppCtx.ourHelloWorldService.awaitExpected();
|
TestServerAppCtx.ourHelloWorldService.awaitExpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.hapi.fhir.cdshooks.controller;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceAcceptedSuggestionJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceIndicatorEnum;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceIndicatorEnum;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
|
@ -11,6 +12,9 @@ import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseCardSourceJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ExampleCdsService {
|
public class ExampleCdsService {
|
||||||
@CdsService(value = "example-service",
|
@CdsService(value = "example-service",
|
||||||
hook = "patient-view",
|
hook = "patient-view",
|
||||||
|
@ -33,7 +37,8 @@ public class ExampleCdsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@CdsServiceFeedback("example-service")
|
@CdsServiceFeedback("example-service")
|
||||||
public String exampleServiceFeedback(CdsServiceFeedbackJson theFeedback) {
|
public CdsServiceFeedbackJson feedback(CdsServiceFeedbackJson theFeedback) {
|
||||||
return "{\"message\": \"Thank you for your feedback dated " + theFeedback.getOutcomeTimestamp() + "!\"}";
|
theFeedback.setAcceptedSuggestions(List.of(new CdsServiceAcceptedSuggestionJson().setId(UUID.randomUUID().toString())));
|
||||||
|
return theFeedback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,22 @@ import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsService;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServiceFeedback;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
import ca.uhn.hapi.fhir.cdshooks.api.CdsServicePrefetch;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceAcceptedSuggestionJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceIndicatorEnum;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseCardJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseCardSourceJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.ExampleConfigExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.RequestExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.ResponseExtension;
|
||||||
import ca.uhn.test.concurrency.IPointcutLatch;
|
import ca.uhn.test.concurrency.IPointcutLatch;
|
||||||
import ca.uhn.test.concurrency.PointcutLatch;
|
import ca.uhn.test.concurrency.PointcutLatch;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class HelloWorldService implements IPointcutLatch {
|
public class HelloWorldService implements IPointcutLatch {
|
||||||
public static final String TEST_HOOK = "hello-world";
|
public static final String TEST_HOOK = "hello-world";
|
||||||
|
@ -20,6 +30,9 @@ public class HelloWorldService implements IPointcutLatch {
|
||||||
public static final String TEST_HOOK_PLAYBACK_ID = "hwid3";
|
public static final String TEST_HOOK_PLAYBACK_ID = "hwid3";
|
||||||
public static final String TEST_HOOK_PREFETCH_PATIENT_KEY = "patient";
|
public static final String TEST_HOOK_PREFETCH_PATIENT_KEY = "patient";
|
||||||
public static final String TEST_HOOK_PREFETCH_MEDS_KEY = "medications";
|
public static final String TEST_HOOK_PREFETCH_MEDS_KEY = "medications";
|
||||||
|
public static final String CDS_HOOKS_EXTENSION_PROPERTY_PRACTITIONER_SPECIALITY = "myextension-practitionerspecialty";
|
||||||
|
public static final String CDS_HOOKS_EXTENSION_PROPERTY_TIMESTAMP = "timestamp";
|
||||||
|
public static final String CDS_HOOKS_EXTENSION_VALUE_PRACTITIONER_SPECIALITY = "some-speciality";
|
||||||
|
|
||||||
private final PointcutLatch myPointcutLatch = new PointcutLatch("Hello World CDS-Hook");
|
private final PointcutLatch myPointcutLatch = new PointcutLatch("Hello World CDS-Hook");
|
||||||
|
|
||||||
|
@ -31,23 +44,26 @@ public class HelloWorldService implements IPointcutLatch {
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
||||||
})
|
})
|
||||||
public String helloWorld(String theJson) {
|
public CdsServiceResponseJson helloWorld(String theJson) {
|
||||||
return "{\n" +
|
final CdsServiceResponseJson cdsServiceResponseJson = new CdsServiceResponseJson();
|
||||||
" \"cards\" : [ {\n" +
|
final CdsServiceResponseCardJson cdsServiceResponseCardJson = new CdsServiceResponseCardJson();
|
||||||
" \"summary\" : \"Hello World!\",\n" +
|
cdsServiceResponseCardJson.setSummary("Hello World!");
|
||||||
" \"indicator\" : \"warning\",\n" +
|
cdsServiceResponseCardJson.setIndicator(CdsServiceIndicatorEnum.WARNING);
|
||||||
" \"source\" : {\n" +
|
cdsServiceResponseCardJson.setDetail("This is a test. Do not be alarmed.");
|
||||||
" \"label\" : \"World Greeter\"\n" +
|
cdsServiceResponseCardJson.setSource(new CdsServiceResponseCardSourceJson().setLabel("World Greeter"));
|
||||||
" },\n" +
|
final ResponseExtension extension = new ResponseExtension();
|
||||||
" \"detail\" : \"This is a test. Do not be alarmed.\"\n" +
|
extension.setTimestamp(new Date());
|
||||||
" } ]\n" +
|
extension.setPractitionerSpecialty(CDS_HOOKS_EXTENSION_VALUE_PRACTITIONER_SPECIALITY);
|
||||||
"}";
|
cdsServiceResponseCardJson.setExtension(extension);
|
||||||
|
cdsServiceResponseJson.addCard(cdsServiceResponseCardJson);
|
||||||
|
return cdsServiceResponseJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CdsServiceFeedback(TEST_HOOK_WORLD_ID)
|
@CdsServiceFeedback(TEST_HOOK_WORLD_ID)
|
||||||
public String feedback(CdsServiceFeedbackJson theFeedback) {
|
public CdsServiceFeedbackJson feedback(CdsServiceFeedbackJson theFeedback) {
|
||||||
myPointcutLatch.call(theFeedback);
|
myPointcutLatch.call(theFeedback);
|
||||||
return "{\"message\": \"Thank you for your feedback dated " + theFeedback.getOutcomeTimestamp() + "!\"}";
|
theFeedback.setAcceptedSuggestions(List.of(new CdsServiceAcceptedSuggestionJson().setId(UUID.randomUUID().toString())));
|
||||||
|
return theFeedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CdsService(value = TEST_HOOK_UNIVERSE_ID,
|
@CdsService(value = TEST_HOOK_UNIVERSE_ID,
|
||||||
|
@ -57,18 +73,23 @@ public class HelloWorldService implements IPointcutLatch {
|
||||||
prefetch = {
|
prefetch = {
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
||||||
})
|
},
|
||||||
public String helloUniverse(String theJson) {
|
extension = """
|
||||||
return "{\n" +
|
{
|
||||||
" \"cards\" : [ {\n" +
|
"example-config-item": "example-value"
|
||||||
" \"summary\" : \"Hello Universe!\",\n" +
|
}
|
||||||
" \"indicator\" : \"critical\",\n" +
|
""",
|
||||||
" \"source\" : {\n" +
|
extensionClass = RequestExtension.class)
|
||||||
" \"label\" : \"World Greeter\"\n" +
|
public CdsServiceResponseJson helloUniverse(CdsServiceRequestJson theCdsServiceRequestJson) {
|
||||||
" },\n" +
|
final CdsServiceResponseJson cdsServiceResponseJson = new CdsServiceResponseJson();
|
||||||
" \"detail\" : \"This is a test. Do not be alarmed.\"\n" +
|
final CdsServiceResponseCardJson cdsServiceResponseCardJson = new CdsServiceResponseCardJson();
|
||||||
" } ]\n" +
|
cdsServiceResponseCardJson.setSummary("Hello Universe!");
|
||||||
"}";
|
cdsServiceResponseCardJson.setIndicator(CdsServiceIndicatorEnum.CRITICAL);
|
||||||
|
cdsServiceResponseCardJson.setDetail("This is a test. Do not be alarmed.");
|
||||||
|
cdsServiceResponseCardJson.setSource(new CdsServiceResponseCardSourceJson().setLabel("World Greeter"));
|
||||||
|
cdsServiceResponseCardJson.setExtension(theCdsServiceRequestJson.getExtension());
|
||||||
|
cdsServiceResponseJson.addCard(cdsServiceResponseCardJson);
|
||||||
|
return cdsServiceResponseJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CdsService(value = TEST_HOOK_PLAYBACK_ID,
|
@CdsService(value = TEST_HOOK_PLAYBACK_ID,
|
||||||
|
@ -78,21 +99,24 @@ public class HelloWorldService implements IPointcutLatch {
|
||||||
prefetch = {
|
prefetch = {
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_PATIENT_KEY, query = "Patient/{{context.patientId}}"),
|
||||||
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
@CdsServicePrefetch(value = TEST_HOOK_PREFETCH_MEDS_KEY, query = "MedicationRequest?patient={{context.patientId}}")
|
||||||
})
|
},
|
||||||
public String playback(CdsServiceRequestJson theCdsServiceRequestJson) {
|
extension = """
|
||||||
return "{\n" +
|
{
|
||||||
" \"cards\" : [ {\n" +
|
"example-client-conformance": "http://hooks.example.org/fhir/102/Conformance/patientview"
|
||||||
" \"summary\" : \"FhirServer: " + theCdsServiceRequestJson.getFhirServer() +
|
}
|
||||||
|
""",
|
||||||
|
extensionClass = ExampleConfigExtension.class)
|
||||||
|
public CdsServiceResponseJson playback(CdsServiceRequestJson theCdsServiceRequestJson) {
|
||||||
|
final CdsServiceResponseJson cdsServiceResponseJson = new CdsServiceResponseJson();
|
||||||
|
final CdsServiceResponseCardJson cdsServiceResponseCardJson = new CdsServiceResponseCardJson();
|
||||||
|
cdsServiceResponseCardJson.setSummary("FhirServer: " + theCdsServiceRequestJson.getFhirServer() +
|
||||||
" Hook: " + theCdsServiceRequestJson.getHook() +
|
" Hook: " + theCdsServiceRequestJson.getHook() +
|
||||||
" Hook Instance: " + theCdsServiceRequestJson.getHookInstance() +
|
" Hook Instance: " + theCdsServiceRequestJson.getHookInstance());
|
||||||
"\",\n" +
|
cdsServiceResponseCardJson.setIndicator(CdsServiceIndicatorEnum.CRITICAL);
|
||||||
" \"indicator\" : \"critical\",\n" +
|
cdsServiceResponseCardJson.setDetail("This is a test. Do not be alarmed.");
|
||||||
" \"source\" : {\n" +
|
cdsServiceResponseCardJson.setSource(new CdsServiceResponseCardSourceJson().setLabel("World Greeter"));
|
||||||
" \"label\" : \"World Greeter\"\n" +
|
cdsServiceResponseJson.addCard(cdsServiceResponseCardJson);
|
||||||
" },\n" +
|
return cdsServiceResponseJson;
|
||||||
" \"detail\" : \"This is a test. Do not be alarmed.\"\n" +
|
|
||||||
" } ]\n" +
|
|
||||||
"}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.custom.extensions.model;
|
||||||
|
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class ExampleConfigExtension extends CdsHooksExtension {
|
||||||
|
@JsonProperty("example-client-conformance")
|
||||||
|
String myExampleClientConformance;
|
||||||
|
|
||||||
|
public String getExampleClientConformance() {
|
||||||
|
return myExampleClientConformance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.custom.extensions.model;
|
||||||
|
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class ExampleExtension extends CdsHooksExtension {
|
||||||
|
@JsonProperty("example-property")
|
||||||
|
String myExampleProperty;
|
||||||
|
|
||||||
|
public String getExampleProperty() {
|
||||||
|
return myExampleProperty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.custom.extensions.model;
|
||||||
|
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
|
||||||
|
public class RequestExtension extends CdsHooksExtension {
|
||||||
|
@JsonProperty("example-config-item")
|
||||||
|
String myConfigItem;
|
||||||
|
|
||||||
|
public String getConfigItem() {
|
||||||
|
return myConfigItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigItem(String theConfigItem) {
|
||||||
|
myConfigItem = theConfigItem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.custom.extensions.model;
|
||||||
|
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class ResponseExtension extends CdsHooksExtension {
|
||||||
|
@JsonProperty(value = "timestamp", required = true)
|
||||||
|
private Date myDate;
|
||||||
|
@JsonProperty(value = "myextension-practitionerspecialty", required = true)
|
||||||
|
private String myPractitionerSpecialty;
|
||||||
|
|
||||||
|
public void setTimestamp(Date theDate) {
|
||||||
|
myDate = theDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPractitionerSpecialty(String thePractitionerSpecialty) {
|
||||||
|
myPractitionerSpecialty = thePractitionerSpecialty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.serializer;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestContextJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.ExampleExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.CdsServiceRegistryImpl;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class CdsServiceRequestJsonDeserializerTest {
|
||||||
|
@Mock
|
||||||
|
private CdsServiceRegistryImpl myCdsServiceRegistry;
|
||||||
|
private final FhirContext myFhirContext = FhirContext.forR4();
|
||||||
|
private CdsServiceRequestJsonDeserializer myFixture;
|
||||||
|
|
||||||
|
@BeforeEach()
|
||||||
|
void setup() {
|
||||||
|
myFixture = new CdsServiceRequestJsonDeserializer(myCdsServiceRegistry, myFhirContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void configureObjectMapper() {
|
||||||
|
// setup
|
||||||
|
ObjectMapper input = new ObjectMapper();
|
||||||
|
// execute
|
||||||
|
myFixture.configureObjectMapper(input);
|
||||||
|
// validate
|
||||||
|
assertThat(input.getRegisteredModuleIds()).hasSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deserializeExtensionWhenClassFoundShouldDeserializeExtension() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String serviceId = "service-id";
|
||||||
|
final String extension = """
|
||||||
|
{
|
||||||
|
"example-property": "example-value"
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final CdsServiceJson cdsServiceJson = new CdsServiceJson();
|
||||||
|
cdsServiceJson.setId(serviceId);
|
||||||
|
cdsServiceJson.setExtensionClass(ExampleExtension.class);
|
||||||
|
doReturn(cdsServiceJson).when(myCdsServiceRegistry).getCdsServiceJson(serviceId);
|
||||||
|
// execute
|
||||||
|
final ExampleExtension actual = (ExampleExtension) myFixture.deserializeExtension(serviceId, extension);
|
||||||
|
// validate
|
||||||
|
assertThat(actual.getExampleProperty()).isEqualTo("example-value");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deserializeExtensionWhenClassFoundButExtensionHasExtraPropertiesShouldIgnoreExtraProperties() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String serviceId = "service-id";
|
||||||
|
final String extension = """
|
||||||
|
{
|
||||||
|
"example-property": "example-value",
|
||||||
|
"example-extra-property": "example-extra-value"
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final CdsServiceJson cdsServiceJson = new CdsServiceJson();
|
||||||
|
cdsServiceJson.setId(serviceId);
|
||||||
|
cdsServiceJson.setExtensionClass(ExampleExtension.class);
|
||||||
|
doReturn(cdsServiceJson).when(myCdsServiceRegistry).getCdsServiceJson(serviceId);
|
||||||
|
// execute
|
||||||
|
final ExampleExtension actual = (ExampleExtension) myFixture.deserializeExtension(serviceId, extension);
|
||||||
|
// validate
|
||||||
|
assertThat(actual.getExampleProperty()).isEqualTo("example-value");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deserializeExtensionWhenNotClassFoundShouldReturnNull() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String serviceId = "service-id";
|
||||||
|
final String extension = """
|
||||||
|
{
|
||||||
|
"example-property": "example-value"
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final CdsServiceJson cdsServiceJson = new CdsServiceJson();
|
||||||
|
cdsServiceJson.setId(serviceId);
|
||||||
|
doReturn(cdsServiceJson).when(myCdsServiceRegistry).getCdsServiceJson(serviceId);
|
||||||
|
// execute
|
||||||
|
final CdsHooksExtension actual = myFixture.deserializeExtension(serviceId, extension);
|
||||||
|
// validate
|
||||||
|
assertThat(actual).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deserializeRequestContextShouldDeserializeValidContext() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String encounterId = "123";
|
||||||
|
final Patient patientContext = new Patient();
|
||||||
|
patientContext.setId("456");
|
||||||
|
final LinkedHashMap<String, Object> input = new LinkedHashMap<>();
|
||||||
|
input.put("encounterId", encounterId);
|
||||||
|
input.put("patient", patientContext);
|
||||||
|
// execute
|
||||||
|
final CdsServiceRequestContextJson actual = myFixture.deserializeRequestContext(input);
|
||||||
|
// validate
|
||||||
|
assertThat(actual.get("encounterId")).isEqualTo(encounterId);
|
||||||
|
assertThat(actual.get("patient")).usingRecursiveComparison().isEqualTo(patientContext);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
package ca.uhn.hapi.fhir.cdshooks.svc;
|
package ca.uhn.hapi.fhir.cdshooks.svc;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsHooksExtension;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.custom.extensions.model.ExampleExtension;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
|
|
||||||
class CdsHooksContextBooterTest {
|
class CdsHooksContextBooterTest {
|
||||||
|
|
||||||
|
@ -16,35 +17,34 @@ class CdsHooksContextBooterTest {
|
||||||
void setUp() {
|
void setUp() {
|
||||||
myFixture = new CdsHooksContextBooter();
|
myFixture = new CdsHooksContextBooter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateJsonReturnsNullWhenInputIsEmptyString() {
|
void serializeExtensionsReturnsNullWhenInputIsEmptyString() {
|
||||||
// execute
|
// execute
|
||||||
final String actual = myFixture.validateJson("");
|
final CdsHooksExtension actual = myFixture.serializeExtensions("", ExampleExtension.class);
|
||||||
// validate
|
// validate
|
||||||
assertNull(actual);
|
assertThat(actual).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateJsonThrowsExceptionWhenInputIsInvalid() {
|
void serializeExtensionsThrowsExceptionWhenInputIsInvalid() {
|
||||||
// setup
|
// setup
|
||||||
final String expected = "HAPI-2378: Invalid JSON: Unrecognized token 'abc': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n" +
|
final String expected = "HAPI-2378: Invalid JSON: Unrecognized token 'abc': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n" +
|
||||||
" at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 4]";
|
" at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 4]";
|
||||||
// execute
|
// execute & validate
|
||||||
final UnprocessableEntityException actual = assertThrows(UnprocessableEntityException.class, () -> myFixture.validateJson("abc"));
|
assertThatThrownBy(
|
||||||
// validate
|
() -> myFixture.serializeExtensions("abc", ExampleExtension.class))
|
||||||
assertEquals(expected, actual.getMessage());
|
.isInstanceOf(UnprocessableEntityException.class)
|
||||||
|
.hasMessage(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateJsonReturnsInputWhenInputIsValidJsonString() {
|
void serializeExtensionsReturnsInputWhenInputIsValidJsonString() {
|
||||||
// setup
|
// setup
|
||||||
final String expected = "{\n \"com.example.timestamp\": \"2017-11-27T22:13:25Z\",\n \"myextension-practitionerspecialty\" : \"gastroenterology\"\n }";
|
final String input = "{\n\"example-property\": \"some-value\" }";
|
||||||
// execute
|
// execute
|
||||||
final String actual = myFixture.validateJson(expected);
|
final ExampleExtension actual = (ExampleExtension) myFixture.serializeExtensions(input, ExampleExtension.class);
|
||||||
// validate
|
// validate
|
||||||
assertEquals(expected, actual);
|
assertThat(actual.getExampleProperty()).isEqualTo("some-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
package ca.uhn.hapi.fhir.cdshooks.svc;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchSvc;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class CdsServiceRegistryImplTest {
|
||||||
|
private static final String SERVICE_ID = "service-id";
|
||||||
|
@Mock
|
||||||
|
private CdsHooksContextBooter myCdsHooksContextBooter;
|
||||||
|
@Mock
|
||||||
|
private CdsPrefetchSvc myCdsPrefetchSvc;
|
||||||
|
@Mock
|
||||||
|
private ICdsCrServiceFactory myCdsCrServiceFactory;
|
||||||
|
@Mock
|
||||||
|
private ICrDiscoveryServiceFactory myCrDiscoveryServiceFactory;
|
||||||
|
@Mock
|
||||||
|
private CdsServiceCache myCdsServiceCache;
|
||||||
|
private final ObjectMapper myObjectMapper = new ObjectMapper();
|
||||||
|
private final FhirContext myFhirContext = FhirContext.forR4();
|
||||||
|
private CdsServiceRegistryImpl myFixture;
|
||||||
|
|
||||||
|
@BeforeEach()
|
||||||
|
void setup() {
|
||||||
|
myFixture = new CdsServiceRegistryImpl(myCdsHooksContextBooter, myCdsPrefetchSvc, myObjectMapper, myCdsCrServiceFactory, myCrDiscoveryServiceFactory, myFhirContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeFeedbackResponseWhenResponseIsString() {
|
||||||
|
// setup
|
||||||
|
final String expectedCardText = "some-card";
|
||||||
|
final String input = """
|
||||||
|
{
|
||||||
|
"card": "some-card"
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
// execute
|
||||||
|
final CdsServiceFeedbackJson actual = myFixture.encodeFeedbackResponse(SERVICE_ID, input);
|
||||||
|
// validate
|
||||||
|
assertThat(actual.getCard()).isEqualTo(expectedCardText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeFeedbackResponseWhenResponseIsCdsServiceFeedbackJson() {
|
||||||
|
// setup
|
||||||
|
final CdsServiceFeedbackJson expected = new CdsServiceFeedbackJson();
|
||||||
|
expected.setCard("some-card");
|
||||||
|
// execute
|
||||||
|
final CdsServiceFeedbackJson actual = myFixture.encodeFeedbackResponse(SERVICE_ID, expected);
|
||||||
|
// validate
|
||||||
|
assertThat(actual).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeFeedbackResponseWhenResponseIsInvalidString() {
|
||||||
|
// setup
|
||||||
|
final String invalidString = "some-invalid-feedback";
|
||||||
|
// execute & validate
|
||||||
|
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
|
||||||
|
myFixture.encodeFeedbackResponse(SERVICE_ID, invalidString);
|
||||||
|
}).withMessageContaining("HAPI-2538: Failed to serialize json Cds Feedback response for service service-id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeFeedbackResponseWhenResponseIsInvalidObject() {
|
||||||
|
// setup
|
||||||
|
final CdsServiceResponseJson invalidObject = new CdsServiceResponseJson();
|
||||||
|
// execute & validate
|
||||||
|
assertThatExceptionOfType(ClassCastException.class).isThrownBy(() -> {
|
||||||
|
myFixture.encodeFeedbackResponse(SERVICE_ID, invalidObject);
|
||||||
|
}).withMessageContaining("HAPI-2537: Failed to cast feedback response CdsServiceFeedbackJson for service service-id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeServiceResponseWhenResponseIsString() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String input = """
|
||||||
|
{
|
||||||
|
"cards": [
|
||||||
|
{
|
||||||
|
"summary": "some-summary",
|
||||||
|
"indicator": "info",
|
||||||
|
"source": {
|
||||||
|
"label": "some-label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
// execute
|
||||||
|
final CdsServiceResponseJson actual = myFixture.encodeServiceResponse(SERVICE_ID, input);
|
||||||
|
// validate
|
||||||
|
assertThat(actual).usingRecursiveComparison().isEqualTo(myObjectMapper.readValue(input, CdsServiceResponseJson.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeServiceResponseWhenResponseCdsServiceResponseJson() throws JsonProcessingException {
|
||||||
|
// setup
|
||||||
|
final String input = """
|
||||||
|
{
|
||||||
|
"cards": [
|
||||||
|
{
|
||||||
|
"summary": "some-summary",
|
||||||
|
"indicator": "info",
|
||||||
|
"source": {
|
||||||
|
"label": "some-label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
// execute
|
||||||
|
final CdsServiceResponseJson actual = myFixture.encodeServiceResponse(SERVICE_ID, myObjectMapper.readValue(input, CdsServiceResponseJson.class));
|
||||||
|
// validate
|
||||||
|
assertThat(actual).usingRecursiveComparison().isEqualTo(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeServiceResponseWhenResponseIsInvalidString() {
|
||||||
|
// setup
|
||||||
|
final String invalidString = "some-string";
|
||||||
|
// execute & validate
|
||||||
|
assertThatExceptionOfType(ConfigurationException.class).isThrownBy(() -> {
|
||||||
|
myFixture.encodeServiceResponse(SERVICE_ID, invalidString);
|
||||||
|
}).withMessageContaining("Failed to json deserialize Cds service response of type java.lang.String when calling CDS Hook Service service-id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void encodeServiceResponseWhenResponseIsInvalidObject() {
|
||||||
|
// setup
|
||||||
|
final CdsServiceFeedbackJson invalidObject = new CdsServiceFeedbackJson();
|
||||||
|
// execute & validate
|
||||||
|
assertThatExceptionOfType(ConfigurationException.class).isThrownBy(() -> {
|
||||||
|
myFixture.encodeServiceResponse(SERVICE_ID, invalidObject);
|
||||||
|
}).withMessageContaining("Failed to cast Cds service response to CdsServiceResponseJson when calling CDS Hook Service service-id. The type ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceFeedbackJson cannot be casted to CdsServiceResponseJson");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCdsServiceJsonWhenServicePresent() {
|
||||||
|
// setup
|
||||||
|
final CdsServiceJson cdsService = new CdsServiceJson();
|
||||||
|
cdsService.setId(SERVICE_ID);
|
||||||
|
myFixture.setServiceCache(myCdsServiceCache);
|
||||||
|
doReturn(cdsService).when(myCdsServiceCache).getCdsServiceJson(SERVICE_ID);
|
||||||
|
// execute
|
||||||
|
final CdsServiceJson actual = myFixture.getCdsServiceJson(SERVICE_ID);
|
||||||
|
// validate
|
||||||
|
assertThat(actual).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCdsServiceJsonWhenServiceIsNotPresent() {
|
||||||
|
// setup
|
||||||
|
final String serviceId = "non-existent-serviceid";
|
||||||
|
myFixture.setServiceCache(myCdsServiceCache);
|
||||||
|
doReturn(null).when(myCdsServiceCache).getCdsServiceJson(serviceId);
|
||||||
|
// execute & validate
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> {
|
||||||
|
myFixture.getCdsServiceJson(serviceId);
|
||||||
|
}).withMessage("HAPI-2536: No service with " + serviceId + " is registered.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ public class CdsCrServiceR4Test extends BaseCrTest {
|
||||||
requestDetails.setId(planDefinitionId);
|
requestDetails.setId(planDefinitionId);
|
||||||
final Parameters params = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeParams(cdsServiceRequestJson);
|
final Parameters params = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeParams(cdsServiceRequestJson);
|
||||||
|
|
||||||
assertTrue(params.getParameter().size() == 2);
|
assertEquals(2, params.getParameter().size());
|
||||||
assertTrue(params.getParameter("parameters").hasResource());
|
assertTrue(params.getParameter("parameters").hasResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +63,9 @@ public class CdsCrServiceR4Test extends BaseCrTest {
|
||||||
requestDetails.setId(planDefinitionId);
|
requestDetails.setId(planDefinitionId);
|
||||||
final CdsServiceResponseJson cdsServiceResponseJson = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeResponse(responseBundle);
|
final CdsServiceResponseJson cdsServiceResponseJson = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeResponse(responseBundle);
|
||||||
|
|
||||||
assertTrue(cdsServiceResponseJson.getCards().size() == 1);
|
assertEquals(1, cdsServiceResponseJson.getCards().size());
|
||||||
assertTrue(!cdsServiceResponseJson.getCards().get(0).getSummary().isEmpty());
|
assertFalse(cdsServiceResponseJson.getCards().get(0).getSummary().isEmpty());
|
||||||
assertTrue(!cdsServiceResponseJson.getCards().get(0).getDetail().isEmpty());
|
assertFalse(cdsServiceResponseJson.getCards().get(0).getDetail().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -78,7 +79,7 @@ public class CdsCrServiceR4Test extends BaseCrTest {
|
||||||
requestDetails.setId(planDefinitionId);
|
requestDetails.setId(planDefinitionId);
|
||||||
final CdsServiceResponseJson cdsServiceResponseJson = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeResponse(responseBundle);
|
final CdsServiceResponseJson cdsServiceResponseJson = new CdsCrServiceR4(requestDetails, repository, myCdsConfigService).encodeResponse(responseBundle);
|
||||||
|
|
||||||
assertTrue(cdsServiceResponseJson.getServiceActions().size() == 1);
|
assertEquals(1, cdsServiceResponseJson.getServiceActions().size());
|
||||||
assertEquals(ActionType.CREATE, cdsServiceResponseJson.getServiceActions().get(0).getType());
|
assertEquals(ActionType.CREATE, cdsServiceResponseJson.getServiceActions().get(0).getType());
|
||||||
assertNotNull(cdsServiceResponseJson.getServiceActions().get(0).getResource());
|
assertNotNull(cdsServiceResponseJson.getServiceActions().get(0).getResource());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -8,7 +8,7 @@
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<name>HAPI-FHIR</name>
|
<name>HAPI-FHIR</name>
|
||||||
<description>An open-source implementation of the FHIR specification in Java.</description>
|
<description>An open-source implementation of the FHIR specification in Java.</description>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>7.3.8-SNAPSHOT</version>
|
<version>7.3.9-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
Loading…
Reference in New Issue