From d3367cfede4a990e636dffb5882caeed51872035 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 7 Nov 2022 18:57:57 -0500 Subject: [PATCH] Rel 6 2 mergeback (#4257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * jm wrong bundle entry url (#4213) * Bug test * here you go * Generate relative URIs for bundle entry.request.url, as specified * Point jira issue in changelog * Adjust tests to fixes Co-authored-by: juan.marchionatto Co-authored-by: Tadgh * improved logging (#4217) Co-authored-by: Ken Stevens * Rel 6 1 3 mergeback (#4215) * Bump for CVE (#3856) * Bump for CVE * Bump spring-data version * Fix compile * Cut over to spring bom * Bump to RC1 * remove RC * do not contrain reindex for common SP updates (#3876) * only fast-track jobs with exactly one chunk (#3879) * Fix illegalstateexception when an exception is thrown during stream response (#3882) * Finish up changelog, minor refactor * reset buffer only * Hack for some replacements * Failure handling * wip * Fixed the issue (#3845) * Fixed the issue * Changelog modification * Changelog modification * Implemented seventh character extended code and the corresponding dis… (#3709) * Implemented seventh character extended code and the corresponding display * Modifications * Changes on previous test according to modifications made in ICD10-CM XML file * Subscription sending delete events being skipped (#3888) * fixed bug and added test * refactor * Update for CVE (#3895) * updated pointcuts to work as intended (#3903) * updated pointcuts to work as intended * added changelog * review fixes Co-authored-by: leif stawnyczy * 3904 during $delete expunge job hibernate search indexed documents are left orphaned (#3905) * Add test and implementation * Add changelog * 3899 code in limits (#3901) * Add implementation, changelog, test * Update hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java Co-authored-by: Ken Stevens Co-authored-by: Ken Stevens * 3884 overlapping searchparameter undetected rel 6 1 (#3909) * Applying all changes from previous dev branch to current one pointing to rel_6_1 * Fixing merge conflict related to Msg.code value. * Fixing Msg.code value. * Making checkstyle happy. * Making sure that all tests are passing. * Passing all tests after fixing Msg.code * Passing all tests. Co-authored-by: peartree * 3745 - fixed NPE for bundle with duplicate conditional create resourc… (#3746) * 3745 - fixed NPE for bundle with duplicate conditional create resources and a conditional delete * created unit test for skip of delete operation while processing duplicating create entries * moved unit test to FhirSystemDaoR4Test * 3379 mdm fixes (#3906) * added MdmLinkCreateSvcimplTest * fixed creating mdm-link not setting the resource type correctly * fixed a bug where ResourcePersistenceId was being duplicated instead of passed on * Update hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkCreateSvcImplTest.java Change order of tests such that assertEquals takes expected value then actual value Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com> * added changelog, also changed a setup function in test to beforeeach Co-authored-by: Long Ma Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com> * Fix to the issue (#3855) * Fix to the issue * Progress * fixed the issue * Addressing suggestions * add response status code to MethodOutcome * Addressing suggestions Co-authored-by: Ken Stevens * Fix for caching appearing broken in batch2 for bulkexport jobs (#3912) * Respect caching in bullk export, fix bug with completed date on empty jobs * add changelog * Add impl * Add breaking test * Complete failing test * more broken tests * Fix more tests' * Fix paging bug * Fix another brittle test * 3915 do not collapse rules with filters (#3916) * do not attempt to merge compartment permissions with filters * changelog * Rename to IT for concurrency problems Co-authored-by: Tadgh * Version bump * fix $mdm-submit output (#3917) Co-authored-by: Ken Stevens * Gl3407 bundle offset size (#3918) * begin with failing test * fixed * change log * rollback default count change and corresponding comments Co-authored-by: Ken Stevens * Offset interceptor now only works for external calls * Initialize some beans (esp interceptors) later in the boot process so they don't slow down startup. * do not reindex searchparam jobs on startup * Fix oracle non-enterprise attempting online index add (#3925) * 3922 delete expunge large dataset (#3923) * lower batchsize of delete requests so that we do not get sql exceptions * blah * fix test * updated tests to not fail Co-authored-by: leif stawnyczy * add index * Fix up colun grab * Revert offset mode change * Revert fix for null/system request details checks for reindex purposes * Fix bug and add test for SP Validating Interceptor (#3930) * wip * Fix uptests * Fix index online test * Fix SP validating interceptor logic * Updating version to: 6.1.1 post release. * fix compile error * Deploy to sonatype (#3934) * adding sonatype profile to checkstyle module * adding sonatype profile to tinder module * adding sonatype profile to base pom * adding final deployToSonatype profile * wip * Revert version enum * Updating version to: 6.1.1 post release. * Add test, changelog, and implementation * Add backport info * Create failing test * Implemented the fix, fixed existing unit tests * added changelog * added test case for no filter, exclude 1 patient * wip * Add backport info * Add info of new version * Updating version to: 6.1.2 post release. * bump info and backport for 6.1.2 * Bump for hapi * Implement bug fixes, add new tests (#4022) * Implement bug fixes, add new tests * tidy * Tidy * refactor for cleaning * More tidying * Lower logging * Split into nested tests, rename, add todos * Typo * Code review * add backport info * Updating version to: 6.1.3 post release. * Updating version to: 6.1.3 post release. * removed duplicate mention of ver 6.1.3 in versionEnum * backport pr 4101 * mdm message key (#4111) * begin with failing test * fixed 2 tests * fix tests * fix tests * change log Co-authored-by: Ken Stevens * backport 6.1.3 docs changes * fixed typo on doc backport message * fix test breaking * Updating version to: 6.1.4 post release. * wip Co-authored-by: JasonRoberts-smile <85363818+JasonRoberts-smile@users.noreply.github.com> Co-authored-by: Qingyixia <106992634+Qingyixia@users.noreply.github.com> Co-authored-by: TipzCM Co-authored-by: leif stawnyczy Co-authored-by: Ken Stevens Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com> Co-authored-by: peartree Co-authored-by: kateryna-mironova <107507153+kateryna-mironova@users.noreply.github.com> Co-authored-by: longma1 <32119004+longma1@users.noreply.github.com> Co-authored-by: Long Ma Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com> Co-authored-by: Ken Stevens Co-authored-by: markiantorno Co-authored-by: Steven Li * pin okio-jvm for kotlin vuln (#4216) * Fix UrlUtil.unescape() by not escaping "+" to " " if this is an "application/..." _outputFormat. (#4220) * First commit: Failing unit test and a TODO with a vague idea of where the bug happens. * Don't escape "+" in a URL GET parameter if it starts with "application". * Remove unnecessary TODO. * Add changelog. * Code review feedback on naming. Also, make logic more robust by putting plus and should escape boolean && in parens. * Ks 20221031 migration lock (#4224) * started design * complete with tests * changelog * cleanup * tyop Co-authored-by: Ken Stevens * 4207-getpagesoffset-set-to-total-number-of-resources-results-in-inconsistent-amount-of-entries-when-requests-are-sent-consecutively (#4209) * Added test * Added solution * Changelog * Changes made based on comments * Fix bug with MDM submit * fix * Version bump * 4234 consent in conjunction with versionedapiconverterinterceptor fails (#4236) * Add constant for interceptor * add test, changelog * Allow Batch2 transition from ERRORED to COMPLETE (#4242) * Allow Batch2 transition from ERRORED to COMPLETE * Add changelog * Test fix Co-authored-by: James Agnew * 3685 When bulk exporting, if no resource type param is provided, defa… (#4233) * 3685 When bulk exporting, if no resource type param is provided, default to all registered types. * Update test case. * Cleaned up changelog. * Added test case for multiple resource types. * Added failing test case for not returning Binary resource. * Refactor solution. Co-authored-by: kylejule * Add next version * bulk export permanently reusing cached results (#4249) * Add test, fix bug, add changelog * minor refactor * Fix * Bump HAPI version * Remove jetbrains * Fix broken test Co-authored-by: jmarchionatto <60409882+jmarchionatto@users.noreply.github.com> Co-authored-by: juan.marchionatto Co-authored-by: Ken Stevens Co-authored-by: Ken Stevens Co-authored-by: JasonRoberts-smile <85363818+JasonRoberts-smile@users.noreply.github.com> Co-authored-by: Qingyixia <106992634+Qingyixia@users.noreply.github.com> Co-authored-by: TipzCM Co-authored-by: leif stawnyczy Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com> Co-authored-by: peartree Co-authored-by: kateryna-mironova <107507153+kateryna-mironova@users.noreply.github.com> Co-authored-by: longma1 <32119004+longma1@users.noreply.github.com> Co-authored-by: Long Ma Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com> Co-authored-by: markiantorno Co-authored-by: Steven Li Co-authored-by: Luke deGruchy Co-authored-by: karneet1212 <112980019+karneet1212@users.noreply.github.com> Co-authored-by: James Agnew Co-authored-by: James Agnew Co-authored-by: KGJ-software <39975592+KGJ-software@users.noreply.github.com> Co-authored-by: kylejule --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- .../java/ca/uhn/fhir/context/FhirContext.java | 1 - .../main/java/ca/uhn/fhir/util/UrlUtil.java | 5 +- .../java/ca/uhn/fhir/util/VersionEnum.java | 4 +- .../java/ca/uhn/fhir/util/UrlUtilTest.java | 16 ++ hapi-fhir-batch/pom.xml | 2 +- hapi-fhir-bom/pom.xml | 4 +- hapi-fhir-checkstyle/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-api/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- .../fhir/rest/client/impl/GenericClient.java | 1 - hapi-fhir-converter/pom.xml | 2 +- .../VersionedApiConverterInterceptor.java | 4 + hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 2 +- .../uhn/hapi/fhir/changelog/6_1_3/upgrade.md | 0 .../hapi/fhir/changelog/6_1_3/version.yaml | 3 + .../changelog/6_2_0/4111-mdm-message-key.yaml | 1 + ...-when-requests-are-sent-consecutively.yaml | 6 + ...undle-entry-uri-in-transaction-bundle.yaml | 5 + ...tput-format-param-string-escape-issue.yaml | 4 + .../6_2_0/4224-migration-lock-clear.yaml | 4 + ...bulk-to-all-registered-resource-types.yaml | 4 + .../6_2_0/4234-consent-with-convert.yaml | 6 + .../6_2_0/4247-bulk-export-job-reuse.yaml | 4 + .../hapi/fhir/changelog/6_2_0/version.yaml | 2 +- .../hapi/fhir/changelog/6_3_0/version.yaml | 2 +- hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jpa/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- .../jpa/batch2/JpaJobPersistenceImpl.java | 1 + .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 1 + hapi-fhir-jpaserver-cql/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-jpaserver-mdm/pom.xml | 2 +- hapi-fhir-jpaserver-model/pom.xml | 2 +- hapi-fhir-jpaserver-searchparam/pom.xml | 2 +- hapi-fhir-jpaserver-subscription/pom.xml | 2 +- hapi-fhir-jpaserver-test-dstu2/pom.xml | 2 +- ...ceDaoDstu2SearchCustomSearchParamTest.java | 1 + hapi-fhir-jpaserver-test-dstu3/pom.xml | 2 +- .../ResourceProviderDstu3BundleTest.java | 26 ++- .../dstu3/ResourceProviderDstu3Test.java | 6 +- hapi-fhir-jpaserver-test-r4/pom.xml | 2 +- .../jpa/bulk/BulkDataExportProviderTest.java | 56 +++++- .../fhir/jpa/bulk/BulkExportUseCaseTest.java | 177 +++++++++++++++++- .../jpa/dao/BaseHapiFhirResourceDaoTest.java | 2 + ...sentInterceptorResourceProviderR4Test.java | 16 ++ .../r4/ResourceProviderR4BundleTest.java | 22 +++ .../provider/r4/ResourceProviderR4Test.java | 8 +- hapi-fhir-jpaserver-test-r4b/pom.xml | 2 +- .../provider/r4b/ResourceProviderR4BTest.java | 27 ++- hapi-fhir-jpaserver-test-r5/pom.xml | 2 +- .../provider/r5/ResourceProviderR5Test.java | 22 +++ hapi-fhir-jpaserver-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 2 +- hapi-fhir-server-mdm/pom.xml | 2 +- hapi-fhir-server-openapi/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- .../auth/AuthorizationConstants.java | 1 + .../BaseResourceReturningMethodBinding.java | 12 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-sql-migrate/pom.xml | 2 +- .../fhir/jpa/migrate/HapiMigrationLock.java | 58 +++++- .../jpa/migrate/HapiMigrationStorageSvc.java | 11 +- .../uhn/fhir/jpa/migrate/HapiMigratorIT.java | 84 ++++++++- hapi-fhir-storage-batch2-jobs/pom.xml | 2 +- .../BulkExportJobParametersValidator.java | 7 +- .../jobs/export/FetchResourceIdsStep.java | 1 + .../BulkExportJobParametersValidatorTest.java | 5 +- hapi-fhir-storage-batch2/pom.xml | 2 +- .../coordinator/JobCoordinatorImpl.java | 14 +- .../coordinator/JobCoordinatorImplTest.java | 20 +- hapi-fhir-storage-mdm/pom.xml | 2 +- .../uhn/fhir/mdm/batch2/MdmBatch2Config.java | 2 +- hapi-fhir-storage-test-utilities/pom.xml | 2 +- hapi-fhir-storage/pom.xml | 2 +- .../provider/BulkDataExportProvider.java | 17 ++ hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- .../hapi/rest/server/Dstu3BundleFactory.java | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- .../r4/hapi/rest/server/R4BundleFactory.java | 2 +- .../ca/uhn/fhir/rest/server/PagingTest.java | 31 +++ hapi-fhir-structures-r4b/pom.xml | 2 +- .../hapi/rest/server/R4BBundleFactory.java | 2 +- hapi-fhir-structures-r5/pom.xml | 2 +- .../r5/hapi/rest/server/R5BundleFactory.java | 2 +- hapi-fhir-test-utilities/pom.xml | 2 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation-resources-r5/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 2 +- hapi-tinder-test/pom.xml | 2 +- pom.xml | 11 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 117 files changed, 703 insertions(+), 154 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/upgrade.md create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/version.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4207-getpagesoffset-set-to-total-number-of-resources-results-in-inconsistent-amount-of-entries-when-requests-are-sent-consecutively.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4210-wrong-bundle-entry-uri-in-transaction-bundle.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4218-bulk-export-get-output-format-param-string-escape-issue.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4224-migration-lock-clear.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4232-default-export-bulk-to-all-registered-resource-types.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4234-consent-with-convert.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4247-bulk-export-job-reuse.yaml diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index e2b1a4e85c4..524ebabd632 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index 6c2342e66dd..0366e720771 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 37aa8760b9b..b9310e594e5 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java index 3e48b0dc0ee..ecd8073b0eb 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java @@ -24,7 +24,6 @@ import ca.uhn.fhir.rest.client.api.IBasicClient; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.IRestfulClient; import ca.uhn.fhir.rest.client.api.IRestfulClientFactory; -import ca.uhn.fhir.tls.TlsAuthentication; import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.VersionUtil; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java index 47384a87f58..21fdc0b710a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java @@ -488,9 +488,12 @@ public class UrlUtil { if (theString == null) { return null; } + // If the user passes "_outputFormat" as a GET request parameter directly in the URL: + final boolean shouldEscapePlus = !theString.startsWith("application/"); + for (int i = 0; i < theString.length(); i++) { char nextChar = theString.charAt(i); - if (nextChar == '%' || nextChar == '+') { + if (nextChar == '%' || (nextChar == '+' && shouldEscapePlus)) { try { // Yes it would be nice to not use a string "UTF-8" but the equivalent // method that takes Charset is JDK10+ only... sigh.... diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java index 75e2433a626..9bf12999bf2 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java @@ -103,8 +103,10 @@ public enum VersionEnum { V6_1_0, V6_1_1, V6_1_2, + V6_1_3, + V6_1_4, V6_2_0, - V6_3_0, + V6_3_0 ; public static VersionEnum latestVersion() { diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/UrlUtilTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/UrlUtilTest.java index 6c2fd7cc914..a92e7dc73de 100644 --- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/UrlUtilTest.java +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/UrlUtilTest.java @@ -1,10 +1,12 @@ package ca.uhn.fhir.util; +import ca.uhn.fhir.rest.api.Constants; import org.apache.http.message.BasicNameValuePair; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -45,6 +47,20 @@ public class UrlUtilTest { assertEquals("A%2BB", UrlUtil.escapeUrlParam("A+B")); } + @Test + public void testUnescape() { + assertAll( + () -> assertEquals(Constants.CT_JSON, UrlUtil.unescape(Constants.CT_JSON)), + () -> assertEquals(Constants.CT_NDJSON, UrlUtil.unescape(Constants.CT_NDJSON)), + () -> assertEquals(Constants.CT_XML, UrlUtil.unescape(Constants.CT_XML)), + () -> assertEquals(Constants.CT_XML_PATCH, UrlUtil.unescape(Constants.CT_XML_PATCH)), + () -> assertEquals(Constants.CT_APPLICATION_GZIP, UrlUtil.unescape(Constants.CT_APPLICATION_GZIP)), + () -> assertEquals(Constants.CT_RDF_TURTLE, UrlUtil.unescape(Constants.CT_RDF_TURTLE)), + () -> assertEquals(Constants.CT_FHIR_JSON, UrlUtil.unescape(Constants.CT_FHIR_JSON)), + () -> assertEquals(Constants.CT_FHIR_NDJSON, UrlUtil.unescape(Constants.CT_FHIR_NDJSON)) + ); + } + @Test public void testIsValid() { assertTrue(UrlUtil.isValid("http://foo")); diff --git a/hapi-fhir-batch/pom.xml b/hapi-fhir-batch/pom.xml index 4c835e08e17..5932cb89615 100644 --- a/hapi-fhir-batch/pom.xml +++ b/hapi-fhir-batch/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 68e9fcd26b1..820c713da15 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -3,14 +3,14 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT pom HAPI FHIR BOM ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index 6b762465e87..33c519ab52a 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index 201b0a61378..b6fb1879185 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index f025c1daf09..8b7f778705b 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index 9426400ce16..fee873f3abe 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../hapi-deployable-pom diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index 1d093cab89b..734a5bb1564 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index ce54439eed4..fe36758adea 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index 83c21fee9d3..88c20c70f95 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java index 8580f47d8f2..414aa2d2b68 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/GenericClient.java @@ -2234,7 +2234,6 @@ public class GenericClient extends BaseClient implements IGenericClient { return new TransactionExecutable<>(theResources); } - } private class UpdateInternal extends BaseSearch diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 21a43107a8b..49d5394bcac 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/server/VersionedApiConverterInterceptor.java b/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/server/VersionedApiConverterInterceptor.java index b1b29b126ab..a8cf61d1d26 100644 --- a/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/server/VersionedApiConverterInterceptor.java +++ b/hapi-fhir-converter/src/main/java/ca/uhn/hapi/converters/server/VersionedApiConverterInterceptor.java @@ -23,6 +23,7 @@ package ca.uhn.hapi.converters.server; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.interceptor.api.Interceptor; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.RequestDetails; @@ -30,6 +31,7 @@ import ca.uhn.fhir.rest.api.server.ResponseDetails; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; +import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationConstants; import org.hl7.fhir.converter.NullVersionConverterAdvisor10_30; import org.hl7.fhir.converter.NullVersionConverterAdvisor10_40; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_30; @@ -54,6 +56,8 @@ import static org.apache.commons.lang3.StringUtils.*; * Versioned API features. *

*/ + +@Interceptor(order = AuthorizationConstants.ORDER_CONVERTER_INTERCEPTOR) public class VersionedApiConverterInterceptor extends InterceptorAdapter { private final FhirContext myCtxDstu2; private final FhirContext myCtxDstu2Hl7Org; diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index 0672fad4433..a53207d9d6d 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index ca16d485654..657315bfe15 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/upgrade.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/version.yaml new file mode 100644 index 00000000000..1b57632767c --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_3/version.yaml @@ -0,0 +1,3 @@ +--- +release-date: "2022-10-06" +codename: "Unicorn" diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4111-mdm-message-key.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4111-mdm-message-key.yaml index 9d23f25b8a9..014414c2bdb 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4111-mdm-message-key.yaml +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4111-mdm-message-key.yaml @@ -1,5 +1,6 @@ --- type: fix issue: 4111 +backport: 6.1.3 title: "MDM messages were using the resource id as a message key when it should be using the EID as a partition hash key. This could lead to duplicate golden resources on systems using Kafka as a message broker." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4207-getpagesoffset-set-to-total-number-of-resources-results-in-inconsistent-amount-of-entries-when-requests-are-sent-consecutively.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4207-getpagesoffset-set-to-total-number-of-resources-results-in-inconsistent-amount-of-entries-when-requests-are-sent-consecutively.yaml new file mode 100644 index 00000000000..06391321901 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4207-getpagesoffset-set-to-total-number-of-resources-results-in-inconsistent-amount-of-entries-when-requests-are-sent-consecutively.yaml @@ -0,0 +1,6 @@ +--- +type: fix +issue: 4207 +title: "Previously to improve performance, if the total number of resources was less than the _getpageoffset, + the results would default to last resource offset. This is especially evident when requests are consecutive + resulting in one entry being displayed in some requests. This issue is now fixed." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4210-wrong-bundle-entry-uri-in-transaction-bundle.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4210-wrong-bundle-entry-uri-in-transaction-bundle.yaml new file mode 100644 index 00000000000..ca8f939292e --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4210-wrong-bundle-entry-uri-in-transaction-bundle.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 4210 +jira: SMILE-4685 +title: "Generating Bundle with resources was setting `entry.request.url` as absolute url when it should be relative. This has been fixed" diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4218-bulk-export-get-output-format-param-string-escape-issue.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4218-bulk-export-get-output-format-param-string-escape-issue.yaml new file mode 100644 index 00000000000..d279b9c6a74 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4218-bulk-export-get-output-format-param-string-escape-issue.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 4218 +title: "Performing a bulk export with an _outputParam value encoded in a GET request URL that contains a '+' (ex: 'application/fhir+ndjson') will result in a 400 because the '+' is replaced with a ' '. After this fix the '+' will remain in the parameter value." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4224-migration-lock-clear.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4224-migration-lock-clear.yaml new file mode 100644 index 00000000000..6e23328163d --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4224-migration-lock-clear.yaml @@ -0,0 +1,4 @@ +--- +type: add +issue: 4224 +title: "Added new System Property called 'CLEAR_LOCK_TABLE_WITH_DESCRIPTION' that when set to the uuid of a lock record, will clear that lock record before attempting to insert a new one." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4232-default-export-bulk-to-all-registered-resource-types.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4232-default-export-bulk-to-all-registered-resource-types.yaml new file mode 100644 index 00000000000..36ad58b411e --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4232-default-export-bulk-to-all-registered-resource-types.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 4232 +title: "Previously during Bulk Export, if no `_type` parameter was provided, an error would be thrown. This has been changed, and if the `_type` parameter is omitted, Bulk Export will default to all registered types." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4234-consent-with-convert.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4234-consent-with-convert.yaml new file mode 100644 index 00000000000..94e8f53584e --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4234-consent-with-convert.yaml @@ -0,0 +1,6 @@ +--- +type: fix +issue: 4234 +jira: SMILE-4765 +title: "Fixed a bug which caused a failure when combining a Consent Interceptor with version conversion via the `Accept` header." + diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4247-bulk-export-job-reuse.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4247-bulk-export-job-reuse.yaml new file mode 100644 index 00000000000..25f3e3354bb --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4247-bulk-export-job-reuse.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 4247 +title: "Previously, Bulk Export jobs were always reused, even if completed. Now, jobs are only reused if an identical job is already running, and has not yet completed or failed." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml index 4b79306acf9..92d154bf813 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml @@ -1,3 +1,3 @@ --- release-date: "2022-11-18" -codename: "TBD" +codename: "Vishwa" diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_3_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_3_0/version.yaml index 74332cf46c0..65e91d915a7 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_3_0/version.yaml +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_3_0/version.yaml @@ -1,3 +1,3 @@ --- -release-date: "TBD" +release-date: "2022-02-18" codename: "TBD" diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index f5efb715ded..48cdfdfbc2e 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index a3ebdf61763..1123f8f69e1 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index fdaed9ee04e..cf796af2e2d 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 1a18839bc90..06ec5bf9d74 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java index d56d34d4442..2ab5cbd51d5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java @@ -35,6 +35,7 @@ import ca.uhn.fhir.jpa.entity.Batch2JobInstanceEntity; import ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity; import ca.uhn.fhir.jpa.util.JobInstanceUtil; import ca.uhn.fhir.model.api.PagingIterator; +import ca.uhn.fhir.narrative.BaseThymeleafNarrativeGenerator; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index a551022bb7d..74335ffad0c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -160,6 +160,7 @@ public abstract class BaseHapiFhirResourceDao extends B public static final String BASE_RESOURCE_NAME = "resource"; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class); + @Autowired protected PlatformTransactionManager myPlatformTransactionManager; @Autowired(required = false) diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml index db7a25faeba..13f6ab13be8 100644 --- a/hapi-fhir-jpaserver-cql/pom.xml +++ b/hapi-fhir-jpaserver-cql/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml index 3ae132f069d..bef3ac53647 100644 --- a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 0bbc1a3799d..4134515a4d1 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 2c24cb96fdf..b14d33165e1 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index d0edd4fb80a..2bb451fe257 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 8972baf7789..6bc6104870b 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu2/pom.xml b/hapi-fhir-jpaserver-test-dstu2/pom.xml index dbe117f54a6..0fcc342eb08 100644 --- a/hapi-fhir-jpaserver-test-dstu2/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java index 1301aa2eedb..d23a07ae335 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java @@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/hapi-fhir-jpaserver-test-dstu3/pom.xml b/hapi-fhir-jpaserver-test-dstu3/pom.xml index e75a6ceb78c..c2632b3107c 100644 --- a/hapi-fhir-jpaserver-test-dstu3/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu3/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3BundleTest.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3BundleTest.java index 1f84eb75211..48d67088c64 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3BundleTest.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3BundleTest.java @@ -4,11 +4,13 @@ import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.CapabilityStatement; +import org.hl7.fhir.dstu3.model.CarePlan; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.PrimitiveType; import org.hl7.fhir.dstu3.model.StringType; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -56,7 +58,27 @@ public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Te assertTrue(searchInclude.stream().map(PrimitiveType::getValue).anyMatch(stringRevIncludes -> stringRevIncludes.equals("Patient:general-practitioner"))); assertEquals(searchInclude.size(), 4); } - - } + + @Test + void testTransactionBundleEntryUri() { + CarePlan carePlan = new CarePlan(); + carePlan.getText().setDivAsString("A CarePlan"); + carePlan.setId("ACarePlan"); + ourClient.create().resource(carePlan).execute(); + + // GET CarePlans from server + Bundle bundle = ourClient.search() + .byUrl(ourServerBase + "/CarePlan") + .returnBundle(Bundle.class).execute(); + + // Create and populate list of CarePlans + List carePlans = new ArrayList<>(); + bundle.getEntry().forEach(entry -> carePlans.add((CarePlan) entry.getResource())); + + // Post CarePlans should not get: HAPI-2006: Unable to perform PUT, URL provided is invalid... + ourClient.transaction().withResources(carePlans).execute(); + } + + } diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 867b07ab2d5..2be35bd3c08 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -5,7 +5,6 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.dao.data.ISearchDao; import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.util.QueryParameterUtils; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import ca.uhn.fhir.model.primitive.InstantDt; @@ -17,7 +16,6 @@ import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.SearchTotalModeEnum; import ca.uhn.fhir.rest.api.SummaryEnum; -import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.api.IClientInterceptor; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; @@ -30,7 +28,6 @@ import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; -import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; @@ -107,7 +104,6 @@ import org.hl7.fhir.dstu3.model.Organization; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Period; -import org.hl7.fhir.dstu3.model.Person; import org.hl7.fhir.dstu3.model.PlanDefinition; import org.hl7.fhir.dstu3.model.Practitioner; import org.hl7.fhir.dstu3.model.ProcedureRequest; @@ -2354,7 +2350,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { assertEquals(1, ((Patient) history.getEntry().get(0).getResource()).getName().size()); assertEquals(HTTPVerb.DELETE, history.getEntry().get(1).getRequest().getMethodElement().getValue()); - assertEquals("http://localhost:" + ourPort + "/fhir/context/Patient/" + id.getIdPart() + "/_history/2", history.getEntry().get(1).getRequest().getUrl()); + assertEquals("Patient/" + id.getIdPart() + "/_history/2", history.getEntry().get(1).getRequest().getUrl()); assertEquals(null, history.getEntry().get(1).getResource()); assertEquals(id.withVersion("1").getValue(), history.getEntry().get(2).getResource().getId()); diff --git a/hapi-fhir-jpaserver-test-r4/pom.xml b/hapi-fhir-jpaserver-test-r4/pom.xml index 9fbe1e4995b..1629009d032 100644 --- a/hapi-fhir-jpaserver-test-r4/pom.xml +++ b/hapi-fhir-jpaserver-test-r4/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkDataExportProviderTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkDataExportProviderTest.java index 3bff9990352..f5f3e8d90cf 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkDataExportProviderTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkDataExportProviderTest.java @@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.bulk; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.model.Batch2JobInfo; import ca.uhn.fhir.jpa.api.model.Batch2JobOperationResult; import ca.uhn.fhir.jpa.api.model.BulkExportJobResults; @@ -57,6 +58,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -67,12 +69,15 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -93,7 +98,7 @@ public class BulkDataExportProviderTest { private IBatch2JobRunner myJobRunner; private DaoConfig myDaoConfig; - + private DaoRegistry myDaoRegistry; private CloseableHttpClient myClient; @InjectMocks @@ -136,6 +141,9 @@ public class BulkDataExportProviderTest { public void injectDaoConfig() { myDaoConfig = new DaoConfig(); myProvider.setDaoConfig(myDaoConfig); + myDaoRegistry = mock(DaoRegistry.class); + lenient().when(myDaoRegistry.getRegisteredDaoTypes()).thenReturn(Set.of("Patient", "Observation", "Encounter")); + myProvider.setDaoRegistry(myDaoRegistry); } public void startWithFixedBaseUrl() { @@ -863,6 +871,52 @@ public class BulkDataExportProviderTest { } } + @Test + public void testGetBulkExport_outputFormat_FhirNdJson_inHeader() throws IOException { + // when + when(myJobRunner.startNewJob(any())) + .thenReturn(createJobStartResponse()); + + // call + final HttpGet httpGet = new HttpGet(String.format("http://localhost:%s/%s", myPort, JpaConstants.OPERATION_EXPORT)); + httpGet.addHeader("_outputFormat", Constants.CT_FHIR_NDJSON); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + + try (CloseableHttpResponse response = myClient.execute(httpGet)) { + ourLog.info("Response: {}", response.toString()); + assertEquals(202, response.getStatusLine().getStatusCode()); + assertEquals("Accepted", response.getStatusLine().getReasonPhrase()); + assertEquals(String.format("http://localhost:%s/$export-poll-status?_jobId=%s", myPort, A_JOB_ID), response.getFirstHeader(Constants.HEADER_CONTENT_LOCATION).getValue()); + assertTrue(IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8).isEmpty()); + } + + final BulkExportParameters params = verifyJobStart(); + assertEquals(Constants.CT_FHIR_NDJSON, params.getOutputFormat()); + } + + @Test + public void testGetBulkExport_outputFormat_FhirNdJson_inUrl() throws IOException { + // when + when(myJobRunner.startNewJob(any())) + .thenReturn(createJobStartResponse()); + + // call + final HttpGet httpGet = new HttpGet(String.format("http://localhost:%s/%s?_outputFormat=%s", myPort, JpaConstants.OPERATION_EXPORT, Constants.CT_FHIR_NDJSON)); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + + try (CloseableHttpResponse response = myClient.execute(httpGet)) { + assertAll( + () -> assertEquals(202, response.getStatusLine().getStatusCode()), + () -> assertEquals("Accepted", response.getStatusLine().getReasonPhrase()), + () -> assertEquals(String.format("http://localhost:%s/$export-poll-status?_jobId=%s", myPort, A_JOB_ID), response.getFirstHeader(Constants.HEADER_CONTENT_LOCATION).getValue()), + () -> assertTrue(IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8).isEmpty()) + ); + } + + final BulkExportParameters params = verifyJobStart(); + assertEquals(Constants.CT_FHIR_NDJSON, params.getOutputFormat()); + } + private void callExportAndAssertJobId(Parameters input, String theExpectedJobId) throws IOException { HttpPost post; post = new HttpPost("http://localhost:" + myPort + "/" + JpaConstants.OPERATION_EXPORT); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java index 9bace0e1a7a..fe279c65d6a 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java @@ -25,12 +25,14 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Coverage; +import org.hl7.fhir.r4.model.Encounter; import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Group; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Reference; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -41,6 +43,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -48,6 +51,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import static org.awaitility.Awaitility.await; import static org.hamcrest.CoreMatchers.is; @@ -56,6 +60,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -63,7 +68,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; - public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { private static final Logger ourLog = LoggerFactory.getLogger(BulkExportUseCaseTest.class); @@ -76,6 +80,29 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { @Nested public class SpecConformanceTests { + + @Test + public void testBatchJobsAreOnlyReusedIfInProgress() throws IOException { + //Given a patient exists + Patient p = new Patient(); + p.setId("Pat-1"); + myClient.update().resource(p).execute(); + + //And Given we start a bulk export job + String pollingLocation = submitBulkExportForTypes("Patient"); + String jobId = getJobIdFromPollingLocation(pollingLocation); + myBatch2JobHelper.awaitJobCompletion(jobId); + + //When we execute another batch job, it should not have the same job id. + String secondPollingLocation = submitBulkExportForTypes("Patient"); + String secondJobId = getJobIdFromPollingLocation(secondPollingLocation); + + //Then the job id should be different + assertThat(secondJobId, not(equalTo(jobId))); + + + myBatch2JobHelper.awaitJobCompletion(secondJobId); + } @Test public void testPollingLocationContainsAllRequiredAttributesUponCompletion() throws IOException { @@ -85,14 +112,8 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { myClient.update().resource(p).execute(); //And Given we start a bulk export job - HttpGet httpGet = new HttpGet(myClient.getServerBase() + "/$export?_type=Patient"); - httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); - String pollingLocation; - try (CloseableHttpResponse status = ourHttpClient.execute(httpGet)) { - Header[] headers = status.getHeaders("Content-Location"); - pollingLocation = headers[0].getValue(); - } - String jobId = pollingLocation.substring(pollingLocation.indexOf("_jobId=") + 7); + String pollingLocation = submitBulkExportForTypes("Patient"); + String jobId = getJobIdFromPollingLocation(pollingLocation); myBatch2JobHelper.awaitJobCompletion(jobId); //Then: When the poll shows as complete, all attributes should be filled. @@ -113,6 +134,143 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { assertThat(responseContent, containsString("\"error\" : [ ]")); } } + + @NotNull + private String getJobIdFromPollingLocation(String pollingLocation) { + return pollingLocation.substring(pollingLocation.indexOf("_jobId=") + 7); + } + + @Test + public void export_shouldExportPatientResource_whenTypeParameterOmitted() throws IOException { + + //Given a patient exists + Patient p = new Patient(); + p.setId("Pat-1"); + myClient.update().resource(p).execute(); + + //And Given we start a bulk export job + HttpGet httpGet = new HttpGet(myClient.getServerBase() + "/$export"); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + String pollingLocation; + try (CloseableHttpResponse status = ourHttpClient.execute(httpGet)) { + Header[] headers = status.getHeaders("Content-Location"); + pollingLocation = headers[0].getValue(); + } + String jobId = getJobIdFromPollingLocation(pollingLocation); + myBatch2JobHelper.awaitJobCompletion(jobId); + + //Then: When the poll shows as complete, all attributes should be filled. + HttpGet statusGet = new HttpGet(pollingLocation); + String expectedOriginalUrl = myClient.getServerBase() + "/$export"; + try (CloseableHttpResponse status = ourHttpClient.execute(statusGet)) { + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + + ourLog.info(responseContent); + + BulkExportResponseJson result = JsonUtil.deserialize(responseContent, BulkExportResponseJson.class); + assertThat(result.getRequest(), is(equalTo(expectedOriginalUrl))); + assertThat(result.getRequiresAccessToken(), is(equalTo(true))); + assertThat(result.getTransactionTime(), is(notNullValue())); + assertThat(result.getOutput(), is(not(empty()))); + + //We assert specifically on content as the deserialized version will "helpfully" fill in missing fields. + assertThat(responseContent, containsString("\"error\" : [ ]")); + } + } + + @Test + public void export_shouldExportPatientAndObservationAndEncounterResources_whenTypeParameterOmitted() throws IOException { + + Patient patient = new Patient(); + patient.setId("Pat-1"); + myClient.update().resource(patient).execute(); + + Observation observation = new Observation(); + observation.setId("Obs-1"); + myClient.update().resource(observation).execute(); + + Encounter encounter = new Encounter(); + encounter.setId("Enc-1"); + myClient.update().resource(encounter).execute(); + + HttpGet httpGet = new HttpGet(myClient.getServerBase() + "/$export"); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + String pollingLocation; + try (CloseableHttpResponse status = ourHttpClient.execute(httpGet)) { + Header[] headers = status.getHeaders("Content-Location"); + pollingLocation = headers[0].getValue(); + } + String jobId = getJobIdFromPollingLocation(pollingLocation); + myBatch2JobHelper.awaitJobCompletion(jobId); + + HttpGet statusGet = new HttpGet(pollingLocation); + String expectedOriginalUrl = myClient.getServerBase() + "/$export"; + try (CloseableHttpResponse status = ourHttpClient.execute(statusGet)) { + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + BulkExportResponseJson result = JsonUtil.deserialize(responseContent, BulkExportResponseJson.class); + assertThat(result.getRequest(), is(equalTo(expectedOriginalUrl))); + assertThat(result.getRequiresAccessToken(), is(equalTo(true))); + assertThat(result.getTransactionTime(), is(notNullValue())); + assertEquals(result.getOutput().size(), 3); + assertEquals(1, result.getOutput().stream().filter(o -> o.getType().equals("Patient")).collect(Collectors.toList()).size()); + assertEquals(1, result.getOutput().stream().filter(o -> o.getType().equals("Observation")).collect(Collectors.toList()).size()); + assertEquals(1, result.getOutput().stream().filter(o -> o.getType().equals("Encounter")).collect(Collectors.toList()).size()); + + //We assert specifically on content as the deserialized version will "helpfully" fill in missing fields. + assertThat(responseContent, containsString("\"error\" : [ ]")); + } + } + + @Test + public void export_shouldNotExportBinaryResource_whenTypeParameterOmitted() throws IOException { + + Patient patient = new Patient(); + patient.setId("Pat-1"); + myClient.update().resource(patient).execute(); + + Binary binary = new Binary(); + binary.setId("Bin-1"); + myClient.update().resource(binary).execute(); + + HttpGet httpGet = new HttpGet(myClient.getServerBase() + "/$export"); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + String pollingLocation; + try (CloseableHttpResponse status = ourHttpClient.execute(httpGet)) { + Header[] headers = status.getHeaders("Content-Location"); + pollingLocation = headers[0].getValue(); + } + String jobId = getJobIdFromPollingLocation(pollingLocation); + myBatch2JobHelper.awaitJobCompletion(jobId); + + HttpGet statusGet = new HttpGet(pollingLocation); + String expectedOriginalUrl = myClient.getServerBase() + "/$export"; + try (CloseableHttpResponse status = ourHttpClient.execute(statusGet)) { + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + BulkExportResponseJson result = JsonUtil.deserialize(responseContent, BulkExportResponseJson.class); + assertThat(result.getRequest(), is(equalTo(expectedOriginalUrl))); + assertThat(result.getRequiresAccessToken(), is(equalTo(true))); + assertThat(result.getTransactionTime(), is(notNullValue())); + assertEquals(result.getOutput().size(), 1); + assertEquals(1, result.getOutput().stream().filter(o -> o.getType().equals("Patient")).collect(Collectors.toList()).size()); + assertEquals(0, result.getOutput().stream().filter(o -> o.getType().equals("Binary")).collect(Collectors.toList()).size()); + + //We assert specifically on content as the deserialized version will "helpfully" fill in missing fields. + assertThat(responseContent, containsString("\"error\" : [ ]")); + } + } + + } + + private String submitBulkExportForTypes(String... theTypes) throws IOException { + String typeString = String.join(",", theTypes); + HttpGet httpGet = new HttpGet(myClient.getServerBase() + "/$export?_type=" + typeString); + httpGet.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC); + String pollingLocation; + try (CloseableHttpResponse status = ourHttpClient.execute(httpGet)) { + Header[] headers = status.getHeaders("Content-Location"); + pollingLocation = headers[0].getValue(); + } + return pollingLocation; } @Nested @@ -233,7 +391,6 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test { } - @Nested public class PatientBulkExportTests { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java index cf924be002b..ef3646d3543 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java @@ -41,6 +41,8 @@ import javax.persistence.EntityManager; import java.util.List; +import java.util.List; + import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ConsentInterceptorResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ConsentInterceptorResourceProviderR4Test.java index 9abba0bdf60..257b4aeb873 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ConsentInterceptorResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ConsentInterceptorResourceProviderR4Test.java @@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService; import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.UrlUtil; +import ca.uhn.hapi.converters.server.VersionedApiConverterInterceptor; import com.google.common.base.Charsets; import com.google.common.collect.Lists; import org.apache.commons.collections4.ListUtils; @@ -282,6 +283,21 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid }); } + @Test + public void testConsentWorksWithVersionedApiConverterInterceptor() { + myConsentInterceptor = new ConsentInterceptor(new IConsentService() { + }); + ourRestServer.getInterceptorService().registerInterceptor(myConsentInterceptor); + ourRestServer.getInterceptorService().registerInterceptor(new VersionedApiConverterInterceptor()); + + myClient.create().resource(new Patient().setGender(Enumerations.AdministrativeGender.MALE).addName(new HumanName().setFamily("1"))).execute(); + Bundle response = myClient.search().forResource(Patient.class).count(1).accept("application/fhir+json; fhirVersion=3.0").returnBundle(Bundle.class).execute(); + + assertEquals(1, response.getEntry().size()); + assertNull(response.getTotalElement().getValue()); + + } + @Test public void testHistoryAndBlockSome() { create50Observations(); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4BundleTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4BundleTest.java index 89f6d0f1213..4c8d1d13a31 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4BundleTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4BundleTest.java @@ -10,6 +10,7 @@ import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleType; import org.hl7.fhir.r4.model.Bundle.HTTPVerb; +import org.hl7.fhir.r4.model.CarePlan; import org.hl7.fhir.r4.model.Condition; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.OperationOutcome; @@ -331,4 +332,25 @@ public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test { return ids; } + + @Test + void testTransactionBundleEntryUri() { + CarePlan carePlan = new CarePlan(); + carePlan.getText().setDivAsString("A CarePlan"); + carePlan.setId("ACarePlan"); + myClient.create().resource(carePlan).execute(); + + // GET CarePlans from server + Bundle bundle = myClient.search() + .byUrl(ourServerBase + "/CarePlan") + .returnBundle(Bundle.class).execute(); + + // Create and populate list of CarePlans + List carePlans = new ArrayList<>(); + bundle.getEntry().forEach(entry -> carePlans.add((CarePlan) entry.getResource())); + + // Post CarePlans should not get: HAPI-2006: Unable to perform PUT, URL provided is invalid... + myClient.transaction().withResources(carePlans).execute(); + } + } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index b8e7a32b8e0..1358cfe0729 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -10,7 +10,6 @@ import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.UcumServiceUtil; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.ZipCollectionBuilder; import ca.uhn.fhir.jpa.test.config.TestR4Config; import ca.uhn.fhir.jpa.util.QueryParameterUtils; @@ -25,7 +24,6 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.PreferReturnEnum; import ca.uhn.fhir.rest.api.SearchTotalModeEnum; import ca.uhn.fhir.rest.api.SummaryEnum; -import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.apache.ResourceEntity; import ca.uhn.fhir.rest.client.api.IClientInterceptor; import ca.uhn.fhir.rest.client.api.IGenericClient; @@ -41,7 +39,6 @@ import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; -import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; @@ -71,7 +68,6 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; -import org.apache.jena.rdf.model.ModelCon; import org.hamcrest.Matchers; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.instance.model.api.IAnyResource; @@ -132,7 +128,6 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Period; -import org.hl7.fhir.r4.model.Person; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.Procedure; import org.hl7.fhir.r4.model.Quantity; @@ -169,6 +164,7 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Nonnull; +import javax.sql.DataSource; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -3285,7 +3281,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { assertEquals(1, ((Patient) history.getEntry().get(0).getResource()).getName().size()); assertEquals(HTTPVerb.DELETE, history.getEntry().get(1).getRequest().getMethodElement().getValue()); - assertEquals("http://localhost:" + ourPort + "/fhir/context/Patient/" + id.getIdPart() + "/_history/2", history.getEntry().get(1).getRequest().getUrl()); + assertEquals("Patient/" + id.getIdPart() + "/_history/2", history.getEntry().get(1).getRequest().getUrl()); assertEquals(null, history.getEntry().get(1).getResource()); assertEquals(id.withVersion("1").getValue(), history.getEntry().get(2).getResource().getId()); diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml index 1ed22408ee5..99b6ecae0af 100644 --- a/hapi-fhir-jpaserver-test-r4b/pom.xml +++ b/hapi-fhir-jpaserver-test-r4b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java b/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java index 6d835cd99de..e3ab35f3eee 100644 --- a/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java +++ b/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java @@ -13,20 +13,17 @@ import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4b.model.Bundle; import org.hl7.fhir.r4b.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4b.model.CarePlan; import org.hl7.fhir.r4b.model.CodeableConcept; import org.hl7.fhir.r4b.model.Condition; import org.hl7.fhir.r4b.model.DateTimeType; import org.hl7.fhir.r4b.model.MedicationRequest; import org.hl7.fhir.r4b.model.Observation; import org.hl7.fhir.r4b.model.Observation.ObservationComponentComponent; -import org.hl7.fhir.r4b.model.OperationOutcome; import org.hl7.fhir.r4b.model.Organization; import org.hl7.fhir.r4b.model.Parameters; import org.hl7.fhir.r4b.model.Patient; @@ -464,6 +461,28 @@ public class ResourceProviderR4BTest extends BaseResourceProviderR4BTest { assertThat(ids, Matchers.not(hasItem(o2Id))); } + @Test + void testTransactionBundleEntryUri() { + CarePlan carePlan = new CarePlan(); + carePlan.getText().setDivAsString("A CarePlan"); + carePlan.setId("ACarePlan"); + myClient.create().resource(carePlan).execute(); + + // GET CarePlans from server + Bundle bundle = myClient.search() + .byUrl(ourServerBase + "/CarePlan") + .returnBundle(Bundle.class).execute(); + + // Create and populate list of CarePlans + List carePlans = new ArrayList<>(); + bundle.getEntry().forEach(entry -> carePlans.add((CarePlan) entry.getResource())); + + // Post CarePlans should not get: HAPI-2006: Unable to perform PUT, URL provided is invalid... + myClient.transaction().withResources(carePlans).execute(); + } + + + private IIdType createOrganization(String methodName, String s) { Organization o1 = new Organization(); o1.setName(methodName + s); diff --git a/hapi-fhir-jpaserver-test-r5/pom.xml b/hapi-fhir-jpaserver-test-r5/pom.xml index a84c5d01af4..db78d26cb1f 100644 --- a/hapi-fhir-jpaserver-test-r5/pom.xml +++ b/hapi-fhir-jpaserver-test-r5/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java index 8d1d556fc7e..3171fb4af85 100644 --- a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java @@ -19,6 +19,7 @@ import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r5.model.CarePlan; import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.Condition; import org.hl7.fhir.r5.model.DateTimeType; @@ -481,6 +482,27 @@ public class ResourceProviderR5Test extends BaseResourceProviderR5Test { assertThat(ids, Matchers.not(hasItem(o2Id))); } + + @Test + void testTransactionBundleEntryUri() { + CarePlan carePlan = new CarePlan(); + carePlan.getText().setDivAsString("A CarePlan"); + carePlan.setId("ACarePlan"); + myClient.create().resource(carePlan).execute(); + + // GET CarePlans from server + Bundle bundle = myClient.search() + .byUrl(ourServerBase + "/CarePlan") + .returnBundle(Bundle.class).execute(); + + // Create and populate list of CarePlans + List carePlans = new ArrayList<>(); + bundle.getEntry().forEach(entry -> carePlans.add((CarePlan) entry.getResource())); + + // Post CarePlans should not get: HAPI-2006: Unable to perform PUT, URL provided is invalid... + myClient.transaction().withResources(carePlans).execute(); + } + private IIdType createOrganization(String methodName, String s) { Organization o1 = new Organization(); o1.setName(methodName + s); diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 9ca5a676fa1..a2687d0790c 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 41298dfc6f7..12b6a283f49 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index 1d9e1d02ef1..c8c2f0475a0 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index 567d2d91d91..ef7f94f06b0 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index 11d42001f7f..9ebf005be9e 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationConstants.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationConstants.java index f138a14568e..51c1e7c2567 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationConstants.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationConstants.java @@ -24,6 +24,7 @@ public class AuthorizationConstants { public static final int ORDER_CONSENT_INTERCEPTOR = 100; public static final int ORDER_AUTH_INTERCEPTOR = 200; + public static final int ORDER_CONVERTER_INTERCEPTOR = 300; private AuthorizationConstants() { super(); diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java index cb81c181887..a284ea7b1c7 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/BaseResourceReturningMethodBinding.java @@ -369,17 +369,15 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi count = result.preferredPageSize(); } - Integer offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET); - if (offsetI == null || offsetI < 0) { - offsetI = 0; + Integer offset = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET); + if (offset == null || offset < 0) { + offset = 0; } Integer resultSize = result.size(); - int start; + int start = offset; if (resultSize != null) { - start = Math.max(0, Math.min(offsetI, resultSize - 1)); - } else { - start = offsetI; + start = Math.max(0, Math.min(offset, resultSize)); } ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 6b54240e8ec..d04ab284bc5 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index d604e590ee6..b9b1218fc42 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index a2b86796529..e86304e27c4 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT hapi-fhir-spring-boot-sample-client-okhttp diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index 90a9ac73b68..1f399a743da 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT hapi-fhir-spring-boot-sample-server-jersey diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index 040bd66fd2e..528f4f7c923 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT hapi-fhir-spring-boot-samples diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index f934e564e8c..1132d0beac2 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index d00b63f9e79..2daa1947a43 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index 79a854a1e53..df5bad0e721 100644 --- a/hapi-fhir-sql-migrate/pom.xml +++ b/hapi-fhir-sql-migrate/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationLock.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationLock.java index 68a4b4643d2..a65761f50be 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationLock.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationLock.java @@ -21,18 +21,25 @@ package ca.uhn.fhir.jpa.migrate; */ import ca.uhn.fhir.i18n.Msg; +import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Optional; import java.util.UUID; +import static org.apache.commons.lang3.StringUtils.isBlank; + /** * The approach used in this class is borrowed from org.flywaydb.community.database.ignite.thin.IgniteThinDatabase */ public class HapiMigrationLock implements AutoCloseable { + static final Integer LOCK_PID = -100; private static final Logger ourLog = LoggerFactory.getLogger(HapiMigrationLock.class); public static final int SLEEP_MILLIS_BETWEEN_LOCK_RETRIES = 1000; - public static final int MAX_RETRY_ATTEMPTS = 50; + public static final int DEFAULT_MAX_RETRY_ATTEMPTS = 50; + public static int ourMaxRetryAttempts = DEFAULT_MAX_RETRY_ATTEMPTS; + public static final String CLEAR_LOCK_TABLE_WITH_DESCRIPTION = "CLEAR_LOCK_TABLE_WITH_DESCRIPTION"; private final String myLockDescription = UUID.randomUUID().toString(); @@ -47,6 +54,7 @@ public class HapiMigrationLock implements AutoCloseable { } private void lock() { + cleanLockTableIfRequested(); int retryCount = 0; do { @@ -55,23 +63,57 @@ public class HapiMigrationLock implements AutoCloseable { return; } retryCount++; - ourLog.info("Waiting for lock on " + this); - Thread.sleep(SLEEP_MILLIS_BETWEEN_LOCK_RETRIES); + + if (retryCount < ourMaxRetryAttempts) { + ourLog.info("Waiting for lock on {}. Retry {}/{}", myMigrationStorageSvc.getMigrationTablename(), retryCount, ourMaxRetryAttempts); + Thread.sleep(SLEEP_MILLIS_BETWEEN_LOCK_RETRIES); + } } catch (InterruptedException ex) { // Ignore - if interrupted, we still need to wait for lock to become available } - } while (retryCount < MAX_RETRY_ATTEMPTS); + } while (retryCount < ourMaxRetryAttempts); - throw new HapiMigrationException(Msg.code(2153) + "Unable to obtain table lock - another database migration may be running. If no " + + String message = "Unable to obtain table lock - another database migration may be running. If no " + "other database migration is running, then the previous migration did not shut down properly and the " + "lock record needs to be deleted manually. The lock record is located in the " + myMigrationStorageSvc.getMigrationTablename() + " table with " + - "INSTALLED_RANK = " + HapiMigrationStorageSvc.LOCK_PID); + "INSTALLED_RANK = " + LOCK_PID; + + Optional otherLockFound = myMigrationStorageSvc.findFirstByPidAndNotDescription(LOCK_PID, myLockDescription); + if (otherLockFound.isPresent()) { + message += " and DESCRIPTION = " + otherLockFound.get().getDescription(); + } + + throw new HapiMigrationException(Msg.code(2153) + message); + } + + /** + * + * @return whether a lock record was successfully deleted + */ + boolean cleanLockTableIfRequested() { + String description = System.getProperty(CLEAR_LOCK_TABLE_WITH_DESCRIPTION); + if (isBlank(description)) { + description = System.getenv(CLEAR_LOCK_TABLE_WITH_DESCRIPTION); + } + if (isBlank(description)) { + return false; + } + + ourLog.info("Repairing lock table. Removing row in " + myMigrationStorageSvc.getMigrationTablename() + " with INSTALLED_RANK = " + LOCK_PID + " and DESCRIPTION = " + description); + boolean result = myMigrationStorageSvc.deleteLockRecord(description); + if (result) { + ourLog.info("Successfully removed lock record"); + } else { + ourLog.info("No lock record found"); + } + return result; } private boolean insertLockingRow() { try { return myMigrationStorageSvc.insertLockRecord(myLockDescription); } catch (Exception e) { + ourLog.debug("Failed to insert lock record: {}", e.getMessage()); return false; } } @@ -83,4 +125,8 @@ public class HapiMigrationLock implements AutoCloseable { ourLog.error("Failed to delete migration lock record for description = [{}]", myLockDescription); } } + + public static void setMaxRetryAttempts(int theMaxRetryAttempts) { + ourMaxRetryAttempts = theMaxRetryAttempts; + } } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvc.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvc.java index 2ea84380ed2..566f332bd21 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvc.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvc.java @@ -32,7 +32,6 @@ import java.util.Set; public class HapiMigrationStorageSvc { public static final String UNKNOWN_VERSION = "unknown"; private static final String LOCK_TYPE = "hapi-fhir-lock"; - static final Integer LOCK_PID = -100; private final HapiMigrationDao myHapiMigrationDao; @@ -104,11 +103,11 @@ public class HapiMigrationStorageSvc { verifyNoOtherLocksPresent(theLockDescription); // Remove the locking row - return myHapiMigrationDao.deleteLockRecord(LOCK_PID, theLockDescription); + return myHapiMigrationDao.deleteLockRecord(HapiMigrationLock.LOCK_PID, theLockDescription); } void verifyNoOtherLocksPresent(String theLockDescription) { - Optional otherLockFound = myHapiMigrationDao.findFirstByPidAndNotDescription(LOCK_PID, theLockDescription); + Optional otherLockFound = myHapiMigrationDao.findFirstByPidAndNotDescription(HapiMigrationLock.LOCK_PID, theLockDescription); // Check that there are no other locks in place. This should not happen! if (otherLockFound.isPresent()) { @@ -118,7 +117,7 @@ public class HapiMigrationStorageSvc { public boolean insertLockRecord(String theLockDescription) { HapiMigrationEntity entity = new HapiMigrationEntity(); - entity.setPid(LOCK_PID); + entity.setPid(HapiMigrationLock.LOCK_PID); entity.setType(LOCK_TYPE); entity.setDescription(theLockDescription); entity.setExecutionTime(0); @@ -126,4 +125,8 @@ public class HapiMigrationStorageSvc { return myHapiMigrationDao.save(entity); } + + public Optional findFirstByPidAndNotDescription(Integer theLockPid, String theLockDescription) { + return myHapiMigrationDao.findFirstByPidAndNotDescription(theLockPid, theLockDescription); + } } diff --git a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java index 109b4174e6b..1edb81611d9 100644 --- a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java +++ b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java @@ -1,7 +1,9 @@ package ca.uhn.fhir.jpa.migrate; import ca.uhn.fhir.interceptor.api.HookParams; +import ca.uhn.fhir.jpa.migrate.dao.HapiMigrationDao; import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; +import ca.uhn.fhir.jpa.migrate.taskdef.NopTask; import ca.uhn.test.concurrency.IPointcutLatch; import ca.uhn.test.concurrency.PointcutLatch; import org.apache.commons.dbcp2.BasicDataSource; @@ -16,6 +18,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import javax.annotation.Nonnull; import java.util.List; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -25,6 +28,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; class HapiMigratorIT { private static final Logger ourLog = LoggerFactory.getLogger(HapiMigratorIT.class); @@ -32,6 +36,7 @@ class HapiMigratorIT { private final BasicDataSource myDataSource = BaseMigrationTest.getDataSource(); private final JdbcTemplate myJdbcTemplate = new JdbcTemplate(myDataSource); + private HapiMigrationStorageSvc myMigrationStorageSvc; @BeforeEach void before() { @@ -39,12 +44,17 @@ class HapiMigratorIT { migrator.createMigrationTableIfRequired(); Integer count = myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME, Integer.class); assertTrue(count > 0); + HapiMigrationDao migrationDao = new HapiMigrationDao(myDataSource, DriverTypeEnum.H2_EMBEDDED, MIGRATION_TABLENAME); + myMigrationStorageSvc = new HapiMigrationStorageSvc(migrationDao); + } @AfterEach void after() { myJdbcTemplate.execute("DROP TABLE " + MIGRATION_TABLENAME); assertEquals(0, myDataSource.getNumActive()); + HapiMigrationLock.setMaxRetryAttempts(HapiMigrationLock.DEFAULT_MAX_RETRY_ATTEMPTS); + System.clearProperty(HapiMigrationLock.CLEAR_LOCK_TABLE_WITH_DESCRIPTION); } @Test @@ -76,8 +86,7 @@ class HapiMigratorIT { LatchMigrationTask latchMigrationTask2 = new LatchMigrationTask("second new", "2"); LatchMigrationTask latchMigrationTask3 = new LatchMigrationTask("third repeat", "1"); - HapiMigrator migrator2 = buildMigrator(latchMigrationTask2); - migrator2.addTask(latchMigrationTask3); + HapiMigrator migrator2 = buildMigrator(latchMigrationTask2, latchMigrationTask3); // We only expect the first migration to run because the second one will block on the lock and by the time the lock // is released, the first one will have already run so there will be nothing to do @@ -108,10 +117,77 @@ class HapiMigratorIT { assertThat(result2.succeededTasks, hasSize(1)); } + @Test + void test_twoSequentialCalls_noblock() throws InterruptedException, ExecutionException { + + ExecutorService executor = Executors.newSingleThreadExecutor(); + LatchMigrationTask latchMigrationTask = new LatchMigrationTask("first", "1"); + + HapiMigrator migrator = buildMigrator(latchMigrationTask); + assertEquals(0, countLockRecords()); + + { + latchMigrationTask.setExpectedCount(1); + Future future = executor.submit(() -> migrator.migrate()); + latchMigrationTask.awaitExpected(); + assertEquals(1, countLockRecords()); + latchMigrationTask.release("1"); + + MigrationResult result = future.get(); + assertEquals(0, countLockRecords()); + assertThat(result.succeededTasks, hasSize(1)); + } + + { + Future future = executor.submit(() -> migrator.migrate()); + + MigrationResult result = future.get(); + assertEquals(0, countLockRecords()); + assertThat(result.succeededTasks, hasSize(0)); + } + + } + + + @Test + void test_oldLockFails_block() { + HapiMigrationLock.setMaxRetryAttempts(0); + String description = UUID.randomUUID().toString(); + HapiMigrator migrator = buildMigrator(); + myMigrationStorageSvc.insertLockRecord(description); + + try { + migrator.migrate(); + fail(); + } catch (HapiMigrationException e) { + assertEquals("HAPI-2153: Unable to obtain table lock - another database migration may be running. If no other database migration is running, then the previous migration did not shut down properly and the lock record needs to be deleted manually. The lock record is located in the TEST_MIGRATOR_TABLE table with INSTALLED_RANK = -100 and DESCRIPTION = " + description, e.getMessage()); + } + } + + @Test + void test_oldLockWithSystemProperty_cleared() { + HapiMigrationLock.setMaxRetryAttempts(0); + String description = UUID.randomUUID().toString(); + HapiMigrator migrator = buildMigrator(new NopTask("1", "1")); + myMigrationStorageSvc.insertLockRecord(description); + + System.setProperty(HapiMigrationLock.CLEAR_LOCK_TABLE_WITH_DESCRIPTION, description); + + MigrationResult result = migrator.migrate(); + assertThat(result.succeededTasks, hasSize(1)); + } + + + private int countLockRecords() { + return myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME + " WHERE \"installed_rank\" = " + HapiMigrationLock.LOCK_PID, Integer.class); + } + @Nonnull - private HapiMigrator buildMigrator(LatchMigrationTask theLatchMigrationTask) { + private HapiMigrator buildMigrator(BaseTask... theTasks) { HapiMigrator retval = buildMigrator(); - retval.addTask(theLatchMigrationTask); + for (BaseTask next : theTasks) { + retval.addTask(next); + } return retval; } diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml index 66d907374b1..48b4ae31e66 100644 --- a/hapi-fhir-storage-batch2-jobs/pom.xml +++ b/hapi-fhir-storage-batch2-jobs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidator.java b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidator.java index 61179319cde..cf695ecd5aa 100644 --- a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidator.java +++ b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidator.java @@ -43,11 +43,8 @@ public class BulkExportJobParametersValidator implements IJobParametersValidator List errorMsgs = new ArrayList<>(); // initial validation - - if (theParameters.getResourceTypes() == null || theParameters.getResourceTypes().isEmpty()) { - errorMsgs.add("Resource Types are required for an export job."); - } - else { + List resourceTypes = theParameters.getResourceTypes(); + if (resourceTypes != null && !resourceTypes.isEmpty()) { for (String resourceType : theParameters.getResourceTypes()) { if (resourceType.equalsIgnoreCase("Binary")) { errorMsgs.add("Bulk export of Binary resources is forbidden"); diff --git a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java index 1560638dfa0..d512e8c79e0 100644 --- a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java +++ b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java @@ -31,6 +31,7 @@ import ca.uhn.fhir.batch2.jobs.export.models.BulkExportJobParameters; import ca.uhn.fhir.batch2.jobs.models.Id; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.bulk.export.api.IBulkExportProcessor; import ca.uhn.fhir.jpa.bulk.export.model.ExportPIDIteratorParameters; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; diff --git a/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidatorTest.java b/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidatorTest.java index d03ba0ade23..16179fda782 100644 --- a/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidatorTest.java +++ b/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/export/BulkExportJobParametersValidatorTest.java @@ -130,7 +130,7 @@ public class BulkExportJobParametersValidatorTest { } @Test - public void validate_omittedResourceTypes_returnsErrorMessages() { + public void validate_omittedResourceTypes_returnsNoErrorMessages() { // setup BulkExportJobParameters parameters = createSystemExportParameters(); parameters.setResourceTypes(null); @@ -140,8 +140,7 @@ public class BulkExportJobParametersValidatorTest { // verify assertNotNull(results); - assertEquals(1, results.size()); - assertTrue(results.contains("Resource Types are required for an export job.")); + assertEquals(0, results.size()); } @Test diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index 1b6ba40bef2..c2cf092ed43 100644 --- a/hapi-fhir-storage-batch2/pom.xml +++ b/hapi-fhir-storage-batch2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImpl.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImpl.java index 4466e4df3a5..00e822465fd 100644 --- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImpl.java +++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImpl.java @@ -96,14 +96,9 @@ public class JobCoordinatorImpl implements IJobCoordinator { if (isBlank(paramsString)) { throw new InvalidRequestException(Msg.code(2065) + "No parameters supplied"); } - // if cache - use that first if (theStartRequest.isUseCache()) { - FetchJobInstancesRequest request = new FetchJobInstancesRequest(theStartRequest.getJobDefinitionId(), theStartRequest.getParameters(), - StatusEnum.QUEUED, - StatusEnum.IN_PROGRESS, - StatusEnum.COMPLETED - ); + FetchJobInstancesRequest request = new FetchJobInstancesRequest(theStartRequest.getJobDefinitionId(), theStartRequest.getParameters(), getStatesThatTriggerCache()); List existing = myJobPersistence.fetchInstances(request, 0, 1000); if (!existing.isEmpty()) { @@ -142,6 +137,13 @@ public class JobCoordinatorImpl implements IJobCoordinator { return response; } + /** + * Cache will be used if an identical job is QUEUED or IN_PROGRESS. Otherwise a new one will kickoff. + */ + private StatusEnum[] getStatesThatTriggerCache() { + return new StatusEnum[]{StatusEnum.QUEUED, StatusEnum.IN_PROGRESS}; + } + @Override public JobInstance getInstance(String theInstanceId) { return myJobQuerySvc.fetchInstance(theInstanceId); diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java index 6572c4742d1..24ad9149e81 100644 --- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java +++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java @@ -42,6 +42,7 @@ import java.util.Arrays; import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -151,9 +152,10 @@ public class JobCoordinatorImplTest extends BaseBatch2Test { } @Test - public void startInstance_usingExistingCache_returnsExistingJobFirst() { + public void startInstance_usingExistingCache_returnsExistingIncompleteJobFirst() { // setup - String instanceId = "completed-id"; + String completedInstanceId = "completed-id"; + String inProgressInstanceId = "someId"; JobInstanceStartRequest startRequest = new JobInstanceStartRequest(); startRequest.setJobDefinitionId(JOB_DEFINITION_ID); startRequest.setUseCache(true); @@ -162,32 +164,32 @@ public class JobCoordinatorImplTest extends BaseBatch2Test { JobDefinition def = createJobDefinition(); JobInstance existingInProgInstance = createInstance(); - existingInProgInstance.setInstanceId("someId"); + existingInProgInstance.setInstanceId(inProgressInstanceId); existingInProgInstance.setStatus(StatusEnum.IN_PROGRESS); + JobInstance existingCompletedInstance = createInstance(); existingCompletedInstance.setStatus(StatusEnum.COMPLETED); - existingCompletedInstance.setInstanceId(instanceId); + existingCompletedInstance.setInstanceId(completedInstanceId); // when when(myJobDefinitionRegistry.getLatestJobDefinition(eq(JOB_DEFINITION_ID))) .thenReturn(Optional.of(def)); when(myJobInstancePersister.fetchInstances(any(FetchJobInstancesRequest.class), anyInt(), anyInt())) - .thenReturn(Arrays.asList(existingInProgInstance, existingCompletedInstance)); + .thenReturn(Arrays.asList(existingInProgInstance)); // test Batch2JobStartResponse startResponse = mySvc.startInstance(startRequest); // verify - assertEquals(instanceId, startResponse.getJobId()); // make sure it's the completed one + assertEquals(inProgressInstanceId, startResponse.getJobId()); // make sure it's the completed one assertTrue(startResponse.isUsesCachedResult()); ArgumentCaptor requestArgumentCaptor = ArgumentCaptor.forClass(FetchJobInstancesRequest.class); verify(myJobInstancePersister) .fetchInstances(requestArgumentCaptor.capture(), anyInt(), anyInt()); FetchJobInstancesRequest req = requestArgumentCaptor.getValue(); - assertEquals(3, req.getStatuses().size()); + assertEquals(2, req.getStatuses().size()); assertTrue( - req.getStatuses().contains(StatusEnum.COMPLETED) - && req.getStatuses().contains(StatusEnum.IN_PROGRESS) + req.getStatuses().contains(StatusEnum.IN_PROGRESS) && req.getStatuses().contains(StatusEnum.QUEUED) ); } diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index 0cc54962563..5abca8298d7 100644 --- a/hapi-fhir-storage-mdm/pom.xml +++ b/hapi-fhir-storage-mdm/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage-mdm/src/main/java/ca/uhn/fhir/mdm/batch2/MdmBatch2Config.java b/hapi-fhir-storage-mdm/src/main/java/ca/uhn/fhir/mdm/batch2/MdmBatch2Config.java index 51720a90d9b..3eb1ac9f7b4 100644 --- a/hapi-fhir-storage-mdm/src/main/java/ca/uhn/fhir/mdm/batch2/MdmBatch2Config.java +++ b/hapi-fhir-storage-mdm/src/main/java/ca/uhn/fhir/mdm/batch2/MdmBatch2Config.java @@ -51,6 +51,6 @@ public class MdmBatch2Config { JobDefinition clearJobDefinition = myApplicationContext.getBean(MDM_CLEAR_JOB_BEAN_NAME, JobDefinition.class); myJobDefinitionRegistry.addJobDefinitionIfNotRegistered(clearJobDefinition); JobDefinition submitJobDefinition = myApplicationContext.getBean(MDM_SUBMIT_JOB_BEAN_NAME, JobDefinition.class); - myJobDefinitionRegistry.addJobDefinitionIfNotRegistered(clearJobDefinition); + myJobDefinitionRegistry.addJobDefinitionIfNotRegistered(submitJobDefinition); } } diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index 76f9b766ddd..00afd3a83ea 100644 --- a/hapi-fhir-storage-test-utilities/pom.xml +++ b/hapi-fhir-storage-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml 4.0.0 diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index 3002598eb2b..3ab139e591b 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/bulk/export/provider/BulkDataExportProvider.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/bulk/export/provider/BulkDataExportProvider.java index 21596f30d72..f43dc089261 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/bulk/export/provider/BulkDataExportProvider.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/bulk/export/provider/BulkDataExportProvider.java @@ -26,6 +26,7 @@ import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.model.Batch2JobInfo; import ca.uhn.fhir.jpa.api.model.Batch2JobOperationResult; import ca.uhn.fhir.jpa.api.model.BulkExportJobResults; @@ -68,6 +69,7 @@ import org.springframework.beans.factory.annotation.Autowired; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -100,6 +102,9 @@ public class BulkDataExportProvider { @Autowired private DaoConfig myDaoConfig; + @Autowired + private DaoRegistry myDaoRegistry; + /** * $export */ @@ -136,6 +141,13 @@ public class BulkDataExportProvider { // Set the original request URL as part of the job information, as this is used in the poll-status-endpoint, and is needed for the report. parameters.setOriginalRequestUrl(theRequestDetails.getCompleteUrl()); + // If no _type parameter is provided, default to all resource types except Binary + if (theOptions.getResourceTypes() == null || theOptions.getResourceTypes().isEmpty()) { + List resourceTypes = new ArrayList<>(myDaoRegistry.getRegisteredDaoTypes()); + resourceTypes.remove("Binary"); + parameters.setResourceTypes(resourceTypes); + } + // start job Batch2JobStartResponse response = myJobRunner.startNewJob(parameters); @@ -486,4 +498,9 @@ public class BulkDataExportProvider { public void setDaoConfig(DaoConfig theDaoConfig) { myDaoConfig = theDaoConfig; } + + @VisibleForTesting + public void setDaoRegistry(DaoRegistry theDaoRegistry) { + myDaoRegistry = theDaoRegistry; + } } diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index 7fb29f3b479..ce2d5de8f96 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 1ab9b676a87..18b841b3c98 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index e870ec9b19a..8012d551911 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java index c7b3015047f..9813efc5694 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java @@ -136,7 +136,7 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory { if (httpVerb != null) { entry.getRequest().getMethodElement().setValueAsString(httpVerb); if (id != null) { - entry.getRequest().setUrl(id.getValue()); + entry.getRequest().setUrl(id.toUnqualified().getValue()); } } if ("DELETE".equals(httpVerb)) { diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index a0888be5bad..61133ecaeaa 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index 299b268d308..c0d7fa43908 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java index 893bf9e86c3..d80fca6b4ed 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/R4BundleFactory.java @@ -138,7 +138,7 @@ public class R4BundleFactory implements IVersionSpecificBundleFactory { if (httpVerb != null) { entry.getRequest().getMethodElement().setValueAsString(httpVerb); if (id != null) { - entry.getRequest().setUrl(id.getValue()); + entry.getRequest().setUrl(id.toUnqualified().getValue()); } } if ("DELETE".equals(httpVerb)) { diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingTest.java index 6f4f1ee87b2..47b0352e606 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PagingTest.java @@ -146,6 +146,37 @@ public class PagingTest { } } + @Test() + public void testSendingSameRequestConsecutivelyResultsInSameResponse() throws Exception { + initBundleProvider(10); + myServerExtension.getRestfulServer().registerProvider(new DummyPatientResourceProvider()); + myServerExtension.getRestfulServer().setPagingProvider(pagingProvider); + + when(pagingProvider.canStoreSearchResults()).thenReturn(true); + when(pagingProvider.getDefaultPageSize()).thenReturn(10); + when(pagingProvider.getMaximumPageSize()).thenReturn(50); + when(pagingProvider.storeResultList(any(RequestDetails.class), any(IBundleProvider.class))).thenReturn("ABCD"); + when(pagingProvider.retrieveResultList(any(RequestDetails.class), anyString())).thenReturn(ourBundleProvider); + + String nextLink; + String base = "http://localhost:" + myServerExtension.getPort(); + HttpGet get = new HttpGet(base + "/Patient?_getpagesoffset=10"); + String responseContent; + try (CloseableHttpResponse resp = ourClient.execute(get)) { + assertEquals(200, resp.getStatusLine().getStatusCode()); + responseContent = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + + Bundle bundle = ourContext.newJsonParser().parseResource(Bundle.class, responseContent); + assertEquals(0, bundle.getEntry().size()); + } + try (CloseableHttpResponse resp = ourClient.execute(get)) { + assertEquals(200, resp.getStatusLine().getStatusCode()); + responseContent = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8); + + Bundle bundle = ourContext.newJsonParser().parseResource(Bundle.class, responseContent); + assertEquals(0, bundle.getEntry().size()); + } + } private void checkParam(String theUri, String theCheckedParam, String theExpectedValue) { Optional paramValue = URLEncodedUtils.parse(theUri, CHARSET_UTF8).stream() .filter(nameValuePair -> nameValuePair.getName().equals(theCheckedParam)) diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml index f8e1975157b..684b3326585 100644 --- a/hapi-fhir-structures-r4b/pom.xml +++ b/hapi-fhir-structures-r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4b/src/main/java/org/hl7/fhir/r4b/hapi/rest/server/R4BBundleFactory.java b/hapi-fhir-structures-r4b/src/main/java/org/hl7/fhir/r4b/hapi/rest/server/R4BBundleFactory.java index fc1ee804e61..2a1c7f7d910 100644 --- a/hapi-fhir-structures-r4b/src/main/java/org/hl7/fhir/r4b/hapi/rest/server/R4BBundleFactory.java +++ b/hapi-fhir-structures-r4b/src/main/java/org/hl7/fhir/r4b/hapi/rest/server/R4BBundleFactory.java @@ -138,7 +138,7 @@ public class R4BBundleFactory implements IVersionSpecificBundleFactory { if (httpVerb != null) { entry.getRequest().getMethodElement().setValueAsString(httpVerb); if (id != null) { - entry.getRequest().setUrl(id.getValue()); + entry.getRequest().setUrl(id.toUnqualified().getValue()); } } if ("DELETE".equals(httpVerb)) { diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 99903f06a14..5b650763736 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java index 2bc8bac0c48..47d6f1b4fa2 100644 --- a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java +++ b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/rest/server/R5BundleFactory.java @@ -138,7 +138,7 @@ public class R5BundleFactory implements IVersionSpecificBundleFactory { if (httpVerb != null) { entry.getRequest().getMethodElement().setValueAsString(httpVerb); if (id != null) { - entry.getRequest().setUrl(id.getValue()); + entry.getRequest().setUrl(id.toUnqualified().getValue()); } } if ("DELETE".equals(httpVerb)) { diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index 5df3a925631..3e62baf3581 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index e4474237130..395d44fb36b 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index c2a1a7eb6eb..1270d1ad574 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 1cda9139883..dc201566889 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 6570d325bd4..c62b00d908f 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index ddf5804120e..5d7a57d989d 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index 5abcf27bd4a..6768c96a0d7 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index e6bf11151fc..64869c2ca5c 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index e8250473245..f70a6ef5f7e 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 3700638251c..3f99e8a50e5 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 8eadeea9c1f..c68f07bb811 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. https://hapifhir.io @@ -1083,6 +1083,13 @@ okhttp ${okhttp_version} + + + com.squareup.okio + okio-jvm + 3.2.0 + + com.sun.activation javax.activation @@ -2063,7 +2070,7 @@ ca.uhn.hapi.fhir hapi-fhir-checkstyle - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index b247541c7a6..96ab6543e2c 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index 2277e49cecc..fba882bfbb0 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index 5f60aff00de..24cdaae6511 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.0-PRE2-SNAPSHOT + 6.3.0-PRE3-SNAPSHOT ../../pom.xml