diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..2ec819d6f47 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.java] +charset = utf-8 +indent_style = tab diff --git a/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml b/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml index 67a22ce7c0b..c6e01302dab 100644 --- a/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml +++ b/example-projects/hapi-fhir-base-example-embedded-ws/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir 2.3-SNAPSHOT - ../hapi-deployable-pom/pom.xml + ../../pom.xml jar diff --git a/example-projects/hapi-fhir-standalone-overlay-example/pom.xml b/example-projects/hapi-fhir-standalone-overlay-example/pom.xml index 9ac05ee26c8..2cf09371dd2 100644 --- a/example-projects/hapi-fhir-standalone-overlay-example/pom.xml +++ b/example-projects/hapi-fhir-standalone-overlay-example/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir 2.3-SNAPSHOT - ../hapi-deployable-pom/pom.xml + ../../pom.xml hapi-fhir-standalone-overlay-example diff --git a/examples/src/main/java/example/ClientTransactionExamples.java b/examples/src/main/java/example/ClientTransactionExamples.java index 790008bc66c..f7c3aff790b 100644 --- a/examples/src/main/java/example/ClientTransactionExamples.java +++ b/examples/src/main/java/example/ClientTransactionExamples.java @@ -70,7 +70,7 @@ public class ClientTransactionExamples { .setResource(patient) .getRequest() .setUrl("Patient") - .setIfNoneExist("Patient?identifier=http://acme.org/mrns|12345") + .setIfNoneExist("identifier=http://acme.org/mrns|12345") .setMethod(HTTPVerbEnum.POST); // Add the observation. This entry is a POST with no header diff --git a/examples/src/main/java/example/PagingPatientProvider.java b/examples/src/main/java/example/PagingPatientProvider.java index ab398a3679a..ce70e046e76 100644 --- a/examples/src/main/java/example/PagingPatientProvider.java +++ b/examples/src/main/java/example/PagingPatientProvider.java @@ -60,6 +60,11 @@ public class PagingPatientProvider implements IResourceProvider { // Typically this method just returns null return null; } + + @Override + public String getUuid() { + return null; + } }; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java index dae8c9d3dfb..77fd2f2ec57 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HistoryMethodBinding.java @@ -171,7 +171,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding { return new IBundleProvider() { @Override - public InstantDt getPublished() { + public IPrimitiveType getPublished() { return resources.getPublished(); } @@ -202,7 +202,12 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding { @Override public Integer preferredPageSize() { - return null; + return resources.preferredPageSize(); + } + + @Override + public String getUuid() { + return resources.getUuid(); } }; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java index 2c2289a10c5..fe0fde123ad 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java @@ -14,7 +14,7 @@ import ca.uhn.fhir.context.FhirContext; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -48,7 +48,7 @@ abstract class BaseParam implements IQueryParameterType { public Boolean getMissing() { return myMissing; } - + @Override public final String getQueryParameterQualifier() { if (myMissing != null && myMissing.booleanValue()) { @@ -73,8 +73,8 @@ abstract class BaseParam implements IQueryParameterType { } /** - * If set to non-null value, indicates that this parameter has been populated - * with a "[name]:missing=true" or "[name]:missing=false" vale instead of a + * If set to non-null value, indicates that this parameter has been populated + * with a "[name]:missing=true" or "[name]:missing=false" vale instead of a * normal value * * @return Returns a reference to this for easier method chaining @@ -97,10 +97,10 @@ abstract class BaseParam implements IQueryParameterType { throw new InvalidRequestException(msg); } } - + myMissing = null; doSetValueAsQueryToken(theContext, theParamName, theQualifier, theValue); } } - + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java index 868b521bf3e..17e4730a39e 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.param; import static org.apache.commons.lang3.StringUtils.defaultString; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -32,17 +33,26 @@ import ca.uhn.fhir.rest.server.Constants; public class StringParam extends BaseParam implements IQueryParameterType { + private boolean myContains; private boolean myExact; private String myValue; - private boolean myContains; - + + /** + * Constructor + */ public StringParam() { } + /** + * Constructor + */ public StringParam(String theValue) { setValue(theValue); } + /** + * Constructor + */ public StringParam(String theValue, boolean theExact) { setValue(theValue); setExact(theExact); @@ -79,6 +89,29 @@ public class StringParam extends BaseParam implements IQueryParameterType { myValue = ParameterUtil.unescape(theValue); } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof StringParam)) { + return false; + } + + StringParam other = (StringParam) obj; + + EqualsBuilder eb = new EqualsBuilder(); + eb.append(myExact, other.myExact); + eb.append(myContains, other.myContains); + eb.append(myValue, other.myValue); + eb.append(getMissing(), other.getMissing()); + + return eb.isEquals(); + } + public String getValue() { return myValue; } @@ -91,6 +124,13 @@ public class StringParam extends BaseParam implements IQueryParameterType { return defaultString(myValue); } + /** + * String parameter modifier :contains + */ + public boolean isContains() { + return myContains; + } + public boolean isEmpty() { return StringUtils.isEmpty(myValue); } @@ -99,6 +139,18 @@ public class StringParam extends BaseParam implements IQueryParameterType { return myExact; } + /** + * String parameter modifier :contains + */ + public StringParam setContains(boolean theContains) { + myContains = theContains; + if (myContains) { + setExact(false); + setMissing(null); + } + return this; + } + public StringParam setExact(boolean theExact) { myExact = theExact; if (myExact) { @@ -108,13 +160,6 @@ public class StringParam extends BaseParam implements IQueryParameterType { return this; } - /** - * String parameter modifier :contains - */ - public boolean isContains() { - return myContains; - } - public StringParam setValue(String theValue) { myValue = theValue; return this; @@ -136,16 +181,4 @@ public class StringParam extends BaseParam implements IQueryParameterType { return builder.toString(); } - /** - * String parameter modifier :contains - */ - public StringParam setContains(boolean theContains) { - myContains = theContains; - if (myContains) { - setExact(false); - setMissing(null); - } - return this; - } - } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BasePagingProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BasePagingProvider.java new file mode 100644 index 00000000000..d91c97129d6 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BasePagingProvider.java @@ -0,0 +1,36 @@ +package ca.uhn.fhir.rest.server; + +import org.apache.commons.lang3.Validate; + +public abstract class BasePagingProvider implements IPagingProvider { + + private int myDefaultPageSize = 10; + private int myMaximumPageSize = 50; + + public BasePagingProvider() { + super(); + } + + @Override + public int getDefaultPageSize() { + return myDefaultPageSize; + } + + @Override + public int getMaximumPageSize() { + return myMaximumPageSize; + } + + public BasePagingProvider setDefaultPageSize(int theDefaultPageSize) { + Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0"); + myDefaultPageSize = theDefaultPageSize; + return this; + } + + public BasePagingProvider setMaximumPageSize(int theMaximumPageSize) { + Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0"); + myMaximumPageSize = theMaximumPageSize; + return this; + } + +} \ No newline at end of file diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BundleProviders.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BundleProviders.java index 7f5b6bf462b..32027e57bde 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BundleProviders.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/BundleProviders.java @@ -64,6 +64,11 @@ public class BundleProviders { public Integer preferredPageSize() { return null; } + + @Override + public String getUuid() { + return null; + } }; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java index b33612f15e1..08dbda0b015 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/FifoMemoryPagingProvider.java @@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -25,11 +25,9 @@ import java.util.UUID; import org.apache.commons.lang3.Validate; -public class FifoMemoryPagingProvider implements IPagingProvider { +public class FifoMemoryPagingProvider extends BasePagingProvider implements IPagingProvider { private LinkedHashMap myBundleProviders; - private int myDefaultPageSize=10; - private int myMaximumPageSize=50; private int mySize; public FifoMemoryPagingProvider(int theSize) { @@ -39,33 +37,11 @@ public class FifoMemoryPagingProvider implements IPagingProvider { myBundleProviders = new LinkedHashMap(mySize); } - @Override - public int getDefaultPageSize() { - return myDefaultPageSize; - } - - @Override - public int getMaximumPageSize() { - return myMaximumPageSize; - } - @Override public synchronized IBundleProvider retrieveResultList(String theId) { return myBundleProviders.get(theId); } - public FifoMemoryPagingProvider setDefaultPageSize(int theDefaultPageSize) { - Validate.isTrue(theDefaultPageSize > 0, "size must be greater than 0"); - myDefaultPageSize = theDefaultPageSize; - return this; - } - - public FifoMemoryPagingProvider setMaximumPageSize(int theMaximumPageSize) { - Validate.isTrue(theMaximumPageSize > 0, "size must be greater than 0"); - myMaximumPageSize = theMaximumPageSize; - return this; - } - @Override public synchronized String storeResultList(IBundleProvider theList) { while (myBundleProviders.size() > mySize) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IBundleProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IBundleProvider.java index c833a3b0cba..71c7eae09fb 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IBundleProvider.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IBundleProvider.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.rest.server; +import java.util.Date; + /* * #%L * HAPI FHIR - Core Library @@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.server; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,6 +25,7 @@ package ca.uhn.fhir.rest.server; import java.util.List; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import ca.uhn.fhir.model.primitive.InstantDt; @@ -31,15 +34,17 @@ public interface IBundleProvider { /** * Load the given collection of resources by index, plus any additional resources per the * server's processing rules (e.g. _include'd resources, OperationOutcome, etc.). For example, - * if the method is invoked with index 0,10 the method might return 10 search results, plus an + * if the method is invoked with index 0,10 the method might return 10 search results, plus an * additional 20 resources which matched a client's _include specification. * - * @param theFromIndex The low index (inclusive) to return - * @param theToIndex The high index (exclusive) to return + * @param theFromIndex + * The low index (inclusive) to return + * @param theToIndex + * The high index (exclusive) to return * @return A list of resources. The size of this list must be at least theToIndex - theFromIndex. */ List getResources(int theFromIndex, int theToIndex); - + /** * Optionally may be used to signal a preferred page size to the server, e.g. because * the implementing code recognizes that the resources which will be returned by this @@ -50,16 +55,31 @@ public interface IBundleProvider { * @return Returns the preferred page size or null */ Integer preferredPageSize(); - + /** * Returns the total number of results which match the given query (exclusive of any * _include's or OperationOutcome) */ int size(); - + /** * Returns the instant as of which this result was valid */ - InstantDt getPublished(); + IPrimitiveType getPublished(); + + /** + * Returns the UUID associated with this search. Note that this + * does not need to return a non-null value unless it a + * {@link IPagingProvider} is being used that requires UUIDs + * being returned. + *

+ * In other words, if you are using the default {@link FifoMemoryPagingProvider} in + * your server, it is fine for this method to simply return {@code null} since {@link FifoMemoryPagingProvider} + * does not use the value anyhow. On the other hand, if you are creating a custom + * [@code IPagingProvider} implementation you might use this method to communicate + * the search ID back to the provider. + *

+ */ + public String getUuid(); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IResourceProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IResourceProvider.java index 8d5db9d99e5..35fbf8b240e 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IResourceProvider.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IResourceProvider.java @@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SimpleBundleProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SimpleBundleProvider.java index 58e9803c3de..d457d86c972 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SimpleBundleProvider.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/SimpleBundleProvider.java @@ -65,5 +65,10 @@ public class SimpleBundleProvider implements IBundleProvider { public Integer preferredPageSize() { return null; } + + @Override + public String getUuid() { + return null; + } } diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties index 636b56fc038..c8aa3a30c30 100644 --- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties +++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties @@ -67,6 +67,7 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionEntryHasInvalidVerb=Transac ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided. ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1} +ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.cantValidateWithNoResource=No resource supplied for $validate operation (resource is required unless mode is \"delete\") ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithInvalidId=Can not process entity with ID[{0}], this is not a valid FHIR ID ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.incorrectResourceType=Incorrect resource type detected for endpoint, found {0} but expected {1} diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/StringParamTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/StringParamTest.java new file mode 100644 index 00000000000..f19fa54bf58 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/StringParamTest.java @@ -0,0 +1,19 @@ +package ca.uhn.fhir.rest.param; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class StringParamTest { + + @Test + public void testEquals() { + StringParam input = new StringParam("foo", true); + + assertTrue(input.equals(input)); + assertFalse(input.equals(null)); + assertFalse(input.equals("")); + assertFalse(input.equals(new StringParam("foo", false))); + } + +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 9965a51e88b..22e67de435f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -11,7 +11,7 @@ import static org.apache.commons.lang3.StringUtils.defaultIfBlank; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -335,7 +335,7 @@ public abstract class BaseHapiFhirDao implements IDao { continue; } } - + Class type = resourceDefinition.getImplementingClass(); String id = nextId.getIdPart(); if (StringUtils.isBlank(id)) { @@ -677,18 +677,19 @@ public abstract class BaseHapiFhirDao implements IDao { theRequestDetails.getUserData().put(PROCESSING_SUB_REQUEST, Boolean.TRUE); } } - + protected void notifyInterceptors(RestOperationTypeEnum theOperationType, ActionRequestDetails theRequestDetails) { if (theRequestDetails.getId() != null && theRequestDetails.getId().hasResourceType() && isNotBlank(theRequestDetails.getResourceType())) { if (theRequestDetails.getId().getResourceType().equals(theRequestDetails.getResourceType()) == false) { - throw new InternalErrorException("Inconsistent server state - Resource types don't match: " + theRequestDetails.getId().getResourceType() + " / " + theRequestDetails.getResourceType()); + throw new InternalErrorException( + "Inconsistent server state - Resource types don't match: " + theRequestDetails.getId().getResourceType() + " / " + theRequestDetails.getResourceType()); } } if (theRequestDetails.getUserData().get(PROCESSING_SUB_REQUEST) == Boolean.TRUE) { theRequestDetails.notifyIncomingRequestPreHandled(theOperationType); } - + List interceptors = getConfig().getInterceptors(); if (interceptors == null) { return; @@ -779,7 +780,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setHasTags(true); } } - + ArrayList existingTags = new ArrayList(); if (theEntity.isHasTags()) { existingTags.addAll(theEntity.getTags()); @@ -937,9 +938,9 @@ public abstract class BaseHapiFhirDao implements IDao { * Subclasses may override to provide behaviour. Called when a resource has been inserted into the database for the first time. * * @param theEntity - * The entity being updated (Do not modify the entity! Undefined behaviour will occur!) + * The entity being updated (Do not modify the entity! Undefined behaviour will occur!) * @param theTag - * The tag + * The tag * @return Returns true if the tag should be removed */ @SuppressWarnings("unused") @@ -951,9 +952,9 @@ public abstract class BaseHapiFhirDao implements IDao { * Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database * * @param theEntity - * The resource + * The resource * @param theResource - * The resource being persisted + * The resource being persisted */ protected void postUpdate(ResourceTable theEntity, T theResource) { // nothing @@ -1009,9 +1010,9 @@ public abstract class BaseHapiFhirDao implements IDao { *

* * @param theEntity - * The entity being updated (Do not modify the entity! Undefined behaviour will occur!) + * The entity being updated (Do not modify the entity! Undefined behaviour will occur!) * @param theTag - * The tag + * The tag * @return Retturns true if the tag should be removed */ protected boolean shouldDroppedTagBeRemovedOnUpdate(ResourceTable theEntity, ResourceTag theTag) { @@ -1072,7 +1073,7 @@ public abstract class BaseHapiFhirDao implements IDao { } } } - + IParser parser = theEntity.getEncoding().newParser(getContext(theEntity.getFhirVersion())); R retVal; try { @@ -1241,7 +1242,8 @@ public abstract class BaseHapiFhirDao implements IDao { } /* - * Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the matching + * Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the + * matching * resource. */ if (myConfig.isAllowInlineMatchUrlReferences()) { @@ -1437,7 +1439,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setResourceLinks(links); theEntity.toString(); - + } // if thePerformIndexing theEntity = myEntityManager.merge(theEntity); @@ -1538,9 +1540,9 @@ public abstract class BaseHapiFhirDao implements IDao { * "subsetted" tag and rejects resources which have it. Subclasses should call the superclass implementation to preserve this check. * * @param theResource - * The resource that is about to be persisted + * The resource that is about to be persisted * @param theEntityToSave - * TODO + * TODO */ protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) { Object tag = null; @@ -1747,7 +1749,7 @@ public abstract class BaseHapiFhirDao implements IDao { paramMap.add(nextParamName, param); continue; } - + if (Constants.PARAM_COUNT.equals(nextParamName)) { if (paramList.size() > 0 && paramList.get(0).size() > 0) { String intString = paramList.get(0).get(0); @@ -1772,7 +1774,8 @@ public abstract class BaseHapiFhirDao implements IDao { } else { RuntimeSearchParam paramDef = theCallingDao.getSearchParamByName(resourceDef, nextParamName); if (paramDef == null) { - throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName); + throw new InvalidRequestException( + "Failed to parse match URL[" + theMatchUrl + "] - Resource type " + resourceDef.getName() + " does not have a parameter with name: " + nextParamName); } IQueryParameterAnd param = MethodUtil.parseQueryParams(theContext, paramDef, nextParamName, paramList); 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 446534ad694..880cd96e91e 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 @@ -192,7 +192,7 @@ public abstract class BaseHapiFhirResourceDao extends B validateOkToDelete(deleteConflicts, entity); - preDelete(resourceToDelete); + preDelete(resourceToDelete, entity); // Notify interceptors if (theRequestDetails != null) { @@ -722,7 +722,8 @@ public abstract class BaseHapiFhirResourceDao extends B * Subclasses may override to provide behaviour. Invoked within a delete * transaction with the resource that is about to be deleted. */ - protected void preDelete(T theResourceToDelete) { + @SuppressWarnings("unused") + protected void preDelete(T theResourceToDelete, ResourceTable theEntityToDelete) { // nothing by default } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseSearchParamRegistry.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseSearchParamRegistry.java index 8b2cb87df03..8608d26e428 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseSearchParamRegistry.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseSearchParamRegistry.java @@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,7 +27,6 @@ import java.util.Map; import javax.annotation.PostConstruct; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Validate; import org.springframework.beans.factory.annotation.Autowired; @@ -37,8 +36,6 @@ import ca.uhn.fhir.context.RuntimeSearchParam; public abstract class BaseSearchParamRegistry implements ISearchParamRegistry { - private static final Map EMPTY_SP_MAP = Collections.emptyMap(); - private Map> myBuiltInSearchParams; @Autowired @@ -56,27 +53,32 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry { // nothing by default } - public Map> getBuiltInSearchParams() { + @Override + public Map> getActiveSearchParams() { return myBuiltInSearchParams; } @Override - public Map getActiveSearchParams(String theResourceName) { + public Map getActiveSearchParams(String theResourceName) { Validate.notBlank(theResourceName, "theResourceName must not be blank or null"); return myBuiltInSearchParams.get(theResourceName); } + public Map> getBuiltInSearchParams() { + return myBuiltInSearchParams; + } + @PostConstruct public void postConstruct() { - Map> resourceNameToSearchParams = new HashMap>(); + Map> resourceNameToSearchParams = new HashMap>(); for (IFhirResourceDao nextDao : myDaos) { RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType()); String nextResourceName = nextResDef.getName(); HashMap nameToParam = new HashMap(); resourceNameToSearchParams.put(nextResourceName, nameToParam); - + for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) { nameToParam.put(nextSp.getName(), nextSp); } @@ -85,13 +87,4 @@ public abstract class BaseSearchParamRegistry implements ISearchParamRegistry { myBuiltInSearchParams = Collections.unmodifiableMap(resourceNameToSearchParams); } - @Override - public Collection getAllSearchParams(String theResourceName) { - Validate.notBlank(theResourceName, "theResourceName must not be null or blank"); - - Map map = myBuiltInSearchParams.get(theResourceName); - map = ObjectUtils.defaultIfNull(map, EMPTY_SP_MAP); - return Collections.unmodifiableCollection(map.values()); - } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java index 34b82976b90..62ae1312e66 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java @@ -56,6 +56,7 @@ import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.FhirTerser; @@ -133,8 +134,11 @@ public class FhirResourceDaoDstu2 extends BaseHapiFhirResou ValidationResult result; if (isNotBlank(theRawResource)) { result = validator.validateWithResult(theRawResource); - } else { + } else if (theResource != null) { result = validator.validateWithResult(theResource); + } else { + String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "cantValidateWithNoResource"); + throw new InvalidRequestException(msg); } if (result.isSuccessful()) { @@ -160,11 +164,11 @@ public class FhirResourceDaoDstu2 extends BaseHapiFhirResou boolean hasId = theCtx.getResource().getIdElement().hasIdPart(); if (myMode == ValidationModeEnum.CREATE) { if (hasId) { - throw new InvalidRequestException("Resource has an ID - ID must not be populated for a FHIR create"); + throw new UnprocessableEntityException("Resource has an ID - ID must not be populated for a FHIR create"); } } else if (myMode == ValidationModeEnum.UPDATE) { if (hasId == false) { - throw new InvalidRequestException("Resource has no ID - ID must be populated for a FHIR update"); + throw new UnprocessableEntityException("Resource has no ID - ID must be populated for a FHIR update"); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchParamRegistry.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchParamRegistry.java index eea349770cd..58a7d489fd0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchParamRegistry.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/ISearchParamRegistry.java @@ -1,36 +1,15 @@ package ca.uhn.fhir.jpa.dao; -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import java.util.Collection; import java.util.Map; import ca.uhn.fhir.context.RuntimeSearchParam; public interface ISearchParamRegistry { - Map getActiveSearchParams(String theResourceName); - - Collection getAllSearchParams(String theResourceName); - void forceRefresh(); + Map> getActiveSearchParams(); + + Map getActiveSearchParams(String theResourceName); + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 3106f9bc0b8..7cff1643bb2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -2309,6 +2309,11 @@ public class SearchBuilder { public int size() { return myPids.size(); } + + @Override + public String getUuid() { + return null; + } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamCoordsDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamCoordsDao.java new file mode 100644 index 00000000000..2bf1e05ab6e --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamCoordsDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords; + +public interface IResourceIndexedSearchParamCoordsDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamDateDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamDateDao.java new file mode 100644 index 00000000000..d4f05ff8c75 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamDateDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate; + +public interface IResourceIndexedSearchParamDateDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamNumberDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamNumberDao.java new file mode 100644 index 00000000000..9385dd17529 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamNumberDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber; + +public interface IResourceIndexedSearchParamNumberDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamQuantityDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamQuantityDao.java new file mode 100644 index 00000000000..e6948e48a28 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamQuantityDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity; + +public interface IResourceIndexedSearchParamQuantityDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamStringDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamStringDao.java new file mode 100644 index 00000000000..7c9b13b500e --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamStringDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString; + +public interface IResourceIndexedSearchParamStringDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamTokenDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamTokenDao.java new file mode 100644 index 00000000000..03813879786 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceIndexedSearchParamTokenDao.java @@ -0,0 +1,29 @@ +package ca.uhn.fhir.jpa.dao.data; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken; + +public interface IResourceIndexedSearchParamTokenDao extends JpaRepository { + // nothing yet +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java index 571c5e06c99..9da4a0c7c92 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java @@ -54,6 +54,7 @@ import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.FhirTerser; @@ -143,7 +144,8 @@ public class FhirResourceDaoDstu3 extends BaseHapiFhirRe if (resourceToValidateById != null) { result = validator.validateWithResult(resourceToValidateById); } else { - throw new InvalidRequestException("No resource supplied for $validate operation (resource is required unless mode is \"delete\")"); + String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "cantValidateWithNoResource"); + throw new InvalidRequestException(msg); } } else if (isNotBlank(theRawResource)) { result = validator.validateWithResult(theRawResource); @@ -180,11 +182,11 @@ public class FhirResourceDaoDstu3 extends BaseHapiFhirRe boolean hasId = theCtx.getResource().getIdElement().hasIdPart(); if (myMode == ValidationModeEnum.CREATE) { if (hasId) { - throw new InvalidRequestException("Resource has an ID - ID must not be populated for a FHIR create"); + throw new UnprocessableEntityException("Resource has an ID - ID must not be populated for a FHIR create"); } } else if (myMode == ValidationModeEnum.UPDATE) { if (hasId == false) { - throw new InvalidRequestException("Resource has no ID - ID must be populated for a FHIR update"); + throw new UnprocessableEntityException("Resource has no ID - ID must be populated for a FHIR update"); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java index f816fe2f6d4..5432daf5206 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java @@ -2,8 +2,6 @@ package ca.uhn.fhir.jpa.dao.dstu3; import static org.apache.commons.lang3.StringUtils.isBlank; -import java.util.List; - /* * #%L * HAPI FHIR JPA Server @@ -34,20 +32,23 @@ import org.springframework.scheduling.annotation.Scheduled; import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter; import ca.uhn.fhir.jpa.dao.IFhirSystemDao; +import ca.uhn.fhir.jpa.dao.ISearchParamRegistry; import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.jpa.util.DeleteConflict; import ca.uhn.fhir.parser.DataFormatException; -import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import ca.uhn.fhir.util.ElementUtil; public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3 implements IFhirResourceDaoSearchParameter { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoSearchParameterDstu3.class); + @Autowired + private ISearchParamRegistry mySearchParamRegistry; + @Autowired private IFhirSystemDao mySystemDao; - private void markAffectedResources(SearchParameter theResource) { + protected void markAffectedResources(SearchParameter theResource) { if (theResource != null) { String expression = theResource.getExpression(); String resourceType = expression.substring(0, expression.indexOf('.')); @@ -55,8 +56,9 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3 return retVal; - // ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion(); + // ValueSetExpansionComponent expansion = outcome.getValueset().getExpansion(); // - // ValueSet retVal = new ValueSet(); - // retVal.getMeta().setLastUpdated(new Date()); - // retVal.setExpansion(expansion); - // return retVal; + // ValueSet retVal = new ValueSet(); + // retVal.getMeta().setLastUpdated(new Date()); + // retVal.setExpansion(expansion); + // return retVal; } private void validateIncludes(String name, List listToValidate) { @@ -137,11 +138,11 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 public ValueSet expand(ValueSet source, String theFilter) { ValueSet toExpand = new ValueSet(); -// for (UriType next : source.getCompose().getInclude()) { -// ConceptSetComponent include = toExpand.getCompose().addInclude(); -// include.setSystem(next.getValue()); -// addFilterIfPresent(theFilter, include); -// } + // for (UriType next : source.getCompose().getInclude()) { + // ConceptSetComponent include = toExpand.getCompose().addInclude(); + // include.setSystem(next.getValue()); + // addFilterIfPresent(theFilter, include); + // } for (ConceptSetComponent next : source.getCompose().getInclude()) { toExpand.getCompose().addInclude(next); @@ -155,18 +156,41 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 toExpand.getCompose().getExclude().addAll(source.getCompose().getExclude()); ValueSet retVal = doExpand(toExpand); + + if (isNotBlank(theFilter)) { + applyFilter(retVal.getExpansion().getTotalElement(), retVal.getExpansion().getContains(), theFilter); + } + return retVal; } + private void applyFilter(IntegerType theTotalElement, List theContains, String theFilter) { + + for (int idx = 0; idx < theContains.size(); idx++) { + ValueSetExpansionContainsComponent next = theContains.get(idx); + if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) { + theContains.remove(idx); + idx--; + if (theTotalElement.getValue() != null) { + theTotalElement.setValue(theTotalElement.getValue() - 1); + } + } + applyFilter(theTotalElement, next.getContains(), theFilter); + } + } + private void addFilterIfPresent(String theFilter, ConceptSetComponent include) { - if (isNotBlank(theFilter)) { - include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter); + if (ElementUtil.isEmpty(include.getConcept())) { + if (isNotBlank(theFilter)) { + include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter); + } } } @Override - public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType theValueSetIdentifier, IIdType theId, IPrimitiveType theCode, IPrimitiveType theSystem, IPrimitiveType theDisplay, Coding theCoding, + public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCode(IPrimitiveType theValueSetIdentifier, IIdType theId, IPrimitiveType theCode, + IPrimitiveType theSystem, IPrimitiveType theDisplay, Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) { List valueSetIds = Collections.emptyList(); @@ -226,7 +250,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 return thePrimitive != null ? thePrimitive.getValue() : null; } - private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List contains, String theSystem, String theCode, Coding theCoding, CodeableConcept theCodeableConcept) { + private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult validateCodeIsInContains(List contains, String theSystem, String theCode, + Coding theCoding, CodeableConcept theCodeableConcept) { for (ValueSetExpansionContainsComponent nextCode : contains) { ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult result = validateCodeIsInContains(nextCode.getContains(), theSystem, theCode, theCoding, theCodeableConcept); if (result != null) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3.java index ed6612fc852..d6f631cbebd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3.java @@ -50,6 +50,7 @@ import org.hl7.fhir.dstu3.model.ContactPoint; import org.hl7.fhir.dstu3.model.DateTimeType; import org.hl7.fhir.dstu3.model.Duration; import org.hl7.fhir.dstu3.model.Enumeration; +import org.hl7.fhir.dstu3.model.Extension; import org.hl7.fhir.dstu3.model.HumanName; import org.hl7.fhir.dstu3.model.Identifier; import org.hl7.fhir.dstu3.model.IntegerType; @@ -520,7 +521,16 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen // } for (Object nextObject : extractValues(nextPath, theResource)) { + + if (nextObject instanceof Extension) { + Extension nextExtension = (Extension)nextObject; + nextObject = nextExtension.getValue(); + } + if (nextObject == null) { + continue; + } + // Patient:language if (nextObject instanceof PatientCommunicationComponent) { PatientCommunicationComponent nextValue = (PatientCommunicationComponent) nextObject; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamRegistryDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamRegistryDstu3.java index 9faf743d56e..2b3b967e2a6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamRegistryDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamRegistryDstu3.java @@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.dao.dstu3; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -35,6 +35,7 @@ import org.apache.commons.lang3.time.DateUtils; import org.hl7.fhir.dstu3.model.CodeType; import org.hl7.fhir.dstu3.model.SearchParameter; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; import org.springframework.beans.factory.annotation.Autowired; import ca.uhn.fhir.context.RuntimeSearchParam; @@ -50,19 +51,43 @@ import ca.uhn.fhir.rest.server.IBundleProvider; public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamRegistryDstu3.class); - @Autowired - private IFhirResourceDao mySpDao; - - private long myLastRefresh; - private volatile Map> myActiveSearchParams; @Autowired private DaoConfig myDaoConfig; + private long myLastRefresh; + + @Autowired + private IFhirResourceDao mySpDao; + + @Override + public void forceRefresh() { + myLastRefresh = 0; + } + + @Override + public Map> getActiveSearchParams() { + refreshCacheIfNeccesary(); + return myActiveSearchParams; + } + @Override public Map getActiveSearchParams(String theResourceName) { + refreshCacheIfNeccesary(); + return myActiveSearchParams.get(theResourceName); + } + private Map getSearchParamMap(Map> searchParams, String theResourceName) { + Map retVal = searchParams.get(theResourceName); + if (retVal == null) { + retVal = new HashMap(); + searchParams.put(theResourceName, retVal); + } + return retVal; + } + + private void refreshCacheIfNeccesary() { long refreshInterval = 60 * DateUtils.MILLIS_PER_MINUTE; if (System.currentTimeMillis() - refreshInterval > myLastRefresh) { StopWatch sw = new StopWatch(); @@ -91,7 +116,7 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry { if (runtimeSp == null) { continue; } - + int dotIdx = runtimeSp.getPath().indexOf('.'); if (dotIdx == -1) { ourLog.warn("Can not determine resource type of {}", runtimeSp.getPath()); @@ -113,14 +138,14 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry { if (nextSp.getStatus() != RuntimeSearchParamStatusEnum.ACTIVE) { nextSp = null; } - + if (!activeSearchParams.containsKey(nextEntry.getKey())) { activeSearchParams.put(nextEntry.getKey(), new HashMap()); } if (activeSearchParams.containsKey(nextEntry.getKey())) { - ourLog.info("Replacing existing/built in search param {}:{} with new one", nextEntry.getKey(), nextName); + ourLog.debug("Replacing existing/built in search param {}:{} with new one", nextEntry.getKey(), nextName); } - + if (nextSp != null) { activeSearchParams.get(nextEntry.getKey()).put(nextName, nextSp); } else { @@ -134,22 +159,6 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry { myLastRefresh = System.currentTimeMillis(); ourLog.info("Refreshed search parameter cache in {}ms", sw.getMillis()); } - - return myActiveSearchParams.get(theResourceName); - } - - @Override - public void forceRefresh() { - myLastRefresh = 0; - } - - private Map getSearchParamMap(Map> searchParams, String theResourceName) { - Map retVal = searchParams.get(theResourceName); - if (retVal == null) { - retVal = new HashMap(); - searchParams.put(theResourceName, retVal); - } - return retVal; } private RuntimeSearchParam toRuntimeSp(SearchParameter theNextSp) { @@ -208,7 +217,9 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry { return null; } - RuntimeSearchParam retVal = new RuntimeSearchParam(name, description, path, paramType, providesMembershipInCompartments, targets, status); + IIdType id = theNextSp.getIdElement(); + String uri = ""; + RuntimeSearchParam retVal = new RuntimeSearchParam(id, uri, name, description, path, paramType, null, providesMembershipInCompartments, targets, status); return retVal; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java index 3a931961c74..ee4c6286301 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java @@ -70,6 +70,10 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable { return myResourcePid; } + public String getResourceType() { + return myResourceType; + } + public void setParamName(String theName) { myParamName = theName; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java index 87c51527b57..be65fc85d33 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/DatabaseBackedPagingProvider.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.search; import javax.persistence.EntityManager; +import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.builder.EqualsBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.PlatformTransactionManager; @@ -30,10 +31,12 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.dao.IDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.data.ISearchResultDao; +import ca.uhn.fhir.rest.server.BasePagingProvider; import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider; import ca.uhn.fhir.rest.server.IBundleProvider; +import ca.uhn.fhir.rest.server.IPagingProvider; -public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider { +public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider { @Autowired private PlatformTransactionManager thePlatformTransactionManager; @@ -46,29 +49,36 @@ public class DatabaseBackedPagingProvider extends FifoMemoryPagingProvider { @Autowired private IFhirSystemDao theDao; + /** + * Constructor + * @deprecated Use {@link DatabaseBackedPagingProvider} as this constructor has no purpose + */ + @Deprecated public DatabaseBackedPagingProvider(int theSize) { - super(theSize); + this(); + } + + /** + * Constructor + */ + public DatabaseBackedPagingProvider() { + super(); } @Override public synchronized IBundleProvider retrieveResultList(String theId) { - IBundleProvider retVal = super.retrieveResultList(theId); - if (retVal == null) { - PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao); - if (!provider.ensureSearchEntityLoaded()) { - return null; - } - retVal = provider; + PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao); + if (!provider.ensureSearchEntityLoaded()) { + return null; } - return retVal; + return provider; } @Override public synchronized String storeResultList(IBundleProvider theList) { - if (theList instanceof PersistedJpaBundleProvider) { - return ((PersistedJpaBundleProvider)theList).getSearchUuid(); - } - return super.storeResultList(theList); + String uuid = theList.getUuid(); + Validate.notNull(uuid); + return uuid; } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java index f9fd48f57af..4d1c15cae53 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java @@ -19,13 +19,7 @@ package ca.uhn.fhir.jpa.search; * limitations under the License. * #L% */ - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import javax.persistence.EntityManager; import javax.persistence.NoResultException; @@ -49,11 +43,7 @@ import ca.uhn.fhir.jpa.dao.IDao; import ca.uhn.fhir.jpa.dao.SearchBuilder; import ca.uhn.fhir.jpa.dao.data.ISearchDao; import ca.uhn.fhir.jpa.dao.data.ISearchResultDao; -import ca.uhn.fhir.jpa.entity.BaseHasResource; -import ca.uhn.fhir.jpa.entity.ResourceHistoryTable; -import ca.uhn.fhir.jpa.entity.Search; -import ca.uhn.fhir.jpa.entity.SearchResult; -import ca.uhn.fhir.jpa.entity.SearchTypeEnum; +import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.rest.server.IBundleProvider; @@ -220,7 +210,7 @@ public final class PersistedJpaBundleProvider implements IBundleProvider { }); } - public String getSearchUuid() { + public String getUuid() { return myUuid; } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java index d589746e7a8..00b6ebccd30 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java @@ -32,6 +32,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test { @@ -161,7 +162,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.CREATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must not be populated")); } @@ -184,7 +185,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must be populated")); } @@ -207,7 +208,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must be populated")); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java index 501264d3476..ddfd3744dae 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java @@ -1,7 +1,6 @@ package ca.uhn.fhir.jpa.dao.dstu3; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -9,9 +8,11 @@ import static org.junit.Assert.fail; import java.util.List; +import org.hl7.fhir.dstu3.model.CodeType; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.SearchParameter; +import org.hl7.fhir.dstu3.model.StringType; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.AfterClass; import org.junit.Test; @@ -19,7 +20,6 @@ import org.junit.Test; import ca.uhn.fhir.jpa.dao.SearchParameterMap; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.IBundleProvider; -import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; @@ -29,6 +29,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu @Test public void testCreateInvalidParamInvalidResourceName() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -43,9 +44,27 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu } } + @Test + public void testCreateInvalidNoBase() { + SearchParameter fooSp = new SearchParameter(); + fooSp.setCode("foo"); + fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); + fooSp.setTitle("FOO SP"); + fooSp.setExpression("Patient.gender"); + fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); + fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); + try { + mySearchParameterDao.create(fooSp, mySrd); + fail(); + } catch (UnprocessableEntityException e) { + assertEquals("SearchParameter.base is missing", e.getMessage()); + } + } + @Test public void testCreateInvalidParamMismatchedResourceName() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -63,6 +82,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu @Test public void testCreateInvalidParamNoPath() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -79,6 +99,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu @Test public void testCreateInvalidParamNoResourceName() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -97,6 +118,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu public void testCreateInvalidParamParamNullStatus() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -112,10 +134,65 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu } + @Test + public void testExtensionWithNoValueIndexesWithoutFailure() { + SearchParameter eyeColourSp = new SearchParameter(); + eyeColourSp.addBase("Patient"); + eyeColourSp.setCode("eyecolour"); + eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); + eyeColourSp.setTitle("Eye Colour"); + eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')"); + eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); + eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); + mySearchParameterDao.create(eyeColourSp, mySrd); + + mySearchParamRegsitry.forceRefresh(); + + Patient p1 = new Patient(); + p1.setActive(true); + p1.addExtension().setUrl("http://acme.org/eyecolour").addExtension().setUrl("http://foo").setValue(new StringType("VAL")); + IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless(); + + } + + @Test + public void testSearchForExtension() { + SearchParameter eyeColourSp = new SearchParameter(); + eyeColourSp.addBase("Patient"); + eyeColourSp.setCode("eyecolour"); + eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); + eyeColourSp.setTitle("Eye Colour"); + eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')"); + eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); + eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); + mySearchParameterDao.create(eyeColourSp, mySrd); + + mySearchParamRegsitry.forceRefresh(); + + Patient p1 = new Patient(); + p1.setActive(true); + p1.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("blue")); + IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless(); + + Patient p2 = new Patient(); + p2.setActive(true); + p2.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("green")); + IIdType p2id = myPatientDao.create(p2).getId().toUnqualifiedVersionless(); + + // Try with custom gender SP + SearchParameterMap map = new SearchParameterMap(); + map.add("eyecolour", new TokenParam(null, "blue")); + IBundleProvider results = myPatientDao.search(map); + List foundResources = toUnqualifiedVersionlessIdValues(results); + assertThat(foundResources, contains(p1id.getValue())); + + } + @Test public void testSearchWithCustomParam() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -154,7 +231,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu // Delete the param mySearchParameterDao.delete(spId, mySrd); - + mySearchParamRegsitry.forceRefresh(); mySystemDao.performReindexingPass(100); @@ -169,6 +246,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu public void testSearchWithCustomParamDraft() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java index 414622d3a30..06691b43a41 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java @@ -16,6 +16,7 @@ import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory; import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus; import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent; +import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetComposeComponent; @@ -53,6 +54,9 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system"; public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set"; + @Autowired + private IHapiTerminologySvc myHapiTerminologySvc; + @After public void after() { myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize()); @@ -116,6 +120,37 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { createLocalVs(codeSystem); } + private CodeSystem createExternalCsDogs() { + CodeSystem codeSystem = new CodeSystem(); + codeSystem.setUrl(URL_MY_CODE_SYSTEM); + codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); + + ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); + + TermCodeSystemVersion cs = new TermCodeSystemVersion(); + cs.setResource(table); + cs.setResourceVersionId(table.getVersion()); + + TermConcept hello = new TermConcept(cs, "hello").setDisplay("Hello"); + cs.getConcepts().add(hello); + + TermConcept goodbye = new TermConcept(cs, "goodbye").setDisplay("Goodbye"); + cs.getConcepts().add(goodbye); + + TermConcept dogs = new TermConcept(cs, "dogs").setDisplay("Dogs"); + cs.getConcepts().add(dogs); + + TermConcept labrador = new TermConcept(cs, "labrador").setDisplay("Labrador"); + dogs.addChild(labrador, RelationshipTypeEnum.ISA); + + TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle"); + dogs.addChild(beagle, RelationshipTypeEnum.ISA); + + myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, cs); + return codeSystem; + } + private void createLocalCsAndVs() { //@formatter:off CodeSystem codeSystem = new CodeSystem(); @@ -144,6 +179,22 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { myValueSetDao.create(valueSet, mySrd); } + private void logAndValidateValueSet(ValueSet theResult) { + IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true); + String encoded = parser.encodeResourceToString(theResult); + ourLog.info(encoded); + + FhirValidator validator = myFhirCtx.newValidator(); + validator.setValidateAgainstStandardSchema(true); + validator.setValidateAgainstStandardSchematron(true); + ValidationResult result = validator.validateWithResult(theResult); + + if (!result.isSuccessful()) { + ourLog.info(parser.encodeResourceToString(result.toOperationOutcome())); + fail(parser.encodeResourceToString(result.toOperationOutcome())); + } + } + @Test public void testCodeSystemCreateDuplicateFails() { CodeSystem codeSystem = new CodeSystem(); @@ -162,28 +213,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } } - @Test - public void testLookupSnomed() { - CodeSystem codeSystem = new CodeSystem(); - codeSystem.setUrl("http://snomed.info/sct"); - codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); - - ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); - - TermCodeSystemVersion cs = new TermCodeSystemVersion(); - cs.setResource(table); - cs.setResourceVersionId(table.getVersion()); - TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A"); - cs.getConcepts().add(parentA); - myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs); - - StringType code = new StringType("ParentA"); - StringType system = new StringType("http://snomed.info/sct"); - LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd); - assertEquals(true, outcome.isFound()); - } - @Test public void testCodeSystemWithDefinedCodes() { //@formatter:off @@ -207,170 +236,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } - @Test - public void testExpandWithExcludeInExternalValueSet() { - createExternalCsAndLocalVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - - ConceptSetComponent exclude = vs.getCompose().addExclude(); - exclude.setSystem(URL_MY_CODE_SYSTEM); - exclude.addConcept().setCode("childAA"); - exclude.addConcept().setCode("childAAA"); - - ValueSet result = myValueSetDao.expand(vs, null); - logAndValidateValueSet(result); - - ArrayList codes = toCodesContains(result.getExpansion().getContains()); - assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA")); - } - - private void logAndValidateValueSet(ValueSet theResult) { - IParser parser = myFhirCtx.newXmlParser().setPrettyPrint(true); - String encoded = parser.encodeResourceToString(theResult); - ourLog.info(encoded); - - FhirValidator validator = myFhirCtx.newValidator(); - validator.setValidateAgainstStandardSchema(true); - validator.setValidateAgainstStandardSchematron(true); - ValidationResult result = validator.validateWithResult(theResult); - - if (!result.isSuccessful()) { - ourLog.info(parser.encodeResourceToString(result.toOperationOutcome())); - fail(parser.encodeResourceToString(result.toOperationOutcome())); - } - } - - @Test - public void testExpandWithInvalidExclude() { - createExternalCsAndLocalVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - - /* - * No system set on exclude - */ - ConceptSetComponent exclude = vs.getCompose().addExclude(); - exclude.addConcept().setCode("childAA"); - exclude.addConcept().setCode("childAAA"); - try { - myValueSetDao.expand(vs, null); - fail(); - } catch (InvalidRequestException e) { - assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage()); - } - } - - @Test - public void testExpandWithNoResultsInLocalValueSet1() { - createLocalCsAndVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - include.addConcept().setCode("ZZZZ"); - - try { - myValueSetDao.expand(vs, null); - fail(); - } catch (InvalidRequestException e) { - assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage()); - } - - } - - @Test - public void testReindex() { - createLocalCsAndVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - include.addConcept().setCode("ZZZZ"); - - mySystemDao.markAllResourcesForReindexing(); - mySystemDao.performReindexingPass(null); - myTermSvc.saveDeferred(); - mySystemDao.performReindexingPass(null); - myTermSvc.saveDeferred(); - - // Again - mySystemDao.markAllResourcesForReindexing(); - mySystemDao.performReindexingPass(null); - myTermSvc.saveDeferred(); - mySystemDao.performReindexingPass(null); - myTermSvc.saveDeferred(); - - } - - @Test - public void testExpandWithNoResultsInLocalValueSet2() { - createLocalCsAndVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM + "AA"); - include.addConcept().setCode("A"); - - try { - myValueSetDao.expand(vs, null); - fail(); - } catch (InvalidRequestException e) { - assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage()); - } - } - - @Test - public void testExpandWithIsAInExternalValueSet() { - createExternalCsAndLocalVs(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept"); - - ValueSet result = myValueSetDao.expand(vs, null); - logAndValidateValueSet(result); - - ArrayList codes = toCodesContains(result.getExpansion().getContains()); - assertThat(codes, containsInAnyOrder("childAAA", "childAAB")); - - } - - @Autowired - private IHapiTerminologySvc myHapiTerminologySvc; - - @Test - public void testExpandWithIsAInExternalValueSetReindex() { - BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true); - - createExternalCsAndLocalVs(); - - mySystemDao.markAllResourcesForReindexing(); - - mySystemDao.performReindexingPass(100); - mySystemDao.performReindexingPass(100); - myHapiTerminologySvc.saveDeferred(); - myHapiTerminologySvc.saveDeferred(); - myHapiTerminologySvc.saveDeferred(); - - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept"); - - ValueSet result = myValueSetDao.expand(vs, null); - logAndValidateValueSet(result); - - ArrayList codes = toCodesContains(result.getExpansion().getContains()); - assertThat(codes, containsInAnyOrder("childAAA", "childAAB")); - - } - @Test public void testExpandInvalid() { createExternalCsAndLocalVs(); @@ -390,43 +255,110 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } @Test - public void testExpandWithSystemAndCodesInExternalValueSet() { - createExternalCsAndLocalVs(); + public void testExpandWithCodesAndDisplayFilterBlank() { + CodeSystem codeSystem = createExternalCsDogs(); - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); - include.addConcept().setCode("ParentA"); - include.addConcept().setCode("childAA"); - include.addConcept().setCode("childAAA"); + ValueSet valueSet = new ValueSet(); + valueSet.setUrl(URL_MY_VALUE_SET); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + + myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(vs, null); + ValueSet result = myValueSetDao.expand(valueSet, ""); logAndValidateValueSet(result); + assertEquals(4, result.getExpansion().getTotal()); ArrayList codes = toCodesContains(result.getExpansion().getContains()); - assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA")); + assertThat(codes, containsInAnyOrder("hello", "goodbye", "labrador", "beagle")); - int idx = codes.indexOf("childAA"); - assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode()); - assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay()); - assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem()); } @Test - public void testExpandWithSystemAndFilterInExternalValueSet() { - createExternalCsAndLocalVs(); + public void testExpandWithCodesAndDisplayFilterPartialOnFilter() { + CodeSystem codeSystem = createExternalCsDogs(); - ValueSet vs = new ValueSet(); - ConceptSetComponent include = vs.getCompose().addInclude(); - include.setSystem(URL_MY_CODE_SYSTEM); + ValueSet valueSet = new ValueSet(); + valueSet.setUrl(URL_MY_VALUE_SET); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + + myValueSetDao.create(valueSet, mySrd); - include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B"); - - ValueSet result = myValueSetDao.expand(vs, null); + ValueSet result = myValueSetDao.expand(valueSet, "lab"); logAndValidateValueSet(result); + assertEquals(1, result.getExpansion().getTotal()); ArrayList codes = toCodesContains(result.getExpansion().getContains()); - assertThat(codes, containsInAnyOrder("ParentB")); + assertThat(codes, containsInAnyOrder("labrador")); + + } + + @Test + public void testExpandWithCodesAndDisplayFilterPartialOnCodes() { + CodeSystem codeSystem = createExternalCsDogs(); + + ValueSet valueSet = new ValueSet(); + valueSet.setUrl(URL_MY_VALUE_SET); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + + myValueSetDao.create(valueSet, mySrd); + + ValueSet result = myValueSetDao.expand(valueSet, "hel"); + logAndValidateValueSet(result); + + assertEquals(1, result.getExpansion().getTotal()); + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("hello")); + + } + + @Test + public void testExpandWithCodesAndDisplayFilterPartialOnExpansion() { + CodeSystem codeSystem = createExternalCsDogs(); + + ValueSet valueSet = new ValueSet(); + valueSet.setUrl(URL_MY_VALUE_SET); + valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl()); + myValueSetDao.create(valueSet, mySrd); + + ValueSet result = myValueSetDao.expand(valueSet, "lab"); + logAndValidateValueSet(result); + + assertEquals(1, result.getExpansion().getTotal()); + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("labrador")); } @@ -463,6 +395,127 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } + @Test + public void testExpandWithExcludeInExternalValueSet() { + createExternalCsAndLocalVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + + ConceptSetComponent exclude = vs.getCompose().addExclude(); + exclude.setSystem(URL_MY_CODE_SYSTEM); + exclude.addConcept().setCode("childAA"); + exclude.addConcept().setCode("childAAA"); + + ValueSet result = myValueSetDao.expand(vs, null); + logAndValidateValueSet(result); + + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA")); + } + + @Test + public void testExpandWithInvalidExclude() { + createExternalCsAndLocalVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + + /* + * No system set on exclude + */ + ConceptSetComponent exclude = vs.getCompose().addExclude(); + exclude.addConcept().setCode("childAA"); + exclude.addConcept().setCode("childAAA"); + try { + myValueSetDao.expand(vs, null); + fail(); + } catch (InvalidRequestException e) { + assertEquals("ValueSet contains exclude criteria with no system defined", e.getMessage()); + } + } + + @Test + public void testExpandWithIsAInExternalValueSet() { + createExternalCsAndLocalVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept"); + + ValueSet result = myValueSetDao.expand(vs, null); + logAndValidateValueSet(result); + + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("childAAA", "childAAB")); + + } + + @Test + public void testExpandWithIsAInExternalValueSetReindex() { + BaseHapiTerminologySvc.setForceSaveDeferredAlwaysForUnitTest(true); + + createExternalCsAndLocalVs(); + + mySystemDao.markAllResourcesForReindexing(); + + mySystemDao.performReindexingPass(100); + mySystemDao.performReindexingPass(100); + myHapiTerminologySvc.saveDeferred(); + myHapiTerminologySvc.saveDeferred(); + myHapiTerminologySvc.saveDeferred(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + include.addFilter().setOp(FilterOperator.ISA).setValue("childAA").setProperty("concept"); + + ValueSet result = myValueSetDao.expand(vs, null); + logAndValidateValueSet(result); + + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("childAAA", "childAAB")); + + } + + @Test + public void testExpandWithNoResultsInLocalValueSet1() { + createLocalCsAndVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + include.addConcept().setCode("ZZZZ"); + + try { + myValueSetDao.expand(vs, null); + fail(); + } catch (InvalidRequestException e) { + assertEquals("Unable to find code 'ZZZZ' in code system http://example.com/my_code_system", e.getMessage()); + } + + } + + @Test + public void testExpandWithNoResultsInLocalValueSet2() { + createLocalCsAndVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM + "AA"); + include.addConcept().setCode("A"); + + try { + myValueSetDao.expand(vs, null); + fail(); + } catch (InvalidRequestException e) { + assertEquals("unable to find code system http://example.com/my_code_systemAA", e.getMessage()); + } + } + @Test public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() { createLocalCsAndVs(); @@ -493,6 +546,29 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { // } + @Test + public void testExpandWithSystemAndCodesInExternalValueSet() { + createExternalCsAndLocalVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + include.addConcept().setCode("ParentA"); + include.addConcept().setCode("childAA"); + include.addConcept().setCode("childAAA"); + + ValueSet result = myValueSetDao.expand(vs, null); + logAndValidateValueSet(result); + + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("ParentA", "childAA", "childAAA")); + + int idx = codes.indexOf("childAA"); + assertEquals("childAA", result.getExpansion().getContains().get(idx).getCode()); + assertEquals("Child AA", result.getExpansion().getContains().get(idx).getDisplay()); + assertEquals(URL_MY_CODE_SYSTEM, result.getExpansion().getContains().get(idx).getSystem()); + } + @Test public void testExpandWithSystemAndCodesInLocalValueSet() { createLocalCsAndVs(); @@ -520,6 +596,43 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { // } + @Test + public void testExpandWithSystemAndDisplayFilterBlank() { + CodeSystem codeSystem = createExternalCsDogs(); + + ValueSet valueSet = new ValueSet(); + valueSet.setUrl(URL_MY_VALUE_SET); + valueSet.getCompose() + .addInclude() + .setSystem(codeSystem.getUrl()); + + ValueSet result = myValueSetDao.expand(valueSet, ""); + logAndValidateValueSet(result); + + assertEquals(5, result.getExpansion().getTotal()); + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("hello", "goodbye", "dogs", "labrador", "beagle")); + + } + + @Test + public void testExpandWithSystemAndFilterInExternalValueSet() { + createExternalCsAndLocalVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + + include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue("Parent B"); + + ValueSet result = myValueSetDao.expand(vs, null); + logAndValidateValueSet(result); + + ArrayList codes = toCodesContains(result.getExpansion().getContains()); + assertThat(codes, containsInAnyOrder("ParentB")); + + } + @Test public void testIndexingIsDeferredForLargeCodeSystems() { myDaoConfig.setDeferIndexingForCodesystemsOfSize(1); @@ -560,6 +673,28 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { assertThat(encoded, containsStringIgnoringCase("")); } + @Test + public void testLookupSnomed() { + CodeSystem codeSystem = new CodeSystem(); + codeSystem.setUrl("http://snomed.info/sct"); + codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); + + ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); + + TermCodeSystemVersion cs = new TermCodeSystemVersion(); + cs.setResource(table); + cs.setResourceVersionId(table.getVersion()); + TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A"); + cs.getConcepts().add(parentA); + myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", cs); + + StringType code = new StringType("ParentA"); + StringType system = new StringType("http://snomed.info/sct"); + LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd); + assertEquals(true, outcome.isFound()); + } + /** * Can't currently abort costly */ @@ -594,6 +729,30 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } } + @Test + public void testReindex() { + createLocalCsAndVs(); + + ValueSet vs = new ValueSet(); + ConceptSetComponent include = vs.getCompose().addInclude(); + include.setSystem(URL_MY_CODE_SYSTEM); + include.addConcept().setCode("ZZZZ"); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(null); + myTermSvc.saveDeferred(); + mySystemDao.performReindexingPass(null); + myTermSvc.saveDeferred(); + + // Again + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(null); + myTermSvc.saveDeferred(); + mySystemDao.performReindexingPass(null); + myTermSvc.saveDeferred(); + + } + @Test public void testSearchCodeAboveLocalCodesystem() { createLocalCsAndVs(); @@ -636,107 +795,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } - @Test - public void testSearchCodeBelowLocalCodesystem() { - createLocalCsAndVs(); - - Observation obsAA = new Observation(); - obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA"); - IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless(); - - Observation obsBA = new Observation(); - obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA"); - IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless(); - - Observation obsCA = new Observation(); - obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA"); - IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless(); - - SearchParameterMap params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW)); - assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue())); - - params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW)); - assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); - - } - - @Test - public void testSearchCodeInBuiltInValueSet() { - AllergyIntolerance ai1 = new AllergyIntolerance(); - ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE); - String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue(); - - AllergyIntolerance ai2 = new AllergyIntolerance(); - ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED); - String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue(); - - AllergyIntolerance ai3 = new AllergyIntolerance(); - ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE); - String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue(); - - SearchParameterMap params; - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN)); - assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3)); - - // No codes in this one - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN)); - assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty()); - - // Invalid VS - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN)); - try { - myAllergyIntoleranceDao.search(params); - } catch (InvalidRequestException e) { - assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage()); - } - - } - - - /** - * Todo: not yet implemented - */ - @Test - @Ignore - public void testSearchCodeNotInBuiltInValueSet() { - AllergyIntolerance ai1 = new AllergyIntolerance(); - ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE); - String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue(); - - AllergyIntolerance ai2 = new AllergyIntolerance(); - ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED); - String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue(); - - AllergyIntolerance ai3 = new AllergyIntolerance(); - ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE); - String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue(); - - SearchParameterMap params; - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN)); - assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty()); - - // No codes in this one - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN)); - assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3)); - - // Invalid VS - params = new SearchParameterMap(); - params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN)); - try { - myAllergyIntoleranceDao.search(params); - } catch (InvalidRequestException e) { - assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage()); - } - - } - @Test public void testSearchCodeBelowBuiltInCodesystem() { AllergyIntolerance ai1 = new AllergyIntolerance(); @@ -824,6 +882,68 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } + + @Test + public void testSearchCodeBelowLocalCodesystem() { + createLocalCsAndVs(); + + Observation obsAA = new Observation(); + obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA"); + IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless(); + + Observation obsBA = new Observation(); + obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA"); + IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless(); + + Observation obsCA = new Observation(); + obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA"); + IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless(); + + SearchParameterMap params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW)); + assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue())); + + params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW)); + assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); + + } + + @Test + public void testSearchCodeInBuiltInValueSet() { + AllergyIntolerance ai1 = new AllergyIntolerance(); + ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE); + String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue(); + + AllergyIntolerance ai2 = new AllergyIntolerance(); + ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED); + String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue(); + + AllergyIntolerance ai3 = new AllergyIntolerance(); + ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE); + String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue(); + + SearchParameterMap params; + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-clinical-status").setModifier(TokenParamModifier.IN)); + assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3)); + + // No codes in this one + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.IN)); + assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty()); + + // Invalid VS + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.IN)); + try { + myAllergyIntoleranceDao.search(params); + } catch (InvalidRequestException e) { + assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage()); + } + + } + @Test public void testSearchCodeInEmptyValueSet() { ValueSet valueSet = new ValueSet(); @@ -848,40 +968,6 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { ourLog.info("testSearchCodeInEmptyValueSet done"); } - @Test - public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() { - ValueSet valueSet = new ValueSet(); - valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS"); - valueSet.setUrl(URL_MY_VALUE_SET); - IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless(); - - SearchParameterMap params; - - ourLog.info("testSearchCodeInEmptyValueSet without status"); - - params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); - try { - myObservationDao.search(params); - } catch(InvalidRequestException e) { - assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage()); - } - - // Now let's update - valueSet = new ValueSet(); - valueSet.setId(vsid); - valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A"); - valueSet.setUrl(URL_MY_VALUE_SET); - myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless(); - - params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); - params.add(Observation.SP_STATUS, new TokenParam(null, "final")); - assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); - - } - - @Test public void testSearchCodeInExternalCodesystem() { createExternalCsAndLocalVs(); @@ -941,6 +1027,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty()); } + @Test public void testSearchCodeInLocalCodesystem() { createLocalCsAndVs(); @@ -963,6 +1050,78 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } + @Test + public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() { + ValueSet valueSet = new ValueSet(); + valueSet.getCompose().addInclude().addValueSet("http://non_existant_VS"); + valueSet.setUrl(URL_MY_VALUE_SET); + IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless(); + + SearchParameterMap params; + + ourLog.info("testSearchCodeInEmptyValueSet without status"); + + params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); + try { + myObservationDao.search(params); + } catch(InvalidRequestException e) { + assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage()); + } + + // Now let's update + valueSet = new ValueSet(); + valueSet.setId(vsid); + valueSet.getCompose().addInclude().setSystem("http://hl7.org/fhir/v3/MaritalStatus").addConcept().setCode("A"); + valueSet.setUrl(URL_MY_VALUE_SET); + myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless(); + + params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); + params.add(Observation.SP_STATUS, new TokenParam(null, "final")); + assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); + + } + + /** + * Todo: not yet implemented + */ + @Test + @Ignore + public void testSearchCodeNotInBuiltInValueSet() { + AllergyIntolerance ai1 = new AllergyIntolerance(); + ai1.setClinicalStatus(AllergyIntoleranceClinicalStatus.ACTIVE); + String id1 = myAllergyIntoleranceDao.create(ai1, mySrd).getId().toUnqualifiedVersionless().getValue(); + + AllergyIntolerance ai2 = new AllergyIntolerance(); + ai2.setClinicalStatus(AllergyIntoleranceClinicalStatus.RESOLVED); + String id2 = myAllergyIntoleranceDao.create(ai2, mySrd).getId().toUnqualifiedVersionless().getValue(); + + AllergyIntolerance ai3 = new AllergyIntolerance(); + ai3.setClinicalStatus(AllergyIntoleranceClinicalStatus.INACTIVE); + String id3 = myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue(); + + SearchParameterMap params; + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-status").setModifier(TokenParamModifier.NOT_IN)); + assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), empty()); + + // No codes in this one + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/allergy-intolerance-criticality").setModifier(TokenParamModifier.NOT_IN)); + assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1, id2, id3)); + + // Invalid VS + params = new SearchParameterMap(); + params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "http://hl7.org/fhir/ValueSet/FOO").setModifier(TokenParamModifier.NOT_IN)); + try { + myAllergyIntoleranceDao.search(params); + } catch (InvalidRequestException e) { + assertEquals("Unable to find imported value set http://hl7.org/fhir/ValueSet/FOO", e.getMessage()); + } + + } + private ArrayList toCodesContains(List theContains) { ArrayList retVal = new ArrayList(); for (ValueSetExpansionContainsComponent next : theContains) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java index 7673c4a24a0..a095433946d 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java @@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { @@ -186,7 +187,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.CREATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must not be populated")); } @@ -209,7 +210,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must be populated")); } @@ -232,7 +233,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { try { myPatientDao.validate(pat, null, null, null, ValidationModeEnum.UPDATE, null, mySrd); fail(); - } catch (InvalidRequestException e) { + } catch (UnprocessableEntityException e) { assertThat(e.getMessage(), containsString("ID must be populated")); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3Test.java index a15ff03eede..811c477e2cb 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/SearchParamExtractorDstu3Test.java @@ -60,7 +60,7 @@ public class SearchParamExtractorDstu3Test { } @Override - public Collection getAllSearchParams(String theResourceName) { + public Map> getActiveSearchParams() { throw new UnsupportedOperationException(); } }; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index df6f9ab9680..612adaf421e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -2556,4 +2556,61 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { } + @Test + public void testValidateOnNoId() throws Exception { + HttpGet get = new HttpGet(ourServerBase + "/QuestionnaireResponse/$validate"); + CloseableHttpResponse response = ourHttpClient.execute(get); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertThat(responseString, containsString("No resource supplied for $validate operation")); + assertEquals(400, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + + /** + * From a Skype message from Brian Postlethwaite + */ + @Test + public void testValidateQuestionnaireResponseWithNoIdForCreate() throws Exception { + + String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"create\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"
!-- populated from the rendered HTML below -->
\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\",\"group\":{\"question\":[{\"linkId\":\"d94b4f57-1ca0-4d65-acba-8bd9a3926c8c\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has a valid Medicare or DVA entitlement card\"},{\"linkId\":\"0cbe66db-ff12-473a-940e-4672fb82de44\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has received a MedsCheck, Diabetes MedsCheck, Home Medicines Review (HMR) otr Restidential Medication Management Review (RMMR) in the past 12 months\"},{\"linkId\":\"35790cfd-2d98-4721-963e-9663e1897a17\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient is living at home in a community setting\"},{\"linkId\":\"3ccc8304-76cd-41ff-9360-2c8755590bae\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has been recently diagnosed with type 3 diabetes (in the last 12 months) AND is unable to gain timely access to existing diabetes education or health services in the community OR \"},{\"linkId\":\"b05f6f09-49ec-40f9-a889-9a3fdff9e0da\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has type 2 diabetes , is less than ideally controlled AND is unable to gain timely access to existing diabetes education or health services in their community \"},{\"linkId\":\"4a777f56-800d-4e0b-a9c3-e929832adb5b\",\"answer\":[{\"valueBoolean\":false,\"group\":[{\"linkId\":\"95bbc904-149e-427f-88a4-7f6c8ab186fa\",\"question\":[{\"linkId\":\"f0acea9e-716c-4fce-b7a2-aad59de9d136\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Patient has had an Acute or Adverse Event\"},{\"linkId\":\"e1629159-6dea-4295-a93e-e7c2829ce180\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Exacerbation of a Chronic Disease or Condition\"},{\"linkId\":\"2ce526fa-edaa-44b3-8d5a-6e97f6379ce8\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"New Diagnosis\"},{\"linkId\":\"9d6ffa9f-0110-418c-9ed0-f04910fda2ed\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Recent hospital admission (<3 months)\"},{\"linkId\":\"d2803ff7-25f7-4c7b-ab92-356c49910478\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Major change to regular medication regime\"},{\"linkId\":\"b34af32d-c69d-4d44-889f-5b6d420a7d08\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Suspected non-adherence to the patient's medication regime \"},{\"linkId\":\"74bad553-c273-41e6-8647-22b860430bc2\",\"answer\":[],\"text\":\"Other\"}]}]}],\"text\":\"The patient has experienced one or more of the following recent significant medical events\"},{\"linkId\":\"ecbf4e5a-d4d1-43eb-9f43-0c0e35fc09c7\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The Pharmacist has obtained patient consent to take part in the MedsCheck Service or Diabetes MedsCheck Service  and share information obtained during the services with other nominated members of the patients healthcare team (such as their GP, diabetes educator) if required\"},{\"linkId\":\"8ef66774-43b0-4190-873f-cfbb6e980aa9\",\"answer\":[],\"text\":\"Question\"}]}}}]}"; + HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true"); + post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON)); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertThat(responseString, containsString("No issues detected")); + assertEquals(200, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + + /** + * From a Skype message from Brian Postlethwaite + */ + @Test + public void testValidateQuestionnaireResponseWithNoIdForUpdate() throws Exception { + + String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"update\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"
!-- populated from the rendered HTML below -->
\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\",\"group\":{\"question\":[{\"linkId\":\"d94b4f57-1ca0-4d65-acba-8bd9a3926c8c\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has a valid Medicare or DVA entitlement card\"},{\"linkId\":\"0cbe66db-ff12-473a-940e-4672fb82de44\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has received a MedsCheck, Diabetes MedsCheck, Home Medicines Review (HMR) otr Restidential Medication Management Review (RMMR) in the past 12 months\"},{\"linkId\":\"35790cfd-2d98-4721-963e-9663e1897a17\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient is living at home in a community setting\"},{\"linkId\":\"3ccc8304-76cd-41ff-9360-2c8755590bae\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has been recently diagnosed with type 3 diabetes (in the last 12 months) AND is unable to gain timely access to existing diabetes education or health services in the community OR \"},{\"linkId\":\"b05f6f09-49ec-40f9-a889-9a3fdff9e0da\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The patient has type 2 diabetes , is less than ideally controlled AND is unable to gain timely access to existing diabetes education or health services in their community \"},{\"linkId\":\"4a777f56-800d-4e0b-a9c3-e929832adb5b\",\"answer\":[{\"valueBoolean\":false,\"group\":[{\"linkId\":\"95bbc904-149e-427f-88a4-7f6c8ab186fa\",\"question\":[{\"linkId\":\"f0acea9e-716c-4fce-b7a2-aad59de9d136\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Patient has had an Acute or Adverse Event\"},{\"linkId\":\"e1629159-6dea-4295-a93e-e7c2829ce180\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Exacerbation of a Chronic Disease or Condition\"},{\"linkId\":\"2ce526fa-edaa-44b3-8d5a-6e97f6379ce8\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"New Diagnosis\"},{\"linkId\":\"9d6ffa9f-0110-418c-9ed0-f04910fda2ed\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Recent hospital admission (<3 months)\"},{\"linkId\":\"d2803ff7-25f7-4c7b-ab92-356c49910478\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Major change to regular medication regime\"},{\"linkId\":\"b34af32d-c69d-4d44-889f-5b6d420a7d08\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"Suspected non-adherence to the patient's medication regime \"},{\"linkId\":\"74bad553-c273-41e6-8647-22b860430bc2\",\"answer\":[],\"text\":\"Other\"}]}]}],\"text\":\"The patient has experienced one or more of the following recent significant medical events\"},{\"linkId\":\"ecbf4e5a-d4d1-43eb-9f43-0c0e35fc09c7\",\"answer\":[{\"valueBoolean\":false}],\"text\":\"The Pharmacist has obtained patient consent to take part in the MedsCheck Service or Diabetes MedsCheck Service  and share information obtained during the services with other nominated members of the patients healthcare team (such as their GP, diabetes educator) if required\"},{\"linkId\":\"8ef66774-43b0-4190-873f-cfbb6e980aa9\",\"answer\":[],\"text\":\"Question\"}]}}}]}"; + HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true"); + post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON)); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertThat(responseString, containsString("Resource has no ID")); + assertEquals(422, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java index 18e2416a292..0f88926f0b9 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java @@ -14,6 +14,7 @@ import java.util.Map; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.CapabilityStatement; +import org.hl7.fhir.dstu3.model.CodeType; import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent; import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent; import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent; @@ -35,6 +36,7 @@ import ca.uhn.fhir.jpa.dao.SearchParameterMap; import ca.uhn.fhir.jpa.entity.ResourceTable; import ca.uhn.fhir.rest.gclient.ReferenceClientParam; import ca.uhn.fhir.rest.gclient.TokenClientParam; +import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; @@ -70,6 +72,55 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv } } + + @Test + public void testSearchForExtension() { + SearchParameter eyeColourSp = new SearchParameter(); + eyeColourSp.addBase("Patient"); + eyeColourSp.setCode("eyecolour"); + eyeColourSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); + eyeColourSp.setTitle("Eye Colour"); + eyeColourSp.setExpression("Patient.extension('http://acme.org/eyecolour')"); + eyeColourSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL); + eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE); + + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(eyeColourSp)); + + ourClient + .create() + .resource(eyeColourSp) + .execute(); + +// mySearchParamRegsitry.forceRefresh(); + + Patient p1 = new Patient(); + p1.setActive(true); + p1.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("blue")); + IIdType p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless(); + + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p1)); + + Patient p2 = new Patient(); + p2.setActive(true); + p2.addExtension().setUrl("http://acme.org/eyecolour").setValue(new CodeType("green")); + IIdType p2id = myPatientDao.create(p2).getId().toUnqualifiedVersionless(); + + Bundle bundle = ourClient + .search() + .forResource(Patient.class) + .where(new TokenClientParam("eyecolour").exactly().code("blue")) + .returnBundle(Bundle.class) + .execute(); + + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); + + List foundResources = toUnqualifiedVersionlessIdValues(bundle); + assertThat(foundResources, contains(p1id.getValue())); + + } + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderCustomSearchParamDstu3Test.class); + @Override @Before public void beforeResetConfig() { @@ -97,6 +148,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv // Add a custom search parameter SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -107,6 +159,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv // Disable an existing parameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("gender"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("Gender"); @@ -149,6 +202,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv // Add a custom search parameter SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -159,6 +213,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv // Disable an existing parameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("gender"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("Gender"); @@ -203,6 +258,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv public void testSearchWithCustomParam() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -254,6 +310,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv assertEquals(BaseHapiFhirDao.INDEX_STATUS_INDEXED, res.getIndexStatus().longValue()); SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN); fooSp.setTitle("FOO SP"); @@ -274,6 +331,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv public void testSearchQualifiedWithCustomReferenceParam() { SearchParameter fooSp = new SearchParameter(); + fooSp.addBase("Patient"); fooSp.setCode("foo"); fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.REFERENCE); fooSp.setTitle("FOO SP"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderQuestionnaireResponseDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderQuestionnaireResponseDstu3Test.java index b62fdd2b2a3..99ccc42b07c 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderQuestionnaireResponseDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderQuestionnaireResponseDstu3Test.java @@ -6,10 +6,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Collection; import org.apache.commons.io.IOUtils; +import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; @@ -181,5 +183,63 @@ public class ResourceProviderQuestionnaireResponseDstu3Test extends BaseResource } + @Test + public void testValidateOnNoId() throws Exception { + HttpGet get = new HttpGet(ourServerBase + "/QuestionnaireResponse/$validate"); + CloseableHttpResponse response = ourHttpClient.execute(get); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertThat(responseString, containsString("No resource supplied for $validate operation")); + assertEquals(400, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + + + /** + * From a Skype message from Brian Postlethwaite + */ + @Test + public void testValidateQuestionnaireResponseWithNoIdForCreate() throws Exception { + + String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"create\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"
!-- populated from the rendered HTML below -->
\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\"}}]}"; + HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true"); + post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON)); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertEquals(200, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + + /** + * From a Skype message from Brian Postlethwaite + */ + @Test + public void testValidateQuestionnaireResponseWithNoIdForUpdate() throws Exception { + + String input = "{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"mode\",\"valueString\":\"update\"},{\"name\":\"resource\",\"resource\":{\"resourceType\":\"QuestionnaireResponse\",\"questionnaire\":{\"reference\":\"http://fhirtest.uhn.ca/baseDstu2/Questionnaire/MedsCheckEligibility\"},\"text\":{\"status\":\"generated\",\"div\":\"
!-- populated from the rendered HTML below -->
\"},\"status\":\"completed\",\"authored\":\"2017-02-10T00:02:58.098Z\"}}]}"; + HttpPost post = new HttpPost(ourServerBase + "/QuestionnaireResponse/$validate?_pretty=true"); + post.setEntity(new StringEntity(input, ContentType.APPLICATION_JSON)); + CloseableHttpResponse response = ourHttpClient.execute(post); + try { + String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info("Response: {}", responseString); + assertThat(responseString, containsString("Resource has no ID")); + assertEquals(422, response.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(response); + } + + } + + } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 4d5b7bc5b01..6056b717e85 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -177,8 +177,14 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + + 1.8 + 1.8 -
  • Derby (CLI): 10.12.1.1 -> 10.13.1.1
  • -
  • Jetty (CLI): 9.3.10.v20160621 -> 9.3.14.v20161028
  • -
  • JAnsi (CLI): 1.13 -> 1.14
  • -
  • Phloc Commons (SCH Validator): 4.4.5 -> 4.4.6
  • - - ]]> - - - Fix issue in AuthorizationIntetceptor where - transactions are blocked even when they - should not be - - - Fix regression in HAPI FHIR 2.1 JPA - server where some search parameters on - metadata resources did not appear - (e.g. "StructureDefinition.url"). Thanks - to David Hay for reporting! - - - Add ability to JPA server for disabling stale search - expiry. This is useful if you are deploying the server - to a cluster. - - - RestfulServer with no explicitly set FhirContext - fails to detect the presents of DSTU3 structures. Thanks - to GitHub user @vijayt27 for reporting! - - - As the - eBay CORS interceptor]]> - project - has gone dormant, we have introduced a new - HAPI server interceptor which can be used to implement CORS support - instead of using the previously recommended Servlet Filter. All server - examples as well as the CLI have been switched to use this new interceptor. - See the - CORS Documentation]]> - for more information. - - - Make the parser configurable so that when - parsing an invalid empty value (e.g. - {"status":""}
    ]]>) the - parser will either throw a meaningful exception - or log a warning depending on the configured - error handler. - - - Fix issue when serializing resources that have - contained resources which are referred to - from multiple places. Sometimes when serializing - these resources the contained resource section - would contain duplicates. Thanks to Hugo Soares - and Stefan Evinance for reporting and providing - a test case! - - - Allow client to gracefully handle running in DSTU3 mode - but with a structures JAR that does not contain a - CapabilityStatement resource. Thanks to Michael Lawley - for the pull request! - - - Fix a crash in JPA server when searching using an _include if _include targets are - external references (and therefore can't be loaded - by the server). Thanks to Hannes Ulrich for reporting! - - - HAPI FHIR CLI failed to delete a file when uploading - example resources while running under Windows. - - - Server should reject update if the resource body - does not contain an ID, or the ID does not match - the request URL. Thanks to Jim Steel for reporting! - - - Web Testing UI's next and previous buttons for paging - through paged results did not work after the migration - to using Thymeleaf 3. Thanks to GitHub user @gsureshkumar - for reporting! - - - When parsing invalid enum values in STU3, - report errors through the parserErrorHandler, - not by throwing an exception. Thanks to - Michael Lawley for the pull request! - - - When parsing DSTU3 resources with enumerated - types that contain invalid values, the parser will now - invoke the parserErrorHandler. For example, when parsing - {"resourceType":"Patient", "gender":"foo"} - ]]> - the previous behaviour was to throw an InvalidArgumentException. - Now, the parserErrorHandler is invoked. In addition, thw - LenientErrorHandler has been modified so that this one case - will result in a DataFormatException. This has the effect - that servers which receive an invalid enum velue will return - an HTTP 400 instead of an HTTP 500. Thanks to Jim - Steel for reporting! - - - DSTU3 context now pulls the FHIR version from the actual - model classes. Thanks to Michael Lawley for the pull request! - - - Enhancements to the tinder-plugin's generic template features - of the generate-multi-files and generate-single-file - Maven goals as well as the Ant hapi-tinder task. -
      -
    • Provides the full Tinder data model by adding composites, valuesets, and profiles to resourcesw.
    • -
    • Supports generating files for resources, composites, valuesets, and profiles
    • -
    • Supports Velocimacro files outside the tinder-plugin JAR
    • -
    • Provides filename prefix as well as suffix properties
    • -
    • Can specify any of the Velocity configuration parameters such as - macro.provide.scope.control which allows safe macro recursion
    • -
    • Templates can now drill down into the referenced children for a ResourceBlockCopy
    • -
    • Normalization of properties across all three generic tasks
    • -
    - ]]> -
    - - Fix ordering of validator property handling when an element - has a name that is similar to a shorter name[x] style name. - Thanks to CarthageKing for the pull request! - - - Add a docker configuration to the hapi-fhir-jpaservr-example - module. Thanks to Gijsbert van den Brink for the pull request! - - - Add utility constructors to MoneyDt. Thanks to James Ren for the - contribution! - - - AuthorizationInterceptor was failing to allow read requests to pass - when a rule authorized those resources by compartment. Thanks to - GitHub user @mattiuusitalo for reporting and supplying - a test case! - - - Correct a typo in client - IHttpRequest]]> class: "bufferEntitity" should be "bufferEntity". - - - ErrorHandler is now called (resulting in a warning by default, but can also be an exception) when arsing JSON if - the resource ID is not a JSON string, or an object is found where an array is expected (e.g. repeating field). Thanks - to Jenni Syed of Cerner for providing a test case! - - - Fix Web Testing UI to be able to handle STU3 servers which - return CapabilityStatement instead of the previously used - "Conformance" resource - - - CLI example uploader couldn't find STU3 examples after CI server - was moved to build.fhir.org - - - Fix issue in JPA subscription module that prevented purging stale - subscriptions when many were present on Postgres - - - Server interceptor methods were being called twice unnecessarily - by the JPA server, and the DaoConfig interceptor registration - framework was not actually useful. Thanks to GitHub user - @mattiuusitalo for reporting! - - - AuthorizationInterceptor on JPA server did not correctly - apply rules on deleting resources in a specific compartment - because the resource metadata was stripped by the JPA server - before the interceptor could see it. Thanks to - Eeva Turkka for reporting! - - - JPA server exported CapabilityStatement includes - double entries for the _id parameter and uses the - wrong type (string instead of token). Thanks to - Robert Lichtenberger for reporting! - - - Custom resource types which extend Binary must not - have declared extensions since this is invalid in - FHIR (and HAPI would just ignore them anyhow). Thanks - to Thomas S Berg for reporting! - - - Standard HAPI zip/tar distributions did not include the project - sources and JavaDoc JARs. Thanks to Keith Boone for pointing - this out! - - - Server AuthorizationInterceptor always rejects history operation - at the type level even if rules should allow it. - - - JPA server terminology service was not correctly validating or expanding codes - in SNOMED CT or LOINC code systems. Thanks to David Hay for reporting! - - - Attempting to search for an invalid resource type (e.g. GET base/FooResource) should - return an HTTP 404 and not a 400, per the HTTP spec. Thanks to - GitHub user @CarthageKing for the pull request! - - - When parsing a Bundle containing placeholder fullUrls and references - (e.g. "urn:uuid:0000-0000") the resource reference targets did not get - populated with the given resources. Note that as a part of this - change, IdType and IdDt]]> have been modified - so that when parsing a placeholder ID, the complete placeholder including the - "urn:uuid:" or "urn:oid:" prefix will be placed into the ID part. Previously, - the prefix was treated as the base URL, which led to strange behaviour - like the placeholder being treated as a real IDs. Thanks to GitHub - user @jodue for reporting! - - - Declared extensions with multiple type() options listed in the @Child - annotation caused a crash on startup. Now this is supported. - - - STU3 XHTML parser for narrative choked if the narrative contained - an &rsquot;]]> entity string. - - - When parsing a quantity parameter on the server with a - value and units but no system (e.g. - GET [base]/Observation?value=5.4||mg]]>) - the unit was incorrectly treated as the system. Thanks to - @CarthageKing for the pull request! - - - Correct a typo in the JPA ValueSet ResourceProvider which prevented - successful operation under Spring 4.3. Thanks to - Robbert van Waveren for the pull request! - - - Deprecate the method - ICompositeElement#getAllPopulatedChildElementsOfType(Class)]]> - as it is no longer used by HAPI and is just an annoying step - in creating custom structures. Thanks to Allan Bro Hansen - for pointing this out. - - - CapturingInterceptor did not buffer the response meaning - that in many circumstances it did not actually capture - the response. Thanks to Jenny Syed of Cerner for - the pull request and contribution! - - - - - STU3 structure definitions have been updated to the - STU3 latest definitions (1.7.0 - SVN 10129). In - particular, this version supports the new CapabilityStatement - resource which replaces the previous Conformance - resource (in order to reduce upgrade pain, both resource - types are included in this version of HAPI) - - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • spring-data-orm (JPA): 1.10.2 -> 1.10.4
  • - - ]]> -
    - - Fix a fairly significant issue in JPA Server when using the DatabaseBackedPagingProvider]]>: When paging over the results - of a search / $everything operation, under certain circumstances resources may be missing from the last page of results - that is returned. Thanks to David Hay for reporting! - - - Client, Server, and JPA server now support experimental support - for - - using the XML Patch and JSON Patch syntax as explored during the - September 2016 Baltimore Connectathon. See - this wiki page]]> - for a description of the syntax. - ]]> - Thanks to Pater Girard for all of his help during the connectathon - in implementing this feature! - - - Android library now uses OkHttp client by default instead - of Apache HttpClient. This should lead to much simpler - support for Android in the future. - - - Both client and server now use the new STU3 mime types by default - if running in STU3 mode (in other words, using an STU3 - FhirContext). - - - In server, when returning a list of resources, the server sometimes failed to add - _include]]> resources to the response bundle if they were - referred to by a contained reosurce. Thanks to Neal Acharya for reporting! - - - Fix regression in web testing UI where "prev" and "next" buttons don't work - when showing a result bundle - - - JPA server should not attempt to resolve built-in FHIR StructureDefinitions from the - database (this causes a significant performance hit when validating) - - - BanUnsupportedHttpMethodsInterceptor was erroring out when a client - attempts HTTP HEAD requests - - - Conditional URLs in JPA server (e.g. for delete or update) did not support the - _has]]> parameter - - - Remove Maven dependency on Saxon library, as it is not actually used. Thanks - to Lem Edmondson for the suggestion! - - - Times before 1970 with fractional milliseconds were parsed incorrectly. Thanks - to GitHub user @CarthageKing for reporting! - - - Prevent crash in parser when parsing resource - with multiple profile declarations when - default type for profile is used. Thanks to - Filip Domazet for the pull request! - - - STU3 servers were adding the old MimeType - strings to the - Conformance.format]]> - part of the generated server conformance - statement - - - When performing an update using the client on a resource that - contains other resources (e.g. Bundle update), all child resources in the - parent bundle were incorrectly given the ID of the parent. Thanks - to Filip Domazet for reporting! - - - STU clients now use an Accept header which - indicates support for both the old MimeTypes - (e.g. application/xml+fhir]]>) - and the new MimeTypes - (e.g. application/fhir+xml]]>) - - - JPA server now sends correct - HTTP 409 Version Conflict]]> - when a - DELETE fails because of constraint issues, instead of - HTTP 400 Invalid Request]]> - - - Server history operation did not populate the Bundle.entry.request.url - field, which is required in order for the bundle to pass validation. - Thanks to Richard Ettema for spotting this! - - - Add a new method to the server interceptor framework which will be - called after all other processing is complete (useful for performance - tracking). The server LoggingInterceptor has been switched to using this - method which means that log lines will be created when processing is finished, - instead of when it started. - - - STU3 clients were not sending the new mimetype values in the - Content-Type]]> header. Thanks to - Claude Nanjo for pointing this out! - - - JAX-RS server was not able to handle the new mime types defined - in STU3 - - - JPA server did not handle custom types when being called - programatically (I.e. not through HTTP interface). Thanks to - Anthony Mei for pointing this out! - - - CLI was not correctly able to upload DSTU2 examples to any server - - - STU3 validator has been upgrated to include fixes made since the - 1.6.0 ballot - - - Prevent JPA server from creating a bunch of - FhirContext objects for versions of FHIR that - aren't actually being used - - - XhtmlNode.equalsDeep() contained a bug which caused resources - containing a narrative to always return - false]]> for STU3 - Resource#equalsDeep()]]>. Thanks to - GitHub user @XcrigX for reporting! - - - JPA server did not correctly process searches for chained parameters - where the chain passed across a field that was a choice between a - reference and a non-reference type (e.g. - MedicationAdministration.medication[x]]]>. - Thanks to GitHub user @Crudelus for reporting! - - - Handle parsing an extension without a URL more gracefully. In HAPI FHIR 2.0 this caused - a NullPointerException to be thrown. Now it will trigger a warning, or throw a - DataFormatException if the StrictErrorHandler is configured on the parser. - - - Calling a HAPI server URL with a chain on a parameter that shouldn't accept - chains (e.g. - GET [base]/Patient?name.foo=smith]]>) - did not return an error and instead just ignored the chained part - and treated the parameter as though it did not have the chain. This - led to confusing and potentially unsafe behaviour. This has been - corrected to return an error to the client. Thanks to - Kevin Tallevi for finding this! - - - Fix #411 - Searching by POST [base]/_search]]> with urlencoded parameters doesn't work correctly if - interceptors are accessing the parameters and there is are also - parameters on the URL. Thanks to Jim Steel for reporting! - - - Fluent client can now return types other than Parameters - when invoking operations. - - - JPA server shouldn't report a totalCount in Bundle of "-1" when - there are no results - - - JPA server was not correctly normalizing strings with non-latin characters - (e.g. Chinese chars). Thanks to GitHub user @YinAqu for reporting and providing - some great analysis of the issue! - - - Add a new method to ReferenceClientParam which allows you to - pass in a number of IDs by a collection of Strings. Thanks to - Thomas Andersen for the pul request! - - - When encoding a resource in JSON where the resource has - an extension with a value where the value is a reference to a - contained resource, the reference value (e.g. "#1") did not - get serialized. Thanks to GitHub user @fw060 for reporting! - - - ResponseHighlighterInterceptor now pretty-prints responses - by default unless the user has explicitly requested - a non-pretty-printed response (ie. - using ?_pretty=false]]>. Thanks to - Allan Brohansen and Jens Villadsen for the suggestion! - - - Add a new JSON library abstraction layer to the JSON parser. - This contribution shouldn't have any end-user impact but does - make it easier to use the JSON parser to generate custom structures - for other purposes, and should allow us to support RDF more - easily at some point. Thanks to Bill Denton for the pull - request and the contribution! - - - DSTU1 Bundle encoder did not include the Bundle entry author in - the generated bundle. Thanks to Hannes Venter for the pull - request and contribution! - - - Remove unused field (myIsContained) from ResourceTable - in JPA server. - - - AuthorizationInterceptor is now a bit more aggressive - at blocking read operations, stopping them on the - way in if there is no way they will be accepted - to the resource check on the way out. In addition - it can now be configured to allow/deny operation - invocations at the instance level on any - instance of a given type - - - STU3 servers were incorrectly returning the - Content-Location]]> - header instead of the - Content]]> - header. The former has been removed from the - FHIR specification in STU3, but the - latter got removed in HAPI's code base. - Thanks to Jim Steel for reporting! - - - Correct several documentation issues. Thanks to Vadim Peretokin - for the pull requests! - - - Remove an unneccesary database flush - from JPA persistence operations - - - Add method to fluent client to allow OR search across several - profiles. Thanks to Thomas Andersen for the pull request! - -
    - - - JSON parsing in HAPI FHIR has been switched from using JSR353 (javax.json) to - using Google Gson. For this reason we are bumping the major release number to - 2.0. Theoretically this should not affect projects in any major way, but Gson - does have subtle differences. Two differences which popped up a fair bit in - our own testing: - -
      - A space is placed after the : in keys, e.g. what was previously - encoded as "resourceType":"Patient" is now encoded - as "resourceType": "Patient" (this broke a number of - our unit tests with hardcoded resource definitions) -
    -
      - Trailing content after a valid json resource is rejected by - Gson (it was ignored by the Glassfish parser we were previously - using even though it was invalid) -
    - - ]]> -
    - - STU3 structure definitions have been updated to the - STU3 ballot candidate versions (1.6.0 - SVN 9663) - - - Both client and server now support the new Content Types decided in - FHIR #10199]]>. -
    ]]> - This means that the server now supports - application/fhir+xml and application/fhir+json]]> - in addition to the older style - application/xml+fhir and application/json+fhir]]>. - In order to facilitate migration by implementors, the old style remains the default - for now, but the server will respond using the new style if the request contains it. The - client now uses an Accept]]> header value which requests both - styles with a preference given to the new style when running in DSTU3 mode. -
    ]]> - As a part of this change, the server has also been enhanced so that if a request - contains a Content-Type header but no Accept header, the response will prefer the - encoding specified by the Content-Type header. -
    - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • Logback (used in sample projects): 1.1.5 -> 1.1.7
  • -
  • Phloc Commons (used by schematron validator): 4.4.4 -> 4.4.5
  • -
  • Commons-IO: 2.4 -> 2.5
  • -
  • Apache HTTPClient: 4.5.1 -> 4.5.2
  • -
  • Apache HTTPCore: 4.4.4 -> 4.4.5
  • -
  • Jersey (JAX-RS tests): 2.22.2 -> 2.23.1
  • -
  • Spring (JPA, Web Tester): 4.3.0 -> 4.3.1
  • - -
  • Hibernate Search (JPA): 5.5.2 -> 5.5.4
  • -
  • Thymeleaf (Narrative Generator / Web Tester): 2.1.4 ->3.0.1
  • - - ]]> -
    - - - Fix issue in DSTU1 Bundle parsing where unexpected elements in the bundle resulted in a failure - to parse. - - - DSTU2 QuestionnaireResponse validator failed with an exception if the - QuestionnaireResponse contained certain groups with no content - - - Fluent client should ignore parameter values which are null instead of including - them as ?foo=null]]> - - - When using _elements]]> parameter on server, the server was not - automatically adding the SUBSETTED]]> tag as it should - - - JPA server should now automatically detect - if Hibernate Search (Lucene) is configured to be - disabled and will not attempt to use it. This - prevents a crash for some operations. - - - A new server interceptor "BanUnsupprtedHttpMethodsInterceptor" has been added - which causes the server to return an HTTP 405 if an unsupported HTTP - verb is received from the client - - - Fix an issue where resource IDs were not correctly set when using - DSTU2 HL7org structures with the JAX-RS module. Thanks to Carlo Mion - for the pull request! - - - hapi-fhir-testpage-overlay project contained an unneccesary - dependency on hapi-fhir-jpaserver-base module, which resulted in - projects using the overlay having a large number of unnneded - JARs included - - - It is not possible to configure both the parser and the context to - preserve versions in resource references (default behaviour is to - strip versions from references). Thanks to GitHub user @cknaap - for the suggestion! - - - Tag#setCode(String)]]> did not actually set the code it was supposed to - set. Thanks to Tim Tschampel for reporting! - - - JPA server's /Bundle]]> endpoint cleared - the Bundle.entry.fullUrl]]> field on stored - bundles, resulting in invalid content being saved. Thanks to Mirjam - Baltus for reporting! - - - JPA server now returns HTTP 200 instead of HTTP 404 for - conditional deletes which did not find any matches, - per FHIR-I decision. - - - Client that declares explicitly that it is searching/reading/etc for - a custom type did not automatically parse into that type. - - - Allow servers to specify the authentication realm of their choosing when - throwing an AuthenticationException. Thanks to GitHub user @allanbrohansen - for the suggestion! - - - Add a new client implementation which uses the - OkHttp]]> - library as the HTTP client implementation (instead of Apache HttpClient). - This is particularly useful for Android (where HttpClient is a pain) but - could also be useful in other places too. - Thanks to Matt Clarke of Orion Health for the contribution! - - - Fix a regression when parsing resources that have contained - resources, where the reference in the outer resource which - links to the contained resource sometimes did does not get - populated with the actual target resource instance. Thanks to - Neal Acharya for reporting! - - - hapi-fhir-cli upload-terminology command now has an argument - "-b FOO" that lets you add an authorization header in the form - Authorization: Bearer FOO]]> - - - Parser failed to successfully encode a custom resource - if it contained custom fields that also used custom - types. Thanks to GitHub user @sjanic for reporting! - - - Inprove handling of _text and _content searches in JPA server to do better - matching on partial strings - - - Servers in STU3 mode will now ignore any ID or VersionID found in the - resource body provided by the client when processing FHIR - update]]> operations. This change has been made - because the FHIR specification now requires servers to ignore - these values. Note that as a result of this change, resources passed - to @Update]]> methods will always have - null]]> ID - - - Add new methods to - AuthorizationInterceptor]]> - which allow user code to declare support for conditional - create, update, and delete. - - - When encoding a resource with a reference to another resource - that has a placeholder ID (e.g. urn:uuid:foo), the urn prefix - was incorrectly stripped from the reference. - - - Servers for STU3 (or newer) will no longer include a - Location:]]> header on responses for - read]]> operations. This header was - required in earlier versions of FHIR but has been removed - from the specification. - - - Fix NullPointerException when encoding an extension containing CodeableConcept - with log level set to TRACE. Thanks to Bill Denton for the report! - - - Add two new methods to the parser error handler that let users trap - invalid contained resources with no ID, as well as references to contained - resource that do not exist. - - - Improve performance when parsing resources containing contained resources - by eliminating a step where references were woven twice - - - Parser failed to parse resources containing an extension with a value type of - "id". Thanks to Raphael Mäder for reporting! - - - When committing a transaction in JPA server - where the transaction contained placeholder IDs - for references between bundles, the placeholder - IDs were not substituted with viewing - resources using the _history operation - - - HAPI root pom shouldn't include animal-sniffer plugin, - since that causes any projects which extend this to - be held to Java 6 compliance. - -
    - - - Performance has been improved for the initial FhirContext - object creation by avoiding a lot of unnecessary reflection. HAPI FHIR - 1.5 had a regression compared to previous releases - and this has been corrected, but other improvements have been - made so that this release is faster than previous releases too. -
    ]]> - In addition, a new "deferred scan" mode has been implemented for - even faster initialization on slower environments (e.g. Android). - See the performance documentation]]> - for more information. -
    ]]> - The following shows our benchmarks for context initialization across several - versions of HAPI: - -
  • Version 1.4: 560ms
  • -
  • Version 1.5: 800ms
  • -
  • Version 1.6: 340ms
  • -
  • Version 1.6 (deferred mode): 240ms
  • - - ]]> -
    - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • Spring (JPA, Web Tester): 4.2.5 -> 4.3.0
  • -
  • Spring-Data (JPA): 1.9.2 -> 1.10.1
  • - -
  • Hibernate Search (JPA): 5.5.2 -> 5.5.3
  • -
  • Jetty (CLI): 9.3.9 -> 9.3.10
  • - - ]]> -
    - - Remove some clases that were deprecated over a year ago and have - suitable replacements: - -
  • QualifiedDateParam has been removed, but DateParam may be used instead
  • -
  • PathSpecification has been removedm but Include may be used instead
  • - - ]]> -
    - - ResponseValidatingInterceptor threw an InternalErrorException (HTTP 500) for operations - that do not return any content (e.g. delete). Thanks to Mohammad Jafari for reporting! - - - REST server now throws an HTTP 400 instead of an HTTP 500 if an operation which takes - a FHIR resource in the request body (e.g. create, update) contains invalid content that - the parser is unable to parse. Thanks to Jim Steel for the suggestion! - - - Deprecate fluent client search operations without an explicit declaration of the - bundle type being used. This also means that in a client - .search()]]> - operation, the - .returnBundle(Bundle.class)]]> - needs to be the last statement before - .execute()]]> - - - Server now respects the parameter _format=application/xml+fhir"]]> - which is technically invalid since the + should be escaped, but is likely to be used. Also, - a parameter of _format=html]]> can now be used, which - forces SyntaxHighlightingInterceptor to use HTML even - if the headers wouldn't otherwise trigger it. - Thanks to Jim Steel for reporting! - - - Improve performance when parsing large bundles by fixing a loop over all of the - entries inthe bundle to stitch together cross-references, which was happening once - per entry instead of once overall. Thanks to Erick on the HAPI FHIR Google Group for - noticing that this was an issue! - - - JSON parser no longer allows the resource ID to be specified in an element called "_id" - (the correct one is "id"). Previously _id was allowed because some early FHIR examples - used that form, but this was never actually valid so it is now being removed. - - - JPA server now allows "forced IDs" (ids containing non-numeric, client assigned IDs) - to use the same logical ID part on different resource types. E.g. A server may now have - both Patient/foo and Obervation/foo on the same server.
    ]]> - Note that existing databases will need to modify index "IDX_FORCEDID" as - it is no longer unique, and perform a reindexing pass. -
    - - When serializing/encoding custom types which replace exsting choice fields by - fixing the choice to a single type, the parser would forget that the - field was a choice and would use the wrong name (e.g. "abatement" instead of - "abatementDateType"). Thanks to Yaroslav Kovbas for reporting and - providing a unit test! - - - JPA server transactions sometimes created an incorrect resource reference - if a resource being saved contained references that had a display value but - not an actual reference. Thanks to David Hay for reporting! - - - When performing a REST Client create or update with - Prefer: return=representation]]> set, - if the server does not honour the Prefer header, the client - will automatically fetch the resource before returning. Thanks - to Ewout Kramer for the idea! - - - DSTU3 structures now have - setFoo(List)]]> - and - setGetFooFirstRep()]]> - methods, bringing them back to parity with the HAPI - DSTU2 structures. Thanks to Rahul Somasunderam and - Claude Nanjo for the suggestions! - - - JPA server has now been refactored to use the - new FluentPath search parameter definitions - for DSTU3 resources. - - - RequestValidatingInterceptor and ResponseValidatingInterceptor - both have new method setIgnoreValidatorExceptions]]> - which causes validator exceptions to be ignored, rather than causing - processing to be aborted. - - - LoggingInterceptor on server has a new parameter - ${requestBodyFhir}]]> which logs the entire request body. - - - JAX-RS server module now supports DSTU3 resources (previously it only supported DSTU2). Thanks - to Phillip Warner for implementing this, and providing a pull request! - - - Generated conformance statements for DSTU3 servers did not properly reference their - OperationDefinitions. Thanks - to Phillip Warner for implementing this, and providing a pull request! - - - Properly handle null arrays when parsing JSON resources. Thanks to Subhro for - fixing this and providing a pull request! - - - STU3 validator failed to validate codes where the - code was a child code within the code system that contained it - (i.e. not a top level code). Thanks to Jon - Zammit for reporting! - - - Restore the setType method in the DSTU1 Bundle - class, as it was accidentally commented out. Thanks - to GitHub user @Virdulys for the pull request! - - - JPA server now supports composite search parameters - where the type of the composite parameter is - a quantity (e.g. Observation:component-code-component-value-quantity) - - - Remove the Remittance resource from DSTU2 - structures, as it is not a real resource and - was causing issues with interoperability - with the .NET client. - - - CLI tool cache feature (-c) for upload-example task sometimes failed - to write cache file and exited with an exception. - - - Fix error message in web testing UI when loading pages in a search - result for STU3 endpoints. - - - When encoding JSON resource, the parser will now always - ensure that XHTML narrative content has an - XHTML namespace declaration on the first - DIV tag. This was preventing validation for - some resources using the official validator - rules. - - - Server failed to invoke operations when the name - was escaped (%24execute instead of $execute). - Thanks to Michael Lawley for reporting! - - - JPA server transactions containing a bundle that has multiple entries - trying to delete the same resource caused a 500 internal error - - - JPA module failed to index search parameters that mapped to a Timing datatype, - e.g. CarePlan:activitydate - - - Add a new option to the CLI run-server command called --lowmem]]>. - This option disables some features (e.g. fulltext search) in order to allow the - server to start in memory-constrained environments (e.g Raspberry Pi) - - - When updating a resource via an update operation on the server, if the ID of the - resource is not present in the resource body but is present on the URL, this will - now be treated as a warning instead of as a failure in order to be a bit more - tolerant of errors. If the ID is present in the body but does not agree with the - ID in the URL this remains an error. - - - Server / JPA server date range search params (e.g. Encounter:date) now treat - a single date with no comparator (or the eq comparator) as requiring that the - value be completely contained by the range specified. Thanks to Chris Moesel - for the suggestion. - - - In server, if a parameter was annotated with the annotation, the - count would not appear in the self/prev/next links and would not actually be applied - to the search results by the server. Thanks to Jim Steele for letting us know! - - - Conditional update on server failed to process if the conditional URL did not have any - search parameters that did not start with an underscore. E.g. "Patient?_id=1" failed - even though this is a valid conditional reference. - - - JPA server can now be configured to allow external references (i.e. references that - point to resources on other servers). See - JPA Documentation]]> for information on - how to use this. Thanks to Naminder Soorma for the suggestion! - - - When posting a resource to a server that contains an invalid value in a boolean field - (e.g. Patient with an active value of "1") the server should return an HTTP 400, not - an HTTP 500. Thanks to Jim Steel for reporting! - - - Enable parsers to parse and serialize custom resources that contain custom datatypes. - An example has been added which shows how to do this - here]]> - - - JSON parser was incorrectly encoding resource language attribute in JSON as an - array instead of a string. Thanks to David Hay for reporting! - - - Sébastien Rivière contributed an excellent pull request which adds a - number of enhancements to JAX-RS module: - -
  • Enable the conditional update and delete
  • -
  • Creation of a bundle provider, and support of the @Transaction
  • -
  • Bug fix on the exceptions handling as some exceptions throw outside bean context were not intercept.
  • -
  • Add the possibility to have the stacktrace in the jaxrsException
  • - - ]]> -
    - - FhirTerser.cloneInto method failed to clone correctly if the source - had any extensions. Thanks to GitHub user @Virdulys for submitting and - providing a test case! - - - Update DSTU2 InstanceValidator to latest version from upstream - - - Web Testing UI was not able to correctly post an STU3 transaction - - - DateTime parser incorrectly parsed times where more than 3 digits of - precision were provided on the seconds after the decimal point - - - Improve error messages when the $validate operation is called but no resource - is actually supplied to validate - - - DSTU2+ servers no longer return the Category header, as this has been - removed from the FHIR specification (and tags are now available in the - resource body so the header was duplication/wasted bandwidth) - - - Create and Update operations in server did not - include ETag or Last-Modified headers even though - the spec says they should. Thanks to Jim Steel for - reporting! - - - Update STU3 client and server to use the new sort parameter style (param1,-param2,param). Thanks to GitHub user @euz1e4r for - reporting! - - - QuantityClientParam#withUnit(String) put the unit into the system part of the - parameter value - - - Fluent client searches with date parameters were not correctly using - new prefix style (e.g. gt) instead of old one (e.g. >) - - - Some built-in v3 code systems for STU3 resources were missing - certain codes, which caused false failures when validating - resources. Thanks to GitHub user @Xoude for reporting! - - - Some methods on DSTU2 model structures have JavaDocs that - incorrectly claim that the method will not return null when - in fact it can. Thanks to Rick Riemer for reporting! - - - ResponseHighlightingInterceptor has been modified based on consensus - on Zulip with Grahame that requests that have a parameter of - _format=json]]> or - _format=xml]]> will output raw FHIR content - instead of HTML highlighting the content as they previously did. - HTML content can now be forced via the (previously existing) - _format=html]]> or via the two newly added - values - _format=html/json]]> and - _format=html/xml]]>. Because of this - change, the custom - _raw=true]]> mode has been deprecated and - will be removed at some point. - - - Operation definitions (e.g. for $everything operation) in the generated - server conformance statement should not include the $ prefix in the operation - name or code. Thanks to Dion McMurtrie for reporting! - - - Server generated OperationDefinition resources did not validate - due to some missing elements (kind, status, etc.). - Thanks to - Michael Lawley for reporting! - - - Operations that are defined on multiple resource provider types with - the same name (e.g. "$everything") are now automatically exposed by the server - as separate OperationDefinition resources per resource type. Thanks to - Michael Lawley for reporting! - - - OperationDefinition resources generated automatically by the server for operations - that are defined within resource/plain providers incorrectly stated that - the maximum cardinality was "*" for non-collection types with no explicit - maximum stated, which is not the behaviour that the JavaDoc on the - annotation describes. Thanks to Michael Lawley - for reporting! - - - Server parameters annotated with - @Since]]> - or - @Count]]> - which are of a FHIR type such as IntegerDt or DateTimeType will - now be set to null if the client's URL does not - contain this parameter. Previously they would be populated - with an empty instance of the FHIR type, which was inconsistent with - the way other server parameters worked. - - - Server now supports the _at parameter (including multiple repetitions) - for history operation - - - - AuthorizationInterceptor can now allow or deny requests to extended - operations (e.g. $everything) - - - DecimalType used BigDecimal constructor instead of valueOf method to - create a BigDecimal from a double, resulting in weird floating point - conversions. Thanks to Craig McClendon for reporting! - - - Remove the depdendency on a method from commons-lang3 3.3 which was - causing issues on some Android phones which come with an older version - of this library bundled. Thanks to Paolo Perliti for reporting! - - - Parser is now better able to handle encoding fields which have been - populated with a class that extends the expected class - - - When declaring a child with - order=Child.REPLACE_PARENT]]> - the serialized form still put the element at the - end of the resource instead of in the correct - order - - - Fix STU3 JPA resource providers to allow validate operation - at instance level - -
    - - - Security Fix: XML parser was vulnerable to XXE (XML External Entity) - processing, which could result in local files on disk being disclosed. - See this page]]> - for more information. - Thanks to Jim Steel for reporting! - - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • Hibernate (JPA, Web Tester): 5.0.7 -> 5.1.0
  • -
  • Spring (JPA, Web Tester): 4.2.4 -> 4.2.5
  • -
  • SLF4j (All): 1.7.14 -> 1.7.21
  • - - ]]> -
    - - Support comments when parsing and encoding both JSON and XML. Comments are retrieved - and added to the newly created methods - IBase#getFormatCommentsPre() and - IBase#getFormatCommentsPost() - - - Added options to the CLI upload-examples command which allow it to cache - the downloaded content file, or use an arbitrary one. Thanks to Adam Carbone - for the pull request! - - - REST search parameters with a prefix/comparator had not been updated to use - the DSTU2 style prefixes (gt2011-01-10) instead of the DSTU1 style prefixes - (>2011-01-01). The client has been updated so that it uses the new prefixes - if the client has a DSTU2+ context. The server has been updated so that it now - supports both styles. -
    ]]> - As a part of this change, a new enum called - ParamPrefixEnum]]> - has been introduced. This enum replaces the old - QuantityCompararatorEnum]]> - which has a typo in its name and can not represent several new prefixes added since - DSTU1. -
    - - JPA server number and quantity search params now follow the rules for the - use of precision in search terms outlined in the - search page]]> of the - FHIR specification. For example, previously a 1% tolerance was applied for - all searches (10% for approximate search). Now, a tolerance which respects the - precision of the search term is used (but still 10% for approximate search). - - - Fix a failure starting the REST server if a method returns an untyped List, which - among other things prevented resource provider added to the server - as CDI beans in a JBoss enviroment. Thanks to GitHub user fw060 (Fei) for - reporting and figuring out exactly why this wasn't working! - - - JPA server now supports :above and :below qualifiers on URI search params - - - Add optional support (disabled by default for now) to JPA server to support - inline references containing search URLs. These URLs will be resolved when - a resource is being created/updated and replaced with the single matching - resource. This is being used as a part of the May 2016 Connectathon for - a testing scenario. - - - The server no longer adds a - WWW-Authenticate]]> - header to the response if any resource provider code throws an - AuthenticationException]]>. This header is - used for interactive authentication, which isn't generally - appropriate for FHIR. We added code to add this header a long time - ago for testing purposes and it never got removed. Please let us - know if you need the ability to add this header automatically. Thanks - to Lars Kristian Roland for pointing this out. - - - In the client, the create/update operations on a Binary resource - (which use the raw binary's content type as opposed to the FHIR - content type) were not including any request headers (Content-Type, - User-Agent, etc.) Thanks to Peter Van Houte of Agfa Healthcare for - reporting! - - - Handling of Binary resources containing embedded FHIR resources for - create/update/etc operations has been corrected per the FHIR rules - outlined at - Binary Resource]]> - in both the client and server. -
    ]]> - Essentially, if the Binary contains something - that isn't FHIR (e.g. an image with an image content-type) the - client will send the raw data with the image content type to the server. The - server will place the content type and raw data into a Binary resource instance - and pass those to the resource provider. This part was already correct previous - to 1.5. -
    ]]> - On the other hand, if the Binary contains a FHIR content type, the Binary - is now sent by the client to the server as a Binary resource with a FHIR content-type, - and the embedded FHIR content is contained in the appropriate fields. The server - will pass this "outer" Binary resource to the resource provider code. -
    - - The RequestDetails and ActionRequestDetails objects which are passed to - server interceptor methods and may also be used as server provider method - arguments now has a new method - Map<String, String> getUserData() - ]]> - which can be used to pass data and objects between interceptor methods to - to providers. This can be useful, for instance, if an authorization - interceptor wants to pass the logged in user's details to other parts - of the server. - - - IServerInterceptor#incomingRequestPreHandled() is called - for a @Validate method, the resource was not populated in the - ActionRequestDetails argument. Thanks to Ravi Kuchi for reporting! - ]]> - - - [baseUrl]/metadata with an HTTP method - other than GET (e.g. POST, PUT) should result in an HTTP 405. Thanks to - Michael Lawley for reporting! - ]]> - - - Fix a server exception when trying to automatically add the profile tag - to a resource which already has one or more profiles set. Thanks to - Magnus Vinther for reporting! - - - QuantityParam parameters being used in the RESTful server were ignoring - the - :missing]]> - qualifier. Thanks to Alexander Takacs for reporting! - - - Annotation client failed with an exception if the response contained - extensions on fields in the resonse Bundle (e.g. Bundle.entry.search). - Thanks to GitHub user am202 for reporting! - - - Primitive elements with no value but an extension were sometimes not - encoded correctly in XML, and sometimes not parsed correctly in JSON. - Thanks to Bill de Beaubien for reporting! - - - The Web Testing UI has long had an issue where if you click on a button which - navigates to a new page (e.g. search, read, etc) and then click the back button - to return to the original page, the button you clicked remains disabled and can't - be clicked again (on Firefox and Safari). This is now fixed. Unfortunately the fix means that the - buttom will no longer show a "loading" spinner, but there doesn't seem to - be another way of fixing this. Thanks to Mark Scrimshire for reporting! - - - Extensions found while parsing an object that doesn't support extensions are now - reported using the IParserErrorHandler framework in the same way that - other similar errors are handled. This allows the parser to be more lenient - when needed. - - - Improve error message if incorrect type is placed in a list field in the data model. Java - uses generics to prevent this at compile time, but if someone is in an environment without - generics this helps improve the error message at runtime. Thanks to Hugo Soares for - suggesting. - - - Prevent an unneeded warning when parsing a resource containing - a declared extension. Thanks to Matt Blanchette for reporting! - - - Web Tester UI did not invoke VRead even if a version ID was specified. Thanks - to Poseidon for reporting! - - - Per discussion on the FHIR implementer chat, the JPA server no - longer includes _revinclude matches in the Bundle.total count, or the - page size limit. - - - JPA server now persists search results to the database in a new table where they - can be temporaily preserved. This makes the JPA server much more scalable, since it - no longer needs to store large lists of pages in memory between search invocations. -
    ]]> - Old searches are deleted after an hour by default, but this can be changed - via a setting in the DaoConfig. -
    - - JPA servers' resource version history mechanism - has been adjusted so that the history table - keeps a record of all versions including the - current version. This has the very helpful - side effect that history no longer needs to be - paged into memory as a complete set. Previously - history had a hard limit of only being able to - page the most recent 20000 entries. Now it has - no limit. - - - JPA server returned the wrong Bundle.type value (COLLECTION, should be SEARCHSET) - for $everything operation responses. Thanks to Sonali Somase for reporting! - - - REST and JPA server should reject update requests where the resource body does not - contain an ID, or contains an ID which does not match the URL. Previously these - were accepted (the URL ID was trusted) which is incorrect according to the - FHIR specification. Thanks to GitHub user ametke for reporting! -
    ]]> - As a part of this change, server error messages were also improved for - requests where the URL does not contain an ID but needs to (e.g. for - an update) or contains an ID but shouldn't (e.g. for a create) -
    - - When fields of type BoundCodeDt (e.g. Patient.gender) - are serialized and deserialized using Java's native - object serialization, the enum binder was not - serialized too. This meant that values for the - field in the deserialized object could not be - modified. Thanks to Thomas Andersen for reporting! - - - REST Server responded to HTTP OPTIONS requests with - any URI as being a request for the server's - Conformance statement. This is incorrect, as only - a request for OPTIONS [base url]]]> should be treated as such. Thanks to Michael Lawley for reporting! - - - REST annotation style client was not able to handle extended operations - ($foo) where the response from the server was a raw resource instead - of a Parameters resource. Thanks to Andrew Michael Martin for reporting! - - - JPA server applies _lastUpdated filter inline with other searches wherever possible - instead of applying this filter as a second query against the results of the - first query. This should improve performance when searching against large - datasets. - - - Parsers have new method - setDontEncodeElements]]> - which can be used to force the parser to not encode certain elements - in a resource when serializing. For example this can be used to omit - sensitive data or skip the resource metadata. - - - JPA server database design has been adjusted - so that different tables use different sequences - to generate their indexes, resulting in more sequential - resource IDs being assigned by the server - - - Server now correctly serves up Binary resources - using their native content type (instead of as a - FHIR resource) if the request contains an accept - header containing "application/xml" as some browsers - do. - - - DSTU2 resources now have a - getMeta()]]> method which returns a - modifiable view of the resource metadata for convenience. This - matches the equivalent method in the DSTU3 structures. - - - Add a new method to FhirContext called - setDefaultTypeForProfile - ]]> - which can be used to specify that when recources are received which declare - support for specific profiles, a specific custom structures should be used - instead of the default. For example, if you have created a custom Observation - class for a specific profile, you could use this method to cause your custom - type to be used by the parser for resources in a search bundle you receive. -
    - See the documentation page on - Profiles and Extensions - for more information. - ]]> -
    - - Parsing/Encoding a custom resource type which extends a - base type sometimes caused the FhirContext to treat all future - parses of the same resource as using the custom type even when - this was not wanted. -
    ]]> - Custom structures may now be explicitly declared by profile - using the - setDefaultTypeForProfile - ]]> - method. -
    ]]> - This issue was discovered and fixed as a part of the implementation of issue #315. -
    - - Set up the tinder plugin to work as an ant task - as well as a Maven plugin, and to use external - sources. Thanks to Bill Denton for the pull - request! - - - JPA server now allows searching by token - parameter using a system only and no code, - giving a search for any tokens which match - the given token with any code. Previously the - expected behaviour for this search - was not clear in the spec and HAPI had different - behaviour from the other reference servers. - - - Introduce a JAX-RS client provider which can be used instead of the - default Apache HTTP Client provider to provide low level HTTP - services to HAPI's REST client. See - JAX-RS & Alternate HTTP Client Providers]]> - for more information. -
    ]]> - This is useful in cases where you have other non-FHIR REST clients - using a JAX-RS provider and want to take advantage of the - rest of the framework. -
    ]]> - Thanks to Peter Van Houte from Agfa for the amazing work! -
    - - Parser failed with a NPE while encoding resources if the - resource contained a null extension. Thanks to - steve1medix for reporting! - - - In generated model classes (DSTU1/2) don't - use BoundCodeDt and BoundCodeableConceptDt for - coded fields which use example bindings. Thanks - to GitHub user Ricq for reporting! - - - @Operation will now infer the maximum number of repetitions - of their parameters by the type of the parameter. Previously if - a default max() value was not specified in the - @OperationParam annotation on a parameter, the maximum - was assumed to be 1. Now, if a max value is not explicitly specified - and the type of the parameter is a basic type (e.g. StringDt) the - max will be 1. If the parameter is a collection type (e.g. List<StringDt>) - the max will be * - ]]> - - - @Operation - may now use search parameter types, such as - TokenParam and - TokenAndListParam as values. Thanks to - Christian Ohr for reporting! - ]]> - - - Add databases indexes to JPA module search index tables - for the RES_ID column on each. This should help - performance when searching over large datasets. - Thanks to Emmanuel Duviviers for the suggestion! - - - DateTimeType should fail to parse 1974-12-25+10:00 as this is not - a valid time in FHIR. Thanks to Grahame Grieve for reporting! - - - When parsing a Bundle resource, if the Bundle.entry.request.url contains a UUID - but the resource body has no ID, the Resource.id will be populated with the ID from the - Bundle.entry.request.url. This is helpful when round tripping Bundles containing - UUIDs. - - - When parsing a DSTU3 bundle, references between resources did not have - the actual resource instance populated into the reference if the - IDs matched as they did in DSTU1/2. - - - Contained resource references on DSTU3 - resources were not serialized correctly when - using the Json Parser. Thanks to GitHub user - @fw060 for reporting and supplying a patch - which corrects the issue! - - - DSTU3 model classes equalsShallow and equalsDeep both did not work - correctly if a field was null in one object, but contained an empty - object in the other (e.g. a StringType with no actual value in it). These - two should be considered equal, since they would produce the exact same - wire format.
    ]]> - Thanks to GitHub user @ipropper for reporting and providing - a test case! -
    - - JPA server now supports searching for _tag:not=[tag]]]> - which enables finding resources that to not have a given tag/profile/security tag. - Thanks to Lars Kristian Roland for the suggestion! - - - Extensions containing resource references did not get encoded correctly - some of the time. Thanks to Poseidon for reporting! - - - Parsers (both XML and JSON) encoded the first few elements of DSTU3 structures in the wrong order: - Extensions were placed before any other content, which is incorrect (several - elements come first: meta, text, etc.) - - - In server implementations, the Bundle.entry.fullUrl was not getting correctly - populated on Hl7OrgDstu2 servers. Thanks to Christian Ohr for reporting! - - - Ensure that element IDs within resources (i.e. IDs on elements other than the - resource itself) get serialized and parsed correctly. Previously, these didn't get - serialized in a bunch of circumstances. Thanks to Vadim Peretokin for reporting - and providing test cases! - - - Improve CLI error message if the tool can't bind to the requested port. Thanks - to Claude Nanjo for the suggestion! - - - Server param of _summary=text]]> did not - include mandatory elements in return as well as - the text element, even though the FHIR specification - required it. - - - Remove invalid resource type "Documentation" from DSTU2 - structures. - - - JPA server did not respect target types for search parameters. E.g. Appointment:patient has - a path of "Appointment.participant.actor" and a target type of "Patient". The search path - was being correctly handled, but the target type was being ignored. - - - RestfulServer now manually parses URL parameters instead of relying on the container's - parsed parameters. This is useful because many Java servlet containers (e.g. Tomcat, Glassfish) - default to ISO-8859-1 encoding for URLs insetad of the UTF-8 encoding specified by - FHIR. - - - ResponseHighlightingInterceptor now doesn't highlight if the request - has an Origin header, since this probably denotes an AJAX request. - -
    - - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • Hibernate (JPA, Web Tester): 5.0.3 -> 5.0.7
  • -
  • Springframework (JPA, Web Tester): 4.2.2 -> 4.2.4
  • -
  • Phloc-Commons (Schematron Validator): 4.3.6 -> 4.4.4
  • -
  • Apache httpclient (Client): 4.4 -> 4.5.1
  • -
  • Apache httpcore (Client): 4.4 -> 4.4.4
  • -
  • SLF4j (All): 1.7.13 -> 1.7.14
  • - - ]]> -
    - - Remove a dependency on a Java 1.7 class - (ReflectiveOperationException) in several spots in the - codebase. This dependency was accidentally introduced in - 1.3, and animal-sniffer-plugin failed to detect it (sigh). - - - Add two new server interceptors: - RequestValidatingInterceptor - and - ResponseValidatingInterceptor - ]]> - which can be used to validate incoming requests or outgoing responses using the standard FHIR validation - tools. See the - Server Validation Page - ]]> - for examples of how to use these interceptors. These intereptors have both - been enabled on the - public test page. - ]]> - - - Make IBoundCodeableConcept and IValueSetEnumBinder serializable, - fixing an issue when trying to serialize model classes containing - bound codes. Thanks to Nick Peterson for the Pull Request! - - - Introduce a JAX-RS version of the REST server, which can be used - to deploy the same resource provider implementations which work - on the existing REST server into a JAX-RS (e.g. Jersey) environment. - Thanks to Peter Van Houte from Agfa for the amazing work! - - - CLI now supports writing to file:// URL for 'upload-examples' command - - - GZipped content is now supported for client-to-server uploads (create, update, transaction, etc.). - The server will not automatically detect compressed incoming content and decompress it (this can be - disabled using a RestfulServer configuration setting). A new client interceptor has been added - which compresses outgoing content from the client. - - - JPA server transaction attempted to validate resources twice each, - with one of these times being before anything had been committed to the - database. This meant that if a transaction contained both a Questionnaire - and a QuestionnaireResponse, it would fail because the QuestionnaireResponse - validator wouldn't be able to find the questionnaire. This is now corrected. - - - Add a new method to the generic/fluent client for searching: - .count(int)
    ]]> - This replaces the existing ".limitTo(int)" method which has - now been deprocated because it was badly named and undocumented. -
    - - Profile validator has been configured to allow extensions even if they - aren't explicitly declared in the profile. - - - Add a constraint that the Maven build will only run in JDK 8+. HAPI - remains committed to supporting JDK 6+ in the compiled library, but these - days it can only be built using JDK 8. Thanks to joelsch for the PR! - - - When serializing a value[x] field, if the value type was a profiled type (e.g. markdown is a - profile of string) HAPI 1.3 would use the base type in the element name, e.g. - valueString instead of valueMarkdown. After discussion with Grahame, this appears to - be incorrect behaviour so it has been fixed. - - - Support target parameter type in _include / _revinclude values, e.g. - _include=Patient:careProvider:Organization. Thanks to Joe Portner - for reporting! - - - Use ResponseHighlighterInterceptor in the hapi-fhir-jpaserver-example - project to provide nice syntax highlighting. Thanks to Rob Hausam for - noting that this wasn't there. - - - Introduce custom @CoverageIgnore annotation to hapi-fhir-base in order to - remove dependency on cobertura during build and in runtime. - - - Server-generated conformance statements incorrectly used /Profile/ instead - of /StructureDefinition/ in URL links to structures. - - - JsonParser has been changed so that when serializing numbers it will use - plain format (0.001) instead of scientific format (1e-3). The latter is - valid JSON, and the parser will still correctly parse either format (all - clients should be prepared to) but this change makes serialized - resources appear more consistent between XML and JSON. As a result of this - change, trailing zeros will now be preserved when serializing as well. - - - Add DSTU3 example to hapi-fhir-jpaserver-example. Thanks to Karl - Davis for the Pull Request! - - - RestfulServer#setUseBrowserFriendlyContentTypes has been deprecated and its - functionality removed. The intention of this feature was that if it - detected a request coming in from a browser, it would serve up JSON/XML - using content types that caused the browsers to pretty print. But - each browser has different rules for when to pretty print, and - after we wrote that feature both Chrome and FF changed their rules to break it anyhow. - ResponseHighlightingInterceptor provides a better implementation of - this functionality and should be used instead. - - - Narrative generator framework has removed the - ability to generate resource titles. This - functionality was only useful for DSTU1 - implementations and wasn't compatible - with coming changes to that API. - - - Remove dependency on Servlet-API 3.0+ by using methods available in 2.5 where possible. - Note that we continue to use Servlet-API 3.0+ features in some parts of the JPA API, so - running in an old serlvet container should be tested well before use. Thanks to Bill Denton - for reporting! - - - Add new methods to RestfulClientFactory allowing you to configure the size of the - client pool used by Apache HttpClient. Thanks to Matt Blanchette for the pull - request! - - - Add support for new modifier types on Token search params in Server and - annotation client. - - - Server conformance statement should include search parameter chains if the - chains are explicitly defined via @Search(whitelist={....}). Thanks to lcamilo15 - for reporting! - - - Remove afterPropertiesSet() call in Java config for JPA - server's EntityManagerFactory. This doesn't need to be called - manually, the the manual call led to a warning about - the EntityManager being created twice. - - - Allow server to correctly figure out it's own address even if the container provides - a Servlet Context Path which does not include the root. Thanks to Petro Mykhaylyshyn - for the pull request! - -
    - - - Bump the version of a few dependencies to the - latest versions (dependent HAPI modules listed in brackets): - -
  • Commons-lang3 (Core): 3.3.2 -> 3.4
  • -
  • Logback (Core): 1.1.2 -> 1.1.3
  • -
  • SLF4j (Core): 1.7.102 -> 1.7.12
  • -
  • Springframework (JPA, Web Tester): 4.1.5 -> 4.2.2
  • -
  • Hibernate (JPA, Web Tester): 4.2.17 -> 5."
  • -
  • Hibernate Validator (JPA, Web Tester): 5.2.1 -> 5.2.2
  • -
  • Derby (JPA, CLI, Public Server): 10.11.1.1 -> 10.12.1.1
  • -
  • Jetty (JPA, CLI, Public Server): 9.2.6.v20141205 -> 9.3.4.v20151007
  • - - ]]> -
    - - JPA and Tester Overlay now use Spring Java config files instead - of the older XML config files. All example projects have been updated. - - - JPA server removes duplicate resource index entries before storing them - (e.g. if a patient has the same name twice, only one index entry is created - for that name) - - - JPA server did not correctly index search parameters of type "reference" where the - path had multiple entries (i.e. "Resource.path1 | Resource.path2") - - - JPA server _history operations (server, type, instance) not correctly set the - Bundle.entry.request.method to POST or PUT for create and updates of the resource. - - - Support AND/OR on _id search parameter in JPA - - - Constructor for DateRanfeParam which dates in two DateParam instances was ignoring - comparators on the DateParam. - - - In JSON parsing, finding an object where an array was expected led to an unhelpful - error message. Thanks to Avinash Shanbhag for reporting! - - - JPA server gave an unhelpful error message if $meta-add or $meta-delete were called - with no meta elements in the input Parameters - - - Narrative generator did not include OperationOutcome.issue.diagnostics in the - generated narrative. - - - Clients (generic and annotation) did not populate the Accept header on outgoing - requests. This is now populated to indicate that the client supports both XML and - JSON unless the user has explicitly requested one or the other (in which case the - appropriate type only will be send in the accept header). Thanks to - Avinash Shanbhag for reporting! - - - QuestionnaireResponse validator now allows responses to questions of - type OPENCHOICE to be of type 'string' - - - JPA server should reject resources with a reference that points to an incorrectly typed - resource (e.g. points to Patient/123 but resource 123 is actually an Observation) or points - to a resource that is not valid in the location it is found in (e.g. points to Patient/123 but - the field supposed to reference an Organization). Thanks to Bill de Beaubien for reporting! - - - In server, if a client request is received and it has an Accept header indicating - that it supports both XML and JSON with equal weight, the server's default is used instead of the first entry in the list. - - - JPA server now supports searching with sort by token, quantity, - number, Uri, and _lastUpdated (previously only string, date, and _id - were supported) - - - Fix issue in JPA where a search with a _lastUpdated filter which matches no results - would crash if the search also had a _sort - - - Fix several cases where invalid requests would cause an HTTP 500 instead of - a more appropriate 400/404 in the JPA server (vread on invalid version, - delete with no ID, etc.) - - - Fix narrative generation for DSTU2 Medication resource - - - Profile validator now works for valuesets which use - v2 tables - - - JPA server Patient/[id]/$everything operation now supports - _lastUpdated filtering and _sort'ing of results. - - - Fix parser issue where profiled choice element datatypes (e.g. value[x] where one allowable - type is Duration, which is a profile of Quantity) get incorrectly encoded using the - profiled datatype name instead of the base datatype name as required by the FHIR - spec. Thanks to Nehashri Puttu Lokesh for reporting! - - - Some generated Enum types in DSTU2 HAPI structures - did not have latest valueset definitions applied. Thanks - to Bill de Beaubien for reporting! - - - JPA server can now successfully search for tokens pointing at code values - (values with no explicit system but an implied one, such as Patient.gender) - even if the system is supplied in the query. - - - Correct issues with Android library. Thanks to - Thomas Andersen for the submission! - - - JPA server incorrectly rejected match URLs - if they did not contain a question mark. Thanks - to Bill de Beaubien for reporting! - - - Remove invalid entries in OSGi Manifest. Thanks - to Alexander Kley for the fix! - - - JPA server now supports $everything on Patient and Encounter types (patient and encounter instance was already supported) - - - Generic client operation invocations now - have an additional inline method for generating the input - Parameters using chained method calls instead - of by passing a Parameters resource in - - - Parsing an XML resource where the XHTML - namespace was declared before the beginning - of the narrative section caused an invalid - re-encoding when encoding to JSON. - - - Conditional deletes in JPA did not correctly - process if the condition had a chain or a - qualifier, e.g. "Patient?organization.name" or - "Patient.identifier:missing" - - - Generic/fluent client search can now be - performed using a complete URL supplied - by user code. Thanks to Simone Heckmann - pointing out that this was needed! - - - Refactor JPA $everything operations so that - they perform better - - - Server operation methods can now declare the - ID optional, via - @IdParam(optional=true) - meaning that the same operation can also be invoked - at the type level. - - - Make JPA search queries with _lastUpdated parameter a bit more efficient - - - Clean up Android project to make it more lightweight and remove a - number of unneeded dependencies. Thanks to Thomas Andersen - for the pull request! - - - Fix a crash when encoding a Binary resource in JSON encoding - if the resource has no content-type - - - JPA server now supports read/history/search in transaction entries - by calling the actual implementing method in the server (previously - the call was simulated, which meant that many features did not work) - - - ResourceReferenceDt#loadResource(IRestfulClient) did not - use the client's read functionality, so it did not - handle JSON responses or use interceptors. Thanks to - JT for reporting! - - - JPA server maximumn length for a URI search parameter has been reduced from - 256 to 255 in order to accomodate MySQL's indexing requirements - - - Server failed to respond correctly to compartment search operations - if the same provider also contained a read operation. Thanks to GitHub user - @am202 for reporting! - - - Fix issue in testpage-overlay's new Java configuration where only the first - configured server actually gets used. - - - Introduce - IJpaServerInterceptor]]> - interceptors for JPA server which can be used for more fine grained operations. - - - Parser (XML and JSON) shouldn't encode an ID tag in resources - which are part of a bundle when the resource has a UUID/OID - ID. - - - Add ability for a server REST resource provider @Search method - to declare that it should allow even parameters it doesn't - understand. - - - Correctly set the Bundle.type value on all pages of a search result in - the server, and correcltly set the same value in JPA server $everything - results. - - - JPA $everything operations now support new parameters _content - and _text, which work the same way as the same parameters on a - search. This is experimental, since it is not a part of the core - FHIR specification. - - - Process "Accept: text/xml" and "Accept: text/json" headers was - wanting the equivalent FHIR encoding styles. These are not - correct, but the intention is clear so we will honour them - just to be helpful. - - - Generated Enum types for some ValueSets did not include all - codes (specifically, ValueSets which defined concepts containing - child concepts did not result in Enum values for the child concepts) - - - In the JPA server, order of transaction processing should be - DELETE, POST, PUT, GET, and the order should not matter - within entries with the same verb. Thanks to Bill de Beaubien - for reporting! - - - Add the ability to wire JPA conformance providers - using Spring (basically, add default constructors - and setters to the conformance providers). Thanks - to C. Mike Bylund for the pull request! - -
    - - - JPA server now validates QuestionnaireAnswers for conformance to their respective Questionnaire - if one is declared. - - - SyntaxHighlightingInterceptor now also highlights OperationOutcome responses for errors/exceptions. - - - Model classes do not use BoundCodeableConcept for example bindings that do not - actually point to any codes (e.g. Observation.interpretation). Thanks - to GitHub user @steve1medix for reporting! - - - Server now exports operations as separate resources instead of as contained resources - within Conformance - - - Add new operation $get-resource-counts which will replace the resource - count extensions exported in the Conformance statement by the JPA - server. - - - JPA server sorting often returned unexpected orders when multiple - indexes of the same type were found on the same resource (e.g. multiple string indexed fields). Thanks to Travis Cummings for reporting! - - - Add another method to IServerInterceptor which converts an exception generated on the server - into a BaseServerResponseException. This is useful so that servers using ResponseHighlighterInterceptor - will highlight exceptions even if they aren't created with an OperationOutcome. - - - XmlParser and JsonParser in DSTU2 mode should not encode empty - tags in resource. Thanks to Bill De Beaubien for reporting! - - - OperationDefinitions generated by server did not properly document - their return parameters or the type of their input parameters. - - - Operations in server generated conformance statement should only - appear once per name, since the name needs to be unique. - - - Resources and datatypes are now serializable. This is an - experimental feature which hasn't yet been extensively tested. Please test and give us your feedback! - - - Switch REST server to using HttpServletRequest#getContextPath() to get - the servlet's context path. This means that the server should behave more - predictably, and should work in servlet 2.4 environments. Thanks to - Ken Zeisset for the suggestion! - - - Vagrant environment now has an apt recipt to ensure that - package lists are up to date. Thanks to GitHub user - Brian S. Corbin (@corbinbs) for thr contribution! - - - JPA server and generic client now both support the _tag search parameter - - - Add support for BATCH mode to JPA server transaction operation - - - Server was not correctly unescaping URL parameter values with - a trailing comma or an escaped backslash. Thanks to GitHub user - @SherryH for all of her help in diagnosing this issue! - - - Avoid crash when parsing if an invalid child element is found in - a resource reference. - - - Create new android specialty libraries for DSTU1 and DSTU2 - - - Throwing a server exception (e.g. AuthenticationException) in a server interceptor's - incomingRequestPreProcessed method resulted in the server returning an HTTP 500 instead - of the appropriate error code for the exception being thrown. Thanks to Nagesh Bashyam - for reporting! - - - Fix issue in JSON parser where invalid contained resources (missing - a resourceType element) fail to parse with a confusing NullPointerException. - Thanks to GitHub user @hugosoares for reporting! - - - JPA server now implements the $validate-code operation - - - HAPI-FHIR now has support for _summary and _elements parameters, in server, client, - and JPA server. - - - _revinclude results from JPA server should have a Bundle.entry.search.mode of - "include" and not "match". Thanks to Josh Mandel for reporting! - - - Resource references using resource instance objects instead of resource IDs - will correctly qualify the IDs with the resource type if they aren't already qualified - - - Testpage Overlay project now properly allows a custom client - factory to be used (e.g. for custom authentication, etc.) Thanks - to Chin Huang (@pukkaone) for the pull request! - - - JPA server should reject IDs containing invalid characters (e.g. "abc:123") - but should allow client assigned IDs that contain text but do not start with - text. Thanks to Josh Mandel for reporting! - - - :text modifier on server and JPA server did not work correctly. Thanks to - Josh Mandel for reporting! - - - Fix issue in client where parameter values containing a comma were - sometimes double escaped. - - - _include parameters now support the new _include:recurse=FOO]]> - syntax that has been introduced in DSTU2 in the Client, Server, and JPA Server modules. - Non-recursive behaviour is now the default (previously it was recursive) and :recurse - needs to be explicitly stated in order to support recursion. - - - New operations added to JPA server to force re-indexing of all - resources (really only useful after indexes change or bugs are - fixed) - - - JPA server did not correctly index search parameters - of type "URI". Thanks to David Hay for reporting! Note that if you are using the JPA server, this change means that - there are two new tables added to the database schema. Updating existing resources in the database may fail unless you - set default values for the resource - table by issuing a SQL command similar to the following (false may be 0 or something else, depending on the database platform in use) - update hfj_resource set sp_coords_present = false;
    - update hfj_resource set sp_uri_present = false;
    ]]> -
    - - FIx issue in JPA server where profile declarations, tags, and - security labels were not always properly removed by an update that - was trying to remove them. Also don't store duplicates. - - - Instance $meta operations on JPA server did not previously return the - resource version and lastUpdated time - - - Server responses populate Bundle.entry.fullUrl if possible. Thanks - to Bill de Beaubien for reporting! - - - XML parser failed to initialize in environments where a very old Woodstox - library is in use (earlier than 4.0). Thanks to Bill de Beaubien for - reporting! - - - Invalid/unexpected attributes found when parsing composite elements - should be logged or reported to the parser error handler - - - JPA server can now store Conformance resources, per a request - from David Hay - - - ResponseHighlightingInterceptor now skips handling responses if it - finds a URL parameter of _raw=true]]> (in other - words, if this parameter is found, the response won't be returned as - HTML even if the request is detected as coming from a browser. - - - RestfulServer now supports dynamically adding and removing resource providers - at runtime. Thanks to Bill Denton for adding this. - - - JPA server now correctly suppresses contents of deleted resources - in history - - - JPA server returned deleted resources in search results when using the _tag, _id, _profile, or _security search parameters - - - Fix issue with build on Windows. Thanks to Bryce van Dyk for the pull request! - - - JPA server now supports $validate operation completely, including delete mode - and profile validation using the RI InstanceValidator - -
    - - - Add support for reference implementation structures. - - - Parsers did not encode the resource meta element if the resource - had tags but no other meta elements. Thanks to Bill de Beaubien and - Claude Nanjo for finding this. - - - Correct performance issue with :missing=true search requests where the parameter is a resource link. Thanks to wanghaisheng for all his help in testing this. - - - The self link in the Bundle returned by searches on the server does not respect the - server's address strategy (which resulted in an internal IP being shown on fhirtest.uhn.ca) - - - Introduce ResponseHighlighterInterceptor, which provides syntax highlighting on RESTful server responses - if the server detects that the request is coming from a browser. This interceptor has been added - to fhirtest.uhn.ca responses. - - - Performing a create operation in a client used an incorrect URL if the - resource had an ID set. ID should be ignored for creates. Thanks to - Peter Girard for reporting! - - - Add better addXXX() methods to structures, which take the datatype being added as a parameter. Thanks to Claude Nanjo for the - suggestion! - - - Add a new parser validation mechanism (see the - validation page]]> for info) which can be - used to validate resources as they are being parsed, and optionally fail if invalid/unexpected - elements are found in resource bodies during parsing. - - - IParser#parseResource(Class, String) method, which is used to parse a resource into the given - structure will now throw a DataFormatException if the structure is for the wrong type of - resource for the one actually found in the input String (or Reader). For example, if a Patient - resource is being parsed into Organization.class this will now cause an error. Previously, - the XML parser would ignore the type and the JSON parser would fail. This also caused - operations to not parse correctly if they returned a resource type other than - parameters with JSON encoding (e.g. the $everything operation on UHN's test server). - Thanks to Avinash Shanbhag for reporting! - - - Web tester UI now supports _revinclude - - - Support link elements in Bundle.entry when parsing in DSTU2 mode - using the old (non-resource) Bundle class. Thanks to GitHub user - @joedai for reporting! - - - LoggingInterceptor for server now supports logging DSTU2 extended operations by name - - - Woodstox XML parser has a default setting to limit the maximum - length of an attribute to 512kb. This caused issues handling - large attachments, so this setting has been increased to 100Mb. - Thanks to Nikos Kyriakoulakos for reporting! - - - Some HTML entities were not correctly converted during parsing. Thanks to - Nick Kitto for reporting! - - - In the JPA Server: - Transactions creating resources with temporary/placeholder resource IDs - and other resources with references to those placeholder IDs previously - did not work if the reference did not contain the resource type - (e.g. Patient/urn:oid:0.1.2.3 instead of urn:oid:0.1.2.3). The - latter is actually the correct way of specifying a reference to a - placeholder, but the former was the only way that worked. Both forms - now work, in order to be lenient. Thanks to Bill De Beaubien for - reporting! - - - When parsing Bundles, if Bundle.entry.base is set to "cid:" (for DSTU1) - or "urn:uuid:" / "urn:oid:" (for DSTU2) this is now correctly passed as - the base in resource.getId(). Conversely, when - encoding bundles, if a resource ID has a base defined, - and Bundle.entry.base is empty, it will now be - automatically set by the parser. - - - Add fluent client method for validate operation, and support the - new DSTU2 style extended operation for $validate if the client is - in DSTU2 mode. Thanks to Eric from the FHIR Skype Implementers chat for - reporting. - - - Server now supports complete Accept header content negotiation, including - q values specifying order of preference. Previously the q value was ignored. - - - Server in DSTU2 mode now indicates that whether it has support for Transaction operation or not. Thanks to Kevin Paschke for pointing out that this wasn't working! - - - Questionnaire.title now gets correctly indexed in JPA server (it has no path, so it is a special case) - - - JPA server now supports ifNoneMatch in GET within a transaction request. - - - DateRangeParam now supports null values in the constructor for lower or upper bounds (but - still not both) - - - Generic/fluent client and JPA server now both support _lastUpdated search parameter - which was added in DSTU2 - - - JPA server now supports sorting on reference parameters. Thanks to - Vishal Kachroo for reporting that this wasn't working! - - - Prevent Last-Updated header in responses coming back to the client from - overwriting the 'lastUpdated' value in the meta element in DSTU2 - resources. This is important because 'lastUpdated' can have more - precision than the equivalent header, but the client previously - gave the header priority. - - - JPA server supports _count parameter in transaction containing search URL (nested search) - - - DSTU2 servers now indicate support for conditional create/update/delete in their - conformance statement. - - - Support for the Prefer header has been added to the server, client, and - JPA modules. - - - JPA server failed to search for deep chained parameters across multiple references, - e.g. "Location.partof.partof.organization". Thanks to Ismael Sarmento Jr for - reporting! - - - Prevent crash when encoding resources with contained resources - if the contained resources contained a circular reference to each other - - - Add $meta, $meta-add, and $meta-delete operations to generic client - - - - - Bump the version of a few dependencies to the - latest versions: - -
  • Phloc-commons (for schematron validation) 4.3.5 -> 4.3.6
  • -
  • Apache HttpClient 4.3.6 -> 4.4
  • -
  • Woodstox 4.4.0 -> 4.4.1
  • -
  • SLF4j 1.7.9 -> 1.7.10
  • -
  • Spring (used in hapi-fhir-jpaserver-base module) 4.1.3.RELEASE -> 4.1.5.RELEASE
  • - - ]]> -
    - - Add support for "profile" and "tag" elements in the resource Meta block - when parsing DSTU2 structures. - - - When a user manually creates the list of contained resources in a resource, - the encoder fails to encode any resources that don't have a '#' at the - start of their ID. This is unintuitive, so we now assume that '123' means '#123'. - Thanks to myungchoi for reporting and providing a test case! - - - Add methods for setting the default encoding (XML/JSON) and - oretty print behaviour in the Fluent Client. Thanks to Stackoverflow - user ewall for the idea. - - - JPA Server did not mark a resource as "no longer deleted" if it - was updated after being deleted. Thanks to Elliott Lavy and Lloyd - McKenzie for reporting! - - - Fix regression in 0.9 - Server responds with an HTTP 500 and a NullPointerException instead of an HTTP 400 and a useful error message if the client requests an unknown resource type - - - Add support for - _revinclude]]> - parameter in client, server, and JPA. - - - Include constants on resources (such as - Observation.INCLUDE_VALUE_STRING]]>) - have been switched in the DSTU2 structures to use - the new syntax required in DSTU2: [resource name]:[search param NAME] - insead of the DSTU1 style [resource name].[search param PATH] - - - When encoding resources, the parser will now convert any resource - references to versionless references automatically (i.e. it will - omit the version part automatically if one is present in the reference) - since references between resources must be versionless. Additionally, - references in server responses will omit the server base URL part of the - reference if the base matches the base for the server giving - the response. - - - Narrative generator incorrectly sets the Resource.text.status to 'generated' even if the - given resource type does not have a template (and therefore no narrative is actually generated). - Thanks to Bill de Beaubien for reporting! - - - Searching in JPA server with no search parameter returns deleted resources when it should exclude them. - - - Remove Eclipse and IntelliJ artifacts (.project, *.iml, etc) from version control. Thanks - to Doug Martin for the suggestion! - - - REST server methods may now have a parameter of - type NarrativeModeEnum which will be populated with - the value of the _narrative URL parameter - if one was supplied. Annotation client methods - may also include a parameter of this type, and it - will be used to populate this parameter on the request - URL if it is not null. Thanks to Neal Acharya for the - idea! - - - Android JAR now includes servlet-API classes, as the project will not - work without them. Thanks - - - Requested _include values are preserved across paging links when the - server returns multiple pages. Thanks to Bill de Beaubien for - reporting! - - - Add new server address strategy "ApacheProxyAddressStrategy" which uses - headers "x-forwarded-host" and "x-forwarded-proto" to determine the - server's address. This is useful if you are deploying a HAPI FHIR - server behind an Apache proxy (e.g. for load balancing or other reasons). - Thanks to Bill de Beaubien for contributing! - - - Resource references between separate resources found in a single - bundle did not get populated with the actual resource when parsing a - DSTU2 style bundle. Thanks to Nick Peterson for reporting and figuring - out why none of our unit tests were actually catching the problem! - - - JSON encoder did not encode contained resources when encoding - a DSTU2 style bundle. Thanks to Mohammad Jafari and baopingle - for all of their help in tracking this issue down and developing - useful unit tests to demonstrate it. - - - Client now supports invoking transcation using a DSTU2-style - Bundle resource as the input. - - - JPA Server $everything operation could sometimes include a duplicate copy of - the main focus resource if it was referred to in a deep chain. Thanks - to David Hay for reporting! - - - JPA Server $everything operation now allows a _count parameter - - - JPA server failed to index resources containing ContactPointDt elements with - populated values (e.g. Patient.telecom). Thanks to Mohammad Jafari for reporting! - - - Add a new configuration method on the parsers, - setStripVersionsFromReferences(boolean)]]> which - configures the parser to preserve versions in resource reference links when - encoding. By default, these are removed. - - - Terser's IModelVisitor now supplies to the path to the element. This is - an API change, but I don't think there are many users of the IModelVisitor yet. - Please let us know if this is a big hardship and we can find an alternate way - of making this change. - - - Prevent server from returning a Content-Location header for search - response when using the DSTU2 bundle format - - - JPA server (uhnfhirtest.uhn.ca) sometimes included an empty - "text" element in Bundles being returned. - - - Add a framework for the Web Tester UI to allow its internal FHIR client to - be configured (e.g. to add an authorization interceptor so that it adds - credentials to client requests it makes). Thanks to Harsha Kumara for - the suggestion! - - - Fix regression in early 1.0 builds where resource type sometimes does not get - populated in a resource ID when the resource is parsed. Thanks to - Nick Peterson for reporting, and for providing a test case! - - - Allow fluent/generic client users to execute a transaction using a raw string (containing a bundle resource) - as input instead of a Bundle resource class instance. - - - Disable date validation in the web tester UI, so that it is possible to - enter partial dates, or dates without times, or even test out invalid date - options. - - - Make BaseElement#getUndeclaredExtensions() and BaseElement#getUndeclaredExtensions() return - a mutable list so that it is possible to delete extensions from a resource instance. - - - Server conformance statement check in clients (this is the check - where the first time a given FhirContext is used to access a given server - base URL, it will first check the server's Conformance statement to ensure - that it supports the correct version of FHIR) now uses any - registered client interceptors. In addition, IGenericClient now has a method - "forceConformanceCheck()" which manually triggers this check. Thanks to - Doug Martin for reporting and suggesting! - - - Rename the Spring Bean definition for the JPA server EntityManager from - "myEntityManagerFactory" to just "entityManagerFactory" as this is the - default bean name expected in other parts of the Spring framework. - Thanks to Mohammad Jafari for the suggestion! - - - Improve error message when a user tries to perform a create/update with an invalid - or missing Content-Type header. Thanks to wanghaisheng for reporting! (This was - actually a three part bug, so the following two fixes also reference this - bug number) - - - Add support for :missing qualifier in generic/fluent client. - - - Add support for :missing qualifier in JPA server. - - - Add a new configuration method on the parsers, - setStripVersionsFromReferences(boolean)]]> which - configures the parser to preserve versions in resource reference links when - encoding. By default, these are removed. - - - Add an exception for RESTful clients/servers to represent the - HTTP 403 Forbidden status code. Thanks to Joel Costigliola for - the patch! - - - Transaction server operations incorrectly used the "Accept" header instead of the "Content-Type" header to determine the - POST request encoding. Thanks to Rene Spronk for providing a test case! - -
    - - - Support for DSTU2 features introduced: New resource definitions, Bundle resource, - encoding changes (ID in resource bodt, meta tag) - - - Fix an issue encoding extensions on primitive types in JSON. Previously the "_value" object - would be an array even if the field it was extending was not repeatable. This is not correct - according to the specification, nor can HAPI's parser parse this correctly. The encoder - has been corrected, and the parser has been adjusted to be able to handle resources with - extensions encoded in this way. Thanks to Mohammad Jafari for reporting! - - - Library now checks if custom resource types can be instantiated on startup - (e.g. because they don't have a no-argument constructor) in order to - avoid failing later - - - Bump a few dependency JARs to the latest versions in Maven POM: - -
  • SLF4j (in base module) - Bumped to 1.7.9
  • -
  • Apache HTTPClient (in base module) - Bumped to 4.3.6
  • -
  • Hibernate (in JPA module) - Bumped to 4.3.7
  • - - ]]> -
    - - IdDt failed to recognize local identifiers containing fragments that look like - real identifiers as being local identifiers even though they started with '#'. - For example, a local resource reference of "#aa/_history/aa" would be incorrectly - parsed as a non-local reference. - Thanks to Mohammad Jafari for reporting! - - - Last-Modified]]> - header in server was incorrectly using FHIR date format instead - of RFC-1123 format. - - - Server create and update methods failed with an IllegalArgumentException if - the method type was a custom resource definition type (instead of a built-in - HAPI type). Thanks to Neal Acharya for the analysis. - - - JPA server module now supports - _include]]> - value of - *]]>. Thanks to Bill de Beaubien for reporting! - - - IdDt method - - returned String (unlike all of the other "withFoo" methods on that class), - and did not work correctly if the IdDt already had a server base. This - has been corrected. Note that the return type for this method has been - changed, so code may need to be updated. - - - In previous versions of HAPI, the XML parser encoded multiple contained - resources in a single - <contained></contained>]]> - tag, even though the FHIR specification rerquires a separate - <contained></contained>]]> - tag for each resource. This has been corrected. Note that the parser will - correctly parse either form (this has always been the case) so this - change should not cause any breakage in HAPI based trading partners, but - may cause issues if other applications have been coded to depend on the - incorrect behaviour. Thanks to Mochaholic for reporting! - - - Custom/user defined resource definitions which contained more than one - child with no order defined failed to initialize properly. Thanks to - Andy Huang for reporting and figuring out where the - problem was! - - - RESTful Client now queries the server (only once per server base URL) to ensure that - the given server corresponds to the correct version of the FHIR specification, as - defined by the FhirContext. This behaviour can be disabled by setting the - appropriate configuration on the - RestfulClientConfig. Thanks to Grahame Grieve for the suggestion! - - - JPA module now supports deleting resource via transaction - - - DateClientParam#second() incorrectly used DAY precision instead - of SECOND precision. Thanks to Tom Wilson for the pull request! - - - Fix issue where HAPI failed to initialize correctly if Woodstox library was not on the classpath, even - if StAX API was configured to use a different provider. Thanks to - James Butler for reporting and figuring out where the issue was! - - - Calling BaseDateTimeDt#setValue(Date, TemporalPrecisionEnum) did not always actually respect - the given precision when the value was encoded. Thanks to jacksonjesse for - reporting! - - - Encoders (both XML and JSON) will no longer encode contained resources if they are - not referenced anywhere in the resource via a local reference. This is just a convenience - for users who have parsed a resource with contained resources and want to remove some - before re-encoding. Thanks to Alexander Kley for reporting! - - - Add support for DSTU2 style security labels in the parser and encoder. Thanks to - Mohammad Jafari for the contribution! - - - Server requests for Binary resources where the client has explicitly requested XML or JSON responses - (either with a _format]]> URL parameter, or an Accept]]> request header) - will be responded to using the Binary FHIR resource type instead of as Binary blobs. This is - in accordance with the recommended behaviour in the FHIR specification. - - - Add new properties to RestfulServer: "DefaultResponseEncoding", which allows - users to configure a default encoding (XML/JSON) to use if none is specified in the - client request. Currently defaults to XML. Also "DefaultPrettyPrint", which specifies - whether to pretty print responses by default. Both properties can be overridden - on individual requets using the appropriate Accept header or request URL parameters. - - - Add support for quantity search params in FHIR tester UI - - - Add support for FHIR "extended operations" as defined in the FHIR DSTU2 - specification, for the Generic Client, Annotation Client, and - Server. - - - Observation.applies[x] and other similar search fields with multiple allowable - value types were not being correctly indexed in the JPA server. - - - DateClientParam.before() incorrectly placed "<=" instead of - "<" in the request URL. Thanks to Ryan for reporting! - - - Server now only automatically adds _include resources which are provided - as references if the client request actually requested that specific include. - See RestfulServer - - - User defined resource types which contain extensions that use a bound code type - (e.g. an BoundCodeDt with a custom Enum) failed to parse correctly. Thanks - to baopingle for reporting and providing a test case! - - - Sorting is now supported in the Web Testing UI (previously a button existed for sorting, but it didn't do anything) - - - Server will no longer include stack traces in the OperationOutcome returned to the client - when an exception is thrown. A new interceptor called ExceptionHandlingInterceptor has been - created which adds this functionality back if it is needed (e.g. for DEV setups). See the - server interceptor documentation for more information. Thanks to Andy Huang for the suggestion! - -
    - - - API CHANGE:]]> The "FHIR structures" for DSTU1 (the classes which model the - resources and composite datatypes) have been moved out of the core JAR into their - own JAR, in order to allow support for DEV resources, and DSTU2 resources when thast - version is finalized. See the - DSTU2 page]]> - for more information. - - - Deprocated API Removal: The following classes (which were deprocated previously) - have now been removed: -
      -
    • ISecurityManager: If you are using this class, the same functionality - is available through the more general purpose - server interceptor - capabilities. -
    • CodingListParam: This class was made redundant by the - TokenOrListParam - class, which can be used in its place. -
    - ]]> -
    - - API Change: The IResource#getResourceMetadata() method has been changed - from returning - Map<ResourceMetadataKeyEnum<?>, Object> - to returning a new type called - ResourceMetadataMap. This new type implements - Map<ResourceMetadataKeyEnum<?>, Object> - itself, so this change should not break existing code, but may - require a clean build in order to run correctly. - ]]> - - - Profile generation on the server was not working due to IdDt being - incorrectly used. Thanks to Bill de Beaubien for the pull request! - - - Profiles did not generate correctly if a resource definition class had a - defined extension which was of a composite type. Thanks to Bill de Beaubien for the pull request! - - - Remove unnecessary IOException from narrative generator API. Thanks to - Petro Mykhailysyn for the pull request! - - - Introduced a new - @ProvidesResources]]> annotation which can be added to - resource provider and servers to allow them to declare additional resource - classes they are able to serve. This is useful if you have a server which can - serve up multiple classes for the same resource type (e.g. a server that sometimes - returns a default Patient, but sometimes uses a custom subclass). - Thanks to Bill de Beaubien for the pull request! - - - Introduced a new - @Destroy]]> annotation which can be added to - a resource provider method. This method will be called by the server when it - is being closed/destroyed (e.g. when the application is being undeployed, the - container is being shut down, etc.) - Thanks to Bill de Beaubien for the pull request! - - - Add a new method to the server interceptor - framework which allows interceptors to be notified of any exceptions and - runtime errors within server methods. Interceptors may optionally also - override the default error handling behaviour of the RestfulServer. - - - Add constants to BaseResource for the "_id" search parameter which all resources - should support. - - - DateRangeParam parameters on the server now return correct - getLowerBoundAsInstant()]]> - and - getUpperBoundAsInstant()]]> - values if a single unqualified value is passed in. For example, if - a query containing - &birthdate=2012-10-01]]> - is received, previously these two methods would both return the same - value, but with this fix - getUpperBoundAsInstant()]]> - now returns the instant at 23:59:59.9999. - - - Resource fields with a type of "*" (or Any) sometimes failed to parse if a - value type of "code" was used. Thanks to Bill de Beaubien for reporting! - - - Remove dependency on JAXB libraries, which were used to parse and encode - dates and times (even in the JSON parser). JAXB is built in to most JDKs - but the version bundled with IBM's JDK is flaky and resulted in a number - of problems when deploying to Websphere. - - - Primitive datatypes now preserve their original string value when parsing resources, - as well as containing the "parsed value". For instance, a DecimalDt field value of - 1.0000]]> will be parsed into the corresponding - decimal value, but will also retain the original value with the corresponding - level of precision. This allows vadliator rules to be applied to - original values as received "over the wire", such as well formatted but - invalid dates, e.g. "2001-15-01". Thanks to Joe Athman for reporting and - helping to come up with a fix! - - - When using Generic Client, if performing a - or operation using a String as the resource body, - the client will auto-detect the FHIR encoding style and send an appropriate - header. - - - JPA module (and public HAPI-FHIR test server) were unable to process resource types - where at least one search parameter has no path specified. These now correctly save - (although the server does not yet process these params, and it should). Thanks to - GitHub user shvoidlee for reporting and help with analysis! - - - Generic/Fluent Client "create" and "update" method requests were not setting a content type header - - - DateDt left precision value as in the constructor - . - - - RESTful server now doesn't overwrite resource IDs if they are absolute. In other words, if - a server's Resource Provider returns a resource with ID "Patient/123" it will be translated to - "[base url]/Patient/123" but if the RP returns ID "http://foo/Patient/123" the ID will be - returned exactly as is. Thanks to Bill de Beaubien for the suggestion! - - - JPA module Transaction operation was not correctly replacing logical IDs - beginning with "cid:" with server assigned IDs, as required by the - specification. - - - did not visit or find children in contained resources when - searching a resource. This caused server implementations to not always return contained - resources when they are included with a resource being returned. - - - Add a method which returns the name of the - resource in question (e.g. "Patient", or "Observation"). This is intended as a - convenience to users. - - - Do not strip version from resource references in resources returned - from server search methods. Thanks to Bill de Beaubien for reporting! - - - Correct an issue with the validator where changes to the underlying - OperationOutcome produced by a validation cycle cause the validation - results to be incorrect. - - - Client interceptors registered to an interface based client instance - were applied to other client instances for the same client interface as well. (Issue - did not affect generic/fluent clients) - - - DateDt, DateTimeDt and types InstantDt types now do not throw an exception - if they are used to parse a value with the wrong level of precision for - the given type but do throw an exception if the wrong level of precision - is passed into their constructors.
    ]]> - This means that HAPI FHIR can now successfully parse resources from external - sources that have the wrong level of precision, but will generate a validation - error if the resource is validated. Thanks to Alexander Kley for the suggestion! -
    - - Encoding a Binary resource without a content type set should not result in a NullPointerException. Thanks - to Alexander Kley for reporting! - - - Server gives a more helpful error message if multiple IResourceProvider implementations - are provided for the same resource type. Thanks to wanghaisheng for the idea! - - - Bring DSTU1 resource definitions up to version 0.0.82-2929]]> - Bring DEV resource definitions up to 0.4.0-3775]]> - Thanks to crinacimpian for reporting! - - - JPA server did not correctly process _include requests if included - resources were present with a non-numeric identifier. Thanks to - Bill de Beaubien for reporting! - - - Client requests which include a resource/bundle body (e.g. create, - update, transaction) were not including a charset in the content type - header, leading to servers incorrectly assuming ISO-8859/1. Thanks to - shvoidlee for reporting! - - - Clean up the way that Profile resources are automatically exported - by the server for custom resource profile classes. See the - @ResourceDef]]> - JavaDoc for information on how this works. - - - Add convenience methods to TokenOrListParam to test whether any of a set of tokens match - the given requested list. - - - Add a protected method to RestfulServer which allows developers to - implement their own method for determining which part of the request - URL is the FHIR request path (useful if you are embedding the RestulServer inside - of another web framework). Thanks to Harsha Kumara for the pull request! - -
    - - - API CHANGE:]]> The TagList class previously implemented ArrayList semantics, - but this has been replaced with LinkedHashMap semantics. This means that the list of - tags will no longer accept duplicate tags, but that tag order will still be - preserved. Thanks to Bill de Beaubien for reporting! - - - Server was incorrectly including contained resources being returned as both contained resources, and as - top-level resources in the returned bundle for search operations. - Thanks to Bill de Beaubien for reporting! This also fixes Issue #20, thanks to - lephty for reporting! - - - Documentation fixes - - - Add a collection of new methods on the generic client which support the - read, - read, - and search - ]]> - operations using an absolute URL. This allows developers to perform these operations using - URLs they obtained from other sources (or external resource references within resources). In - addition, the existing read/vread operations will now access absolute URL references if - they are passed in. Thanks to Doug Martin of the Regenstrief Center for Biomedical Informatics - for contributing this implementation! - - - Server implementation was not correctly figuring out its own FHIR Base URL when deployed - on Amazon Web Service server. Thanks to Jeffrey Ting and Bill De Beaubien of - Systems Made Simple for their help in figuring out this issue! - - - XML Parser failed to encode fields with both a resource reference child and - a primitive type child. Thanks to Jeffrey Ting and Bill De Beaubien of - Systems Made Simple for their help in figuring out this issue! - - - HAPI now runs successfully on Servlet 2.5 containers (such as Tomcat 6). Thanks to - Bernard Gitaadji for reporting and diagnosing the issue! - - - Summary (in the bundle entry) is now encoded by the XML and JSON parsers if supplied. Thanks to David Hay of - Orion Health for reporting this! - - - Conformance profiles which are automatically generated by the server were missing a few mandatory elements, - which meant that the profile did not correctly validate. Thanks to Bill de Beaubien of Systems Made Simple - for reporting this! - - - XHTML (in narratives) containing escapable characters (e.g. < or ") will now always have those characters - escaped properly in encoded messages. - - - Resources containing entities which are not valid in basic XML (e.g. &sect;) will have those - entities converted to their equivalent unicode characters when resources are encoded, since FHIR does - not allow extended entities in resource instances. - - - Add a new client interceptor which adds HTTP Authorization Bearer Tokens (for use with OAUTH2 servers) - to client requests. - - - Add phloc-commons dependency explicitly, which resolves an issue building HAPI from source on - some platforms. Thanks to Odysseas Pentakalos for the patch! - - - HAPI now logs a single line indicating the StAX implementation being used upon the - first time an XML parser is created. - - - Update methods on the server did not return a "content-location" header, but - only a "location" header. Both are required according to the FHIR specification. - Thanks to Bill de Beaubien of Systems Made Simple for reporting this! - - - Parser failed to correctly read contained Binary resources. Thanks to Alexander Kley for - the patch! - - - Calling encode multiple times on a resource with contained resources caused the contained - resources to be re-added (and the actual message to grow) with each encode pass. Thanks to - Alexander Kley for the test case! - - - JSON-encoded contained resources with the incorrect "_id" element (which should be "id", but some - incorrect examples exist on the FHIR specification) now parse correctly. In other words, HAPI - previously only accepted the correct "id" element, but now it also accepts the incorrect - "_id" element just to be more lenient. - - - Several unit tests failed on Windows (or any platform with non UTF-8 default encoding). This may - have also caused resource validation to fail occasionally on these platforms as well. - Thanks to Bill de Beaubien for reporting! - - - toString() method on TokenParam was incorrectly showing the system as the value. - Thanks to Bill de Beaubien for reporting! - - - Documentation on contained resources contained a typo and did not actually produce contained resources. Thanks - to David Hay of Orion Health for reporting! - - - Add a - Vagrant]]> - based environment (basically a fully built, self contained development environment) for - trying out the HAPI server modules. Thanks to Preston Lee for the pull request, and for - offering to maintain this! - - - Change validation API so that it uses a return type instead of exceptions to communicate - validation failures. Thanks to Joe Athman for the pull request! - - - Add a client interceptor which adds an HTTP cookie to each client request. Thanks to - Petro Mykhailysyn for the pull request! - - - - - - Add server interceptor framework, and new interceptor for logging incoming - requests. - - - Add server validation framework for validating resources against the FHIR schemas and schematrons - - - Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University - Health Network for reporting! - - - Create method was incorrectly returning an HTTP 204 on sucessful completion, but - should be returning an HTTP 200 per the FHIR specification. Thanks to wanghaisheng - for reporting! - - - FHIR Tester UI now correctly sends UTF-8 charset in responses so that message payloads containing - non US-ASCII characters will correctly display in the browser - - - JSON parser was incorrectly encoding extensions on composite elements outside the element itself - (as is done correctly for non-composite elements) instead of inside of them. Thanks to David Hay of - Orion for reporting this! - - - Contained/included resource instances received by a client are now automatically - added to any ResourceReferenceDt instancea in other resources which reference them. - - - Add documentation on how to use eBay CORS Filter to support Cross Origin Resource - Sharing (CORS) to server. CORS support that was built in to the server itself has - been removed, as it did not work correctly (and was reinventing a wheel that others - have done a great job inventing). Thanks to Peter Bernhardt of Relay Health for all the assistance - in testing this! - - - IResource interface did not expose the getLanguage/setLanguage methods from BaseResource, - so the resource language was difficult to access. - - - JSON Parser now gives a more friendly error message if it tries to parse JSON with invalid use - of single quotes - - - Transaction server method is now allowed to return an OperationOutcome in addition to the - incoming resources. The public test server now does this in order to return status information - about the transaction processing. - - - Update method in the server can now flag (via a field on the MethodOutcome object being returned) - that the result was actually a creation, and Create method can indicate that it was actually an - update. This has no effect other than to switch between the HTTP 200 and HTTP 201 status codes on the - response, but this may be useful in some circumstances. - - - Annotation client search methods with a specific resource type (e.g. List<Patient> search()) - won't return any resources that aren't of the correct type that are received in a response - bundle (generally these are referenced resources, so they are populated in the reference fields instead). - Thanks to Tahura Chaudhry of University Health Network for the unit test! - - - Added narrative generator template for OperationOutcome resource - - - Date/time types did not correctly parse values in the format "yyyymmdd" (although the FHIR-defined format - is "yyyy-mm-dd" anyhow, and this is correctly handled). Thanks to Jeffrey Ting of Systems Made Simple - for reporting! - - - Server search method for an unnamed query gets called if the client requests a named query - with the same parameter list. Thanks to Neal Acharya of University Health Network for reporting! - - - Category header (for tags) is correctly read in client for "read" operation - - - Transaction method in server can now have parameter type Bundle instead of - List<IResource> - - - HAPI parsers now use field access to get/set values instead of method accessors and mutators. - This should give a small performance boost. - - - JSON parser encodes resource references incorrectly, using the name "resource" instead - of the name "reference" for the actual reference. Thanks to - Ricky Nguyen for reporting and tracking down the issue! - - - Rename NotImpementedException to NotImplementedException (to correct typo) - - - Server setUseBrowserFriendlyContentType setting also respected for errors (e.g. OperationOutcome with 4xx/5xx status) - - - Fix performance issue in date/time datatypes where pattern matchers were not static - - - Server now gives a more helpful error message if a @Read method has a search parameter (which is invalid, but - previously lead to a very unhelpful error message). Thanks to Tahura Chaudhry of UHN for reporting! - - - Resource of type "List" failed to parse from a bundle correctly. Thanks to David Hay of Orion Health - for reporting! - - - QuantityParam correctly encodes approximate (~) prefix to values - - - If a server defines a method with parameter "_id", incoming search requests for that method may - get delegated to the wrong method. Thanks to Neal Acharya for reporting! - - - SecurityEvent.Object structural element has been renamed to - SecurityEvent.ObjectElement to avoid conflicting names with the - java Object class. Thanks to Laurie Macdougall-Sookraj of UHN for - reporting! - - - Text/narrative blocks that were created with a non-empty - namespace prefix (e.g. <xhtml:div xmlns:xhtml="...">...</xhtml:div>) - failed to encode correctly (prefix was missing in encoded resource) - - - Resource references previously encoded their children (display and reference) - in the wrong order so references with both would fail schema validation. - - - SecurityEvent resource's enums now use friendly enum names instead of the unfriendly - numeric code values. Thanks to Laurie MacDougall-Sookraj of UHN for the - suggestion! - - - - - HAPI has a number of RESTful method parameter types that have similar but not identical - purposes and confusing names. A cleanup has been undertaken to clean this up. - This means that a number of existing classes - have been deprocated in favour of new naming schemes. -
    ]]> - All annotation-based clients and all server search method parameters are now named - (type)Param, for example: StringParam, TokenParam, etc. -
    ]]> - All generic/fluent client method parameters are now named - (type)ClientParam, for example: StringClientParam, TokenClientParam, etc. -
    ]]> - All renamed classes have been retained and deprocated, so this change should not cause any issues - for existing applications but those applications should be refactored to use the - new parameters when possible. -
    - - Allow server methods to return wildcard generic types (e.g. List<? extends IResource>) - - - Search parameters are not properly escaped and unescaped. E.g. for a token parameter such as - "&identifier=system|codepart1\|codepart2" - - - Add support for OPTIONS verb (which returns the server conformance statement) - - - Add support for CORS headers in server - - - Bump SLF4j dependency to latest version (1.7.7) - - - Add interceptor framework for clients (annotation based and generic), and add interceptors - for configurable logging, capturing requests and responses, and HTTP basic auth. - - - Transaction client invocations with XML encoding were using the wrong content type ("application/xml+fhir" instead - of the correct "application/atom+xml"). Thanks to David Hay of Orion Health for surfacing this one! - - - Bundle entries now support a link type of "search". Thanks to David Hay for the suggestion! - - - If a client receives a non 2xx response (e.g. HTTP 500) and the response body is a text/plain message or - an OperationOutcome resource, include the message in the exception message so that it will be - more conveniently displayed in logs and other places. Thanks to Neal Acharya for the suggestion! - - - Read invocations in the client now process the "Content-Location" header and use it to - populate the ID of the returned resource. Thanks to Neal Acharya for the suggestion! - - - Fix issue where vread invocations on server incorrectly get routed to instance history method if one is - defined. Thanks to Neal Acharya from UHN for surfacing this one! - - - Binary reads on a server not include the Content-Disposition header, to prevent HTML in binary - blobs from being used for nefarious purposes. See - FHIR Tracker Bug 3298]]> - for more information. - - - Support has been added for using an HTTP proxy for outgoing requests. - - - Fix: Primitive extensions declared against custom resource types - are encoded even if they have no value. Thanks to David Hay of Orion for - reporting this! - - - Fix: RESTful server deployed to a location where the URL to access it contained a - space (e.g. a WAR file with a space in the name) failed to work correctly. - Thanks to David Hay of Orion for reporting this! - -
    - - - BREAKING CHANGE:]]>: IdDt has been modified so that it - contains a partial or complete resource identity. Previously it contained - only the simple alphanumeric id of the resource (the part at the end of the "read" URL for - that resource) but it can now contain a complete URL or even a partial URL (e.g. "Patient/123") - and can optionally contain a version (e.g. "Patient/123/_history/456"). New methods have - been added to this datatype which provide just the numeric portion. See the JavaDoc - for more information. - - - API CHANGE:]]>: Most elements in the HAPI FHIR model contain - a getId() and setId() method. This method is confusing because it is only actually used - for IDREF elements (which are rare) but its name makes it easy to confuse with more - important identifiers. For this reason, these methods have been deprocated and replaced with - get/setElementSpecificId() methods. The old methods will be removed at some point. Resource - types are unchanged and retain their get/setId methods. - - - Allow use of QuantityDt as a service parameter to support the "quantity" type. Previously - QuantityDt did not implement IQueryParameterType so it was not valid, and there was no way to - support quantity search parameters on the server (e.g. Observation.value-quantity) - - - Introduce StringParameter type which can be used as a RESTful operation search parameter - type. StringParameter allows ":exact" matches to be specified in clients, and handled in servers. - - - Parsers (XML/JSON) now support deleted entries in bundles - - - Transaction method now supported in servers - - - Support for Binary resources added (in servers, clients, parsers, etc.) - - - Support for Query resources fixed (in parser) - - - Nested contained resources (e.g. encoding a resource with a contained resource that itself contains a resource) - now parse and encode correctly, meaning that all contained resources are placed in the "contained" element - of the root resource, and the parser looks in the root resource for all container levels when stitching - contained resources back together. - - - Server methods with @Include parameter would sometimes fail when no _include was actually - specified in query strings. - - - Client requests for IdentifierDt types (such as Patient.identifier) did not create the correct - query string if the system is null. - - - Add support for paging responses from RESTful servers. - - - Don't fail on narrative blocks in JSON resources with only an XML declaration but no content (these are - produced by the Health Intersections server) - - - Server now automatically compresses responses if the client indicates support - - - Server failed to support optional parameters when type is String and :exact qualifier is used - - - Read method in client correctly populated resource ID in returned object - - - Support added for deleted-entry by/name, by/email, and comment from Tombstones spec - - - - - - - - - - + + + + James Agnew + HAPI FHIR Changelog + + + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Hibernate (JPA): 5.1.0 -> 5.2.7
  • +
  • Hibernate Search (JPA): 5.5.4 ->p; 5.7.0.CR1
  • +
  • Hibernate Validator (JPA): 5.2.4 ->p; 5.3.4
  • +
  • Spring (JPA): 4.3.1 -> 4.3.6
  • + + ]]> +
    + + The JPA server now supports custom search parameters in DSTU3 + mode. This allows users to create search parameters which contain + custom paths, or even override and disable existing search + parameters. + + + CLI example uploader couldn't find STU3 examples after CI server + was moved to build.fhir.org + + + Fix issue in JPA subscription module that prevented purging stale + subscriptions when many were present on Postgres + + + Server interceptor methods were being called twice unnecessarily + by the JPA server, and the DaoConfig interceptor registration + framework was not actually useful. Thanks to GitHub user + @mattiuusitalo for reporting! + + + AuthorizationInterceptor on JPA server did not correctly + apply rules on deleting resources in a specific compartment + because the resource metadata was stripped by the JPA server + before the interceptor could see it. Thanks to + Eeva Turkka for reporting! + + + JPA server exported CapabilityStatement includes + double entries for the _id parameter and uses the + wrong type (string instead of token). Thanks to + Robert Lichtenberger for reporting! + + + Custom resource types which extend Binary must not + have declared extensions since this is invalid in + FHIR (and HAPI would just ignore them anyhow). Thanks + to Thomas S Berg for reporting! + + + Standard HAPI zip/tar distributions did not include the project + sources and JavaDoc JARs. Thanks to Keith Boone for pointing + this out! + + + Server AuthorizationInterceptor always rejects history operation + at the type level even if rules should allow it. + + + JPA server terminology service was not correctly validating or expanding codes + in SNOMED CT or LOINC code systems. Thanks to David Hay for reporting! + + + Attempting to search for an invalid resource type (e.g. GET base/FooResource) should + return an HTTP 404 and not a 400, per the HTTP spec. Thanks to + GitHub user @CarthageKing for the pull request! + + + When parsing a Bundle containing placeholder fullUrls and references + (e.g. "urn:uuid:0000-0000") the resource reference targets did not get + populated with the given resources. Note that as a part of this + change, IdType and IdDt]]> have been modified + so that when parsing a placeholder ID, the complete placeholder including the + "urn:uuid:" or "urn:oid:" prefix will be placed into the ID part. Previously, + the prefix was treated as the base URL, which led to strange behaviour + like the placeholder being treated as a real IDs. Thanks to GitHub + user @jodue for reporting! + + + Declared extensions with multiple type() options listed in the @Child + annotation caused a crash on startup. Now this is supported. + + + STU3 XHTML parser for narrative choked if the narrative contained + an &rsquot;]]> entity string. + + + When parsing a quantity parameter on the server with a + value and units but no system (e.g. + GET [base]/Observation?value=5.4||mg]]>) + the unit was incorrectly treated as the system. Thanks to + @CarthageKing for the pull request! + + + Correct a typo in the JPA ValueSet ResourceProvider which prevented + successful operation under Spring 4.3. Thanks to + Robbert van Waveren for the pull request! + + + Deprecate the method + ICompositeElement#getAllPopulatedChildElementsOfType(Class)]]> + as it is no longer used by HAPI and is just an annoying step + in creating custom structures. Thanks to Allan Bro Hansen + for pointing this out. + + + CapturingInterceptor did not buffer the response meaning + that in many circumstances it did not actually capture + the response. Thanks to Jenny Syed of Cerner for + the pull request and contribution! + + + Clean up dependencies and remove Eclipse project files from git. Thanks to + @sekaijin for the pull request! + + + When performing a conditional create in a transaction in JPA server, + if a resource already existed matching the conditional expression, the + server did not change the version of the resource but did update the body + with the passed in body. Thanks to Artem Sopin for reporting and providing a test + case for this! + + + Client revincludes did not include the :recurse modifier. Thanks to + Jenny Meinsma for pointing this out on Zulip! + + + JPA server did not return an OperationOutcome in the response for + a normal delete operation. + + + Fix an issue in JPA server where _history results were kept in memory instead + of being spooled to the database as they should be. Note that as a part of this fix + a new method was added to + IBundleProvider called getUuid()]]>. This + method may return null]]> in any current cases. + + + Expanding a ValueSet in JPA server did not correctly apply + ?filter=]]> parameter when the ValueSet + being expanded had codes included explicitly (i.e. not by + is-a relationship). Thanks to David Hay for reporting! + + + JPA validator incorrectly returned an HTTP 400 instead of an HTTP 422 when + the resource ID was not present and required, or vice versa. Thanks to + Brian Postlethwaite for reporting! + +
    + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + + +
  • Derby (CLI): 10.12.1.1 -> 10.13.1.1
  • +
  • Jetty (CLI): 9.3.10.v20160621 -> 9.3.14.v20161028
  • +
  • JAnsi (CLI): 1.13 -> 1.14
  • +
  • Phloc Commons (SCH Validator): 4.4.5 -> 4.4.6
  • + + ]]> +
    + + Fix issue in AuthorizationIntetceptor where + transactions are blocked even when they + should not be + + + Fix regression in HAPI FHIR 2.1 JPA + server where some search parameters on + metadata resources did not appear + (e.g. "StructureDefinition.url"). Thanks + to David Hay for reporting! + + + Add ability to JPA server for disabling stale search + expiry. This is useful if you are deploying the server + to a cluster. + + + RestfulServer with no explicitly set FhirContext + fails to detect the presents of DSTU3 structures. Thanks + to GitHub user @vijayt27 for reporting! + + + As the + eBay CORS interceptor]]> + project + has gone dormant, we have introduced a new + HAPI server interceptor which can be used to implement CORS support + instead of using the previously recommended Servlet Filter. All server + examples as well as the CLI have been switched to use this new interceptor. + See the + CORS Documentation]]> + for more information. + + + Make the parser configurable so that when + parsing an invalid empty value (e.g. + {"status":""}]]>) the + parser will either throw a meaningful exception + or log a warning depending on the configured + error handler. + + + Fix issue when serializing resources that have + contained resources which are referred to + from multiple places. Sometimes when serializing + these resources the contained resource section + would contain duplicates. Thanks to Hugo Soares + and Stefan Evinance for reporting and providing + a test case! + + + Allow client to gracefully handle running in DSTU3 mode + but with a structures JAR that does not contain a + CapabilityStatement resource. Thanks to Michael Lawley + for the pull request! + + + Fix a crash in JPA server when searching using an _include if _include targets are + external references (and therefore can't be loaded + by the server). Thanks to Hannes Ulrich for reporting! + + + HAPI FHIR CLI failed to delete a file when uploading + example resources while running under Windows. + + + Server should reject update if the resource body + does not contain an ID, or the ID does not match + the request URL. Thanks to Jim Steel for reporting! + + + Web Testing UI's next and previous buttons for paging + through paged results did not work after the migration + to using Thymeleaf 3. Thanks to GitHub user @gsureshkumar + for reporting! + + + When parsing invalid enum values in STU3, + report errors through the parserErrorHandler, + not by throwing an exception. Thanks to + Michael Lawley for the pull request! + + + When parsing DSTU3 resources with enumerated + types that contain invalid values, the parser will now + invoke the parserErrorHandler. For example, when parsing + {"resourceType":"Patient", "gender":"foo"} + ]]> + the previous behaviour was to throw an InvalidArgumentException. + Now, the parserErrorHandler is invoked. In addition, thw + LenientErrorHandler has been modified so that this one case + will result in a DataFormatException. This has the effect + that servers which receive an invalid enum velue will return + an HTTP 400 instead of an HTTP 500. Thanks to Jim + Steel for reporting! + + + DSTU3 context now pulls the FHIR version from the actual + model classes. Thanks to Michael Lawley for the pull request! + + + Enhancements to the tinder-plugin's generic template features + of the generate-multi-files and generate-single-file + Maven goals as well as the Ant hapi-tinder task. +
      +
    • Provides the full Tinder data model by adding composites, valuesets, and profiles to resourcesw.
    • +
    • Supports generating files for resources, composites, valuesets, and profiles
    • +
    • Supports Velocimacro files outside the tinder-plugin JAR
    • +
    • Provides filename prefix as well as suffix properties
    • +
    • Can specify any of the Velocity configuration parameters such as + macro.provide.scope.control which allows safe macro recursion
    • +
    • Templates can now drill down into the referenced children for a ResourceBlockCopy
    • +
    • Normalization of properties across all three generic tasks
    • +
    + ]]> +
    + + Fix ordering of validator property handling when an element + has a name that is similar to a shorter name[x] style name. + Thanks to CarthageKing for the pull request! + + + Add a docker configuration to the hapi-fhir-jpaservr-example + module. Thanks to Gijsbert van den Brink for the pull request! + + + Add utility constructors to MoneyDt. Thanks to James Ren for the + contribution! + + + AuthorizationInterceptor was failing to allow read requests to pass + when a rule authorized those resources by compartment. Thanks to + GitHub user @mattiuusitalo for reporting and supplying + a test case! + + + Correct a typo in client + IHttpRequest]]> class: "bufferEntitity" should be "bufferEntity". + + + ErrorHandler is now called (resulting in a warning by default, but can also be an exception) when arsing JSON if + the resource ID is not a JSON string, or an object is found where an array is expected (e.g. repeating field). Thanks + to Jenni Syed of Cerner for providing a test case! + + + Fix Web Testing UI to be able to handle STU3 servers which + return CapabilityStatement instead of the previously used + "Conformance" resource + + + CLI example uploader couldn't find STU3 examples after CI server + was moved to build.fhir.org + + + Fix issue in JPA subscription module that prevented purging stale + subscriptions when many were present on Postgres + + + Server interceptor methods were being called twice unnecessarily + by the JPA server, and the DaoConfig interceptor registration + framework was not actually useful. Thanks to GitHub user + @mattiuusitalo for reporting! + + + AuthorizationInterceptor on JPA server did not correctly + apply rules on deleting resources in a specific compartment + because the resource metadata was stripped by the JPA server + before the interceptor could see it. Thanks to + Eeva Turkka for reporting! + + + JPA server exported CapabilityStatement includes + double entries for the _id parameter and uses the + wrong type (string instead of token). Thanks to + Robert Lichtenberger for reporting! + + + Custom resource types which extend Binary must not + have declared extensions since this is invalid in + FHIR (and HAPI would just ignore them anyhow). Thanks + to Thomas S Berg for reporting! + + + Standard HAPI zip/tar distributions did not include the project + sources and JavaDoc JARs. Thanks to Keith Boone for pointing + this out! + + + Server AuthorizationInterceptor always rejects history operation + at the type level even if rules should allow it. + + + JPA server terminology service was not correctly validating or expanding codes + in SNOMED CT or LOINC code systems. Thanks to David Hay for reporting! + + + Attempting to search for an invalid resource type (e.g. GET base/FooResource) should + return an HTTP 404 and not a 400, per the HTTP spec. Thanks to + GitHub user @CarthageKing for the pull request! + + + When parsing a Bundle containing placeholder fullUrls and references + (e.g. "urn:uuid:0000-0000") the resource reference targets did not get + populated with the given resources. Note that as a part of this + change, IdType and IdDt]]> have been modified + so that when parsing a placeholder ID, the complete placeholder including the + "urn:uuid:" or "urn:oid:" prefix will be placed into the ID part. Previously, + the prefix was treated as the base URL, which led to strange behaviour + like the placeholder being treated as a real IDs. Thanks to GitHub + user @jodue for reporting! + + + Declared extensions with multiple type() options listed in the @Child + annotation caused a crash on startup. Now this is supported. + + + STU3 XHTML parser for narrative choked if the narrative contained + an &rsquot;]]> entity string. + + + When parsing a quantity parameter on the server with a + value and units but no system (e.g. + GET [base]/Observation?value=5.4||mg]]>) + the unit was incorrectly treated as the system. Thanks to + @CarthageKing for the pull request! + + + Correct a typo in the JPA ValueSet ResourceProvider which prevented + successful operation under Spring 4.3. Thanks to + Robbert van Waveren for the pull request! + + + Deprecate the method + ICompositeElement#getAllPopulatedChildElementsOfType(Class)]]> + as it is no longer used by HAPI and is just an annoying step + in creating custom structures. Thanks to Allan Bro Hansen + for pointing this out. + + + CapturingInterceptor did not buffer the response meaning + that in many circumstances it did not actually capture + the response. Thanks to Jenny Syed of Cerner for + the pull request and contribution! + +
    + + + STU3 structure definitions have been updated to the + STU3 latest definitions (1.7.0 - SVN 10129). In + particular, this version supports the new CapabilityStatement + resource which replaces the previous Conformance + resource (in order to reduce upgrade pain, both resource + types are included in this version of HAPI) + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • spring-data-orm (JPA): 1.10.2 -> 1.10.4
  • + + ]]> +
    + + Fix a fairly significant issue in JPA Server when using the DatabaseBackedPagingProvider]]>: When paging over the results + of a search / $everything operation, under certain circumstances resources may be missing from the last page of results + that is returned. Thanks to David Hay for reporting! + + + Client, Server, and JPA server now support experimental support + for + + using the XML Patch and JSON Patch syntax as explored during the + September 2016 Baltimore Connectathon. See + this wiki page]]> + for a description of the syntax. + ]]> + Thanks to Pater Girard for all of his help during the connectathon + in implementing this feature! + + + Android library now uses OkHttp client by default instead + of Apache HttpClient. This should lead to much simpler + support for Android in the future. + + + Both client and server now use the new STU3 mime types by default + if running in STU3 mode (in other words, using an STU3 + FhirContext). + + + In server, when returning a list of resources, the server sometimes failed to add + _include]]> resources to the response bundle if they were + referred to by a contained reosurce. Thanks to Neal Acharya for reporting! + + + Fix regression in web testing UI where "prev" and "next" buttons don't work + when showing a result bundle + + + JPA server should not attempt to resolve built-in FHIR StructureDefinitions from the + database (this causes a significant performance hit when validating) + + + BanUnsupportedHttpMethodsInterceptor was erroring out when a client + attempts HTTP HEAD requests + + + Conditional URLs in JPA server (e.g. for delete or update) did not support the + _has]]> parameter + + + Remove Maven dependency on Saxon library, as it is not actually used. Thanks + to Lem Edmondson for the suggestion! + + + Times before 1970 with fractional milliseconds were parsed incorrectly. Thanks + to GitHub user @CarthageKing for reporting! + + + Prevent crash in parser when parsing resource + with multiple profile declarations when + default type for profile is used. Thanks to + Filip Domazet for the pull request! + + + STU3 servers were adding the old MimeType + strings to the + Conformance.format]]> + part of the generated server conformance + statement + + + When performing an update using the client on a resource that + contains other resources (e.g. Bundle update), all child resources in the + parent bundle were incorrectly given the ID of the parent. Thanks + to Filip Domazet for reporting! + + + STU clients now use an Accept header which + indicates support for both the old MimeTypes + (e.g. application/xml+fhir]]>) + and the new MimeTypes + (e.g. application/fhir+xml]]>) + + + JPA server now sends correct + HTTP 409 Version Conflict]]> + when a + DELETE fails because of constraint issues, instead of + HTTP 400 Invalid Request]]> + + + Server history operation did not populate the Bundle.entry.request.url + field, which is required in order for the bundle to pass validation. + Thanks to Richard Ettema for spotting this! + + + Add a new method to the server interceptor framework which will be + called after all other processing is complete (useful for performance + tracking). The server LoggingInterceptor has been switched to using this + method which means that log lines will be created when processing is finished, + instead of when it started. + + + STU3 clients were not sending the new mimetype values in the + Content-Type]]> header. Thanks to + Claude Nanjo for pointing this out! + + + JAX-RS server was not able to handle the new mime types defined + in STU3 + + + JPA server did not handle custom types when being called + programatically (I.e. not through HTTP interface). Thanks to + Anthony Mei for pointing this out! + + + CLI was not correctly able to upload DSTU2 examples to any server + + + STU3 validator has been upgrated to include fixes made since the + 1.6.0 ballot + + + Prevent JPA server from creating a bunch of + FhirContext objects for versions of FHIR that + aren't actually being used + + + XhtmlNode.equalsDeep() contained a bug which caused resources + containing a narrative to always return + false]]> for STU3 + Resource#equalsDeep()]]>. Thanks to + GitHub user @XcrigX for reporting! + + + JPA server did not correctly process searches for chained parameters + where the chain passed across a field that was a choice between a + reference and a non-reference type (e.g. + MedicationAdministration.medication[x]]]>. + Thanks to GitHub user @Crudelus for reporting! + + + Handle parsing an extension without a URL more gracefully. In HAPI FHIR 2.0 this caused + a NullPointerException to be thrown. Now it will trigger a warning, or throw a + DataFormatException if the StrictErrorHandler is configured on the parser. + + + Calling a HAPI server URL with a chain on a parameter that shouldn't accept + chains (e.g. + GET [base]/Patient?name.foo=smith]]>) + did not return an error and instead just ignored the chained part + and treated the parameter as though it did not have the chain. This + led to confusing and potentially unsafe behaviour. This has been + corrected to return an error to the client. Thanks to + Kevin Tallevi for finding this! + + + Fix #411 - Searching by POST [base]/_search]]> with urlencoded parameters doesn't work correctly if + interceptors are accessing the parameters and there is are also + parameters on the URL. Thanks to Jim Steel for reporting! + + + Fluent client can now return types other than Parameters + when invoking operations. + + + JPA server shouldn't report a totalCount in Bundle of "-1" when + there are no results + + + JPA server was not correctly normalizing strings with non-latin characters + (e.g. Chinese chars). Thanks to GitHub user @YinAqu for reporting and providing + some great analysis of the issue! + + + Add a new method to ReferenceClientParam which allows you to + pass in a number of IDs by a collection of Strings. Thanks to + Thomas Andersen for the pul request! + + + When encoding a resource in JSON where the resource has + an extension with a value where the value is a reference to a + contained resource, the reference value (e.g. "#1") did not + get serialized. Thanks to GitHub user @fw060 for reporting! + + + ResponseHighlighterInterceptor now pretty-prints responses + by default unless the user has explicitly requested + a non-pretty-printed response (ie. + using ?_pretty=false]]>. Thanks to + Allan Brohansen and Jens Villadsen for the suggestion! + + + Add a new JSON library abstraction layer to the JSON parser. + This contribution shouldn't have any end-user impact but does + make it easier to use the JSON parser to generate custom structures + for other purposes, and should allow us to support RDF more + easily at some point. Thanks to Bill Denton for the pull + request and the contribution! + + + DSTU1 Bundle encoder did not include the Bundle entry author in + the generated bundle. Thanks to Hannes Venter for the pull + request and contribution! + + + Remove unused field (myIsContained) from ResourceTable + in JPA server. + + + AuthorizationInterceptor is now a bit more aggressive + at blocking read operations, stopping them on the + way in if there is no way they will be accepted + to the resource check on the way out. In addition + it can now be configured to allow/deny operation + invocations at the instance level on any + instance of a given type + + + STU3 servers were incorrectly returning the + Content-Location]]> + header instead of the + Content]]> + header. The former has been removed from the + FHIR specification in STU3, but the + latter got removed in HAPI's code base. + Thanks to Jim Steel for reporting! + + + Correct several documentation issues. Thanks to Vadim Peretokin + for the pull requests! + + + Remove an unneccesary database flush + from JPA persistence operations + + + Add method to fluent client to allow OR search across several + profiles. Thanks to Thomas Andersen for the pull request! + +
    + + + JSON parsing in HAPI FHIR has been switched from using JSR353 (javax.json) to + using Google Gson. For this reason we are bumping the major release number to + 2.0. Theoretically this should not affect projects in any major way, but Gson + does have subtle differences. Two differences which popped up a fair bit in + our own testing: + +
      + A space is placed after the : in keys, e.g. what was previously + encoded as "resourceType":"Patient" is now encoded + as "resourceType": "Patient" (this broke a number of + our unit tests with hardcoded resource definitions) +
    +
      + Trailing content after a valid json resource is rejected by + Gson (it was ignored by the Glassfish parser we were previously + using even though it was invalid) +
    + + ]]> +
    + + STU3 structure definitions have been updated to the + STU3 ballot candidate versions (1.6.0 - SVN 9663) + + + Both client and server now support the new Content Types decided in + FHIR #10199]]>. +
    ]]> + This means that the server now supports + application/fhir+xml and application/fhir+json]]> + in addition to the older style + application/xml+fhir and application/json+fhir]]>. + In order to facilitate migration by implementors, the old style remains the default + for now, but the server will respond using the new style if the request contains it. The + client now uses an Accept]]> header value which requests both + styles with a preference given to the new style when running in DSTU3 mode. +
    ]]> + As a part of this change, the server has also been enhanced so that if a request + contains a Content-Type header but no Accept header, the response will prefer the + encoding specified by the Content-Type header. +
    + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Logback (used in sample projects): 1.1.5 -> 1.1.7
  • +
  • Phloc Commons (used by schematron validator): 4.4.4 -> 4.4.5
  • +
  • Commons-IO: 2.4 -> 2.5
  • +
  • Apache HTTPClient: 4.5.1 -> 4.5.2
  • +
  • Apache HTTPCore: 4.4.4 -> 4.4.5
  • +
  • Jersey (JAX-RS tests): 2.22.2 -> 2.23.1
  • +
  • Spring (JPA, Web Tester): 4.3.0 -> 4.3.1
  • + +
  • Hibernate Search (JPA): 5.5.2 -> 5.5.4
  • +
  • Thymeleaf (Narrative Generator / Web Tester): 2.1.4 ->3.0.1
  • + + ]]> +
    + + + Fix issue in DSTU1 Bundle parsing where unexpected elements in the bundle resulted in a failure + to parse. + + + DSTU2 QuestionnaireResponse validator failed with an exception if the + QuestionnaireResponse contained certain groups with no content + + + Fluent client should ignore parameter values which are null instead of including + them as ?foo=null]]> + + + When using _elements]]> parameter on server, the server was not + automatically adding the SUBSETTED]]> tag as it should + + + JPA server should now automatically detect + if Hibernate Search (Lucene) is configured to be + disabled and will not attempt to use it. This + prevents a crash for some operations. + + + A new server interceptor "BanUnsupprtedHttpMethodsInterceptor" has been added + which causes the server to return an HTTP 405 if an unsupported HTTP + verb is received from the client + + + Fix an issue where resource IDs were not correctly set when using + DSTU2 HL7org structures with the JAX-RS module. Thanks to Carlo Mion + for the pull request! + + + hapi-fhir-testpage-overlay project contained an unneccesary + dependency on hapi-fhir-jpaserver-base module, which resulted in + projects using the overlay having a large number of unnneded + JARs included + + + It is not possible to configure both the parser and the context to + preserve versions in resource references (default behaviour is to + strip versions from references). Thanks to GitHub user @cknaap + for the suggestion! + + + Tag#setCode(String)]]> did not actually set the code it was supposed to + set. Thanks to Tim Tschampel for reporting! + + + JPA server's /Bundle]]> endpoint cleared + the Bundle.entry.fullUrl]]> field on stored + bundles, resulting in invalid content being saved. Thanks to Mirjam + Baltus for reporting! + + + JPA server now returns HTTP 200 instead of HTTP 404 for + conditional deletes which did not find any matches, + per FHIR-I decision. + + + Client that declares explicitly that it is searching/reading/etc for + a custom type did not automatically parse into that type. + + + Allow servers to specify the authentication realm of their choosing when + throwing an AuthenticationException. Thanks to GitHub user @allanbrohansen + for the suggestion! + + + Add a new client implementation which uses the + OkHttp]]> + library as the HTTP client implementation (instead of Apache HttpClient). + This is particularly useful for Android (where HttpClient is a pain) but + could also be useful in other places too. + Thanks to Matt Clarke of Orion Health for the contribution! + + + Fix a regression when parsing resources that have contained + resources, where the reference in the outer resource which + links to the contained resource sometimes did does not get + populated with the actual target resource instance. Thanks to + Neal Acharya for reporting! + + + hapi-fhir-cli upload-terminology command now has an argument + "-b FOO" that lets you add an authorization header in the form + Authorization: Bearer FOO]]> + + + Parser failed to successfully encode a custom resource + if it contained custom fields that also used custom + types. Thanks to GitHub user @sjanic for reporting! + + + Inprove handling of _text and _content searches in JPA server to do better + matching on partial strings + + + Servers in STU3 mode will now ignore any ID or VersionID found in the + resource body provided by the client when processing FHIR + update]]> operations. This change has been made + because the FHIR specification now requires servers to ignore + these values. Note that as a result of this change, resources passed + to @Update]]> methods will always have + null]]> ID + + + Add new methods to + AuthorizationInterceptor]]> + which allow user code to declare support for conditional + create, update, and delete. + + + When encoding a resource with a reference to another resource + that has a placeholder ID (e.g. urn:uuid:foo), the urn prefix + was incorrectly stripped from the reference. + + + Servers for STU3 (or newer) will no longer include a + Location:]]> header on responses for + read]]> operations. This header was + required in earlier versions of FHIR but has been removed + from the specification. + + + Fix NullPointerException when encoding an extension containing CodeableConcept + with log level set to TRACE. Thanks to Bill Denton for the report! + + + Add two new methods to the parser error handler that let users trap + invalid contained resources with no ID, as well as references to contained + resource that do not exist. + + + Improve performance when parsing resources containing contained resources + by eliminating a step where references were woven twice + + + Parser failed to parse resources containing an extension with a value type of + "id". Thanks to Raphael Mäder for reporting! + + + When committing a transaction in JPA server + where the transaction contained placeholder IDs + for references between bundles, the placeholder + IDs were not substituted with viewing + resources using the _history operation + + + HAPI root pom shouldn't include animal-sniffer plugin, + since that causes any projects which extend this to + be held to Java 6 compliance. + +
    + + + Performance has been improved for the initial FhirContext + object creation by avoiding a lot of unnecessary reflection. HAPI FHIR + 1.5 had a regression compared to previous releases + and this has been corrected, but other improvements have been + made so that this release is faster than previous releases too. +
    ]]> + In addition, a new "deferred scan" mode has been implemented for + even faster initialization on slower environments (e.g. Android). + See the performance documentation]]> + for more information. +
    ]]> + The following shows our benchmarks for context initialization across several + versions of HAPI: + +
  • Version 1.4: 560ms
  • +
  • Version 1.5: 800ms
  • +
  • Version 1.6: 340ms
  • +
  • Version 1.6 (deferred mode): 240ms
  • + + ]]> +
    + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Spring (JPA, Web Tester): 4.2.5 -> 4.3.0
  • +
  • Spring-Data (JPA): 1.9.2 -> 1.10.1
  • + +
  • Hibernate Search (JPA): 5.5.2 -> 5.5.3
  • +
  • Jetty (CLI): 9.3.9 -> 9.3.10
  • + + ]]> +
    + + Remove some clases that were deprecated over a year ago and have + suitable replacements: + +
  • QualifiedDateParam has been removed, but DateParam may be used instead
  • +
  • PathSpecification has been removedm but Include may be used instead
  • + + ]]> +
    + + ResponseValidatingInterceptor threw an InternalErrorException (HTTP 500) for operations + that do not return any content (e.g. delete). Thanks to Mohammad Jafari for reporting! + + + REST server now throws an HTTP 400 instead of an HTTP 500 if an operation which takes + a FHIR resource in the request body (e.g. create, update) contains invalid content that + the parser is unable to parse. Thanks to Jim Steel for the suggestion! + + + Deprecate fluent client search operations without an explicit declaration of the + bundle type being used. This also means that in a client + .search()]]> + operation, the + .returnBundle(Bundle.class)]]> + needs to be the last statement before + .execute()]]> + + + Server now respects the parameter _format=application/xml+fhir"]]> + which is technically invalid since the + should be escaped, but is likely to be used. Also, + a parameter of _format=html]]> can now be used, which + forces SyntaxHighlightingInterceptor to use HTML even + if the headers wouldn't otherwise trigger it. + Thanks to Jim Steel for reporting! + + + Improve performance when parsing large bundles by fixing a loop over all of the + entries inthe bundle to stitch together cross-references, which was happening once + per entry instead of once overall. Thanks to Erick on the HAPI FHIR Google Group for + noticing that this was an issue! + + + JSON parser no longer allows the resource ID to be specified in an element called "_id" + (the correct one is "id"). Previously _id was allowed because some early FHIR examples + used that form, but this was never actually valid so it is now being removed. + + + JPA server now allows "forced IDs" (ids containing non-numeric, client assigned IDs) + to use the same logical ID part on different resource types. E.g. A server may now have + both Patient/foo and Obervation/foo on the same server.
    ]]> + Note that existing databases will need to modify index "IDX_FORCEDID" as + it is no longer unique, and perform a reindexing pass. +
    + + When serializing/encoding custom types which replace exsting choice fields by + fixing the choice to a single type, the parser would forget that the + field was a choice and would use the wrong name (e.g. "abatement" instead of + "abatementDateType"). Thanks to Yaroslav Kovbas for reporting and + providing a unit test! + + + JPA server transactions sometimes created an incorrect resource reference + if a resource being saved contained references that had a display value but + not an actual reference. Thanks to David Hay for reporting! + + + When performing a REST Client create or update with + Prefer: return=representation]]> set, + if the server does not honour the Prefer header, the client + will automatically fetch the resource before returning. Thanks + to Ewout Kramer for the idea! + + + DSTU3 structures now have + setFoo(List)]]> + and + setGetFooFirstRep()]]> + methods, bringing them back to parity with the HAPI + DSTU2 structures. Thanks to Rahul Somasunderam and + Claude Nanjo for the suggestions! + + + JPA server has now been refactored to use the + new FluentPath search parameter definitions + for DSTU3 resources. + + + RequestValidatingInterceptor and ResponseValidatingInterceptor + both have new method setIgnoreValidatorExceptions]]> + which causes validator exceptions to be ignored, rather than causing + processing to be aborted. + + + LoggingInterceptor on server has a new parameter + ${requestBodyFhir}]]> which logs the entire request body. + + + JAX-RS server module now supports DSTU3 resources (previously it only supported DSTU2). Thanks + to Phillip Warner for implementing this, and providing a pull request! + + + Generated conformance statements for DSTU3 servers did not properly reference their + OperationDefinitions. Thanks + to Phillip Warner for implementing this, and providing a pull request! + + + Properly handle null arrays when parsing JSON resources. Thanks to Subhro for + fixing this and providing a pull request! + + + STU3 validator failed to validate codes where the + code was a child code within the code system that contained it + (i.e. not a top level code). Thanks to Jon + Zammit for reporting! + + + Restore the setType method in the DSTU1 Bundle + class, as it was accidentally commented out. Thanks + to GitHub user @Virdulys for the pull request! + + + JPA server now supports composite search parameters + where the type of the composite parameter is + a quantity (e.g. Observation:component-code-component-value-quantity) + + + Remove the Remittance resource from DSTU2 + structures, as it is not a real resource and + was causing issues with interoperability + with the .NET client. + + + CLI tool cache feature (-c) for upload-example task sometimes failed + to write cache file and exited with an exception. + + + Fix error message in web testing UI when loading pages in a search + result for STU3 endpoints. + + + When encoding JSON resource, the parser will now always + ensure that XHTML narrative content has an + XHTML namespace declaration on the first + DIV tag. This was preventing validation for + some resources using the official validator + rules. + + + Server failed to invoke operations when the name + was escaped (%24execute instead of $execute). + Thanks to Michael Lawley for reporting! + + + JPA server transactions containing a bundle that has multiple entries + trying to delete the same resource caused a 500 internal error + + + JPA module failed to index search parameters that mapped to a Timing datatype, + e.g. CarePlan:activitydate + + + Add a new option to the CLI run-server command called --lowmem]]>. + This option disables some features (e.g. fulltext search) in order to allow the + server to start in memory-constrained environments (e.g Raspberry Pi) + + + When updating a resource via an update operation on the server, if the ID of the + resource is not present in the resource body but is present on the URL, this will + now be treated as a warning instead of as a failure in order to be a bit more + tolerant of errors. If the ID is present in the body but does not agree with the + ID in the URL this remains an error. + + + Server / JPA server date range search params (e.g. Encounter:date) now treat + a single date with no comparator (or the eq comparator) as requiring that the + value be completely contained by the range specified. Thanks to Chris Moesel + for the suggestion. + + + In server, if a parameter was annotated with the annotation, the + count would not appear in the self/prev/next links and would not actually be applied + to the search results by the server. Thanks to Jim Steele for letting us know! + + + Conditional update on server failed to process if the conditional URL did not have any + search parameters that did not start with an underscore. E.g. "Patient?_id=1" failed + even though this is a valid conditional reference. + + + JPA server can now be configured to allow external references (i.e. references that + point to resources on other servers). See + JPA Documentation]]> for information on + how to use this. Thanks to Naminder Soorma for the suggestion! + + + When posting a resource to a server that contains an invalid value in a boolean field + (e.g. Patient with an active value of "1") the server should return an HTTP 400, not + an HTTP 500. Thanks to Jim Steel for reporting! + + + Enable parsers to parse and serialize custom resources that contain custom datatypes. + An example has been added which shows how to do this + here]]> + + + JSON parser was incorrectly encoding resource language attribute in JSON as an + array instead of a string. Thanks to David Hay for reporting! + + + Sébastien Rivière contributed an excellent pull request which adds a + number of enhancements to JAX-RS module: + +
  • Enable the conditional update and delete
  • +
  • Creation of a bundle provider, and support of the @Transaction
  • +
  • Bug fix on the exceptions handling as some exceptions throw outside bean context were not intercept.
  • +
  • Add the possibility to have the stacktrace in the jaxrsException
  • + + ]]> +
    + + FhirTerser.cloneInto method failed to clone correctly if the source + had any extensions. Thanks to GitHub user @Virdulys for submitting and + providing a test case! + + + Update DSTU2 InstanceValidator to latest version from upstream + + + Web Testing UI was not able to correctly post an STU3 transaction + + + DateTime parser incorrectly parsed times where more than 3 digits of + precision were provided on the seconds after the decimal point + + + Improve error messages when the $validate operation is called but no resource + is actually supplied to validate + + + DSTU2+ servers no longer return the Category header, as this has been + removed from the FHIR specification (and tags are now available in the + resource body so the header was duplication/wasted bandwidth) + + + Create and Update operations in server did not + include ETag or Last-Modified headers even though + the spec says they should. Thanks to Jim Steel for + reporting! + + + Update STU3 client and server to use the new sort parameter style (param1,-param2,param). Thanks to GitHub user @euz1e4r for + reporting! + + + QuantityClientParam#withUnit(String) put the unit into the system part of the + parameter value + + + Fluent client searches with date parameters were not correctly using + new prefix style (e.g. gt) instead of old one (e.g. >) + + + Some built-in v3 code systems for STU3 resources were missing + certain codes, which caused false failures when validating + resources. Thanks to GitHub user @Xoude for reporting! + + + Some methods on DSTU2 model structures have JavaDocs that + incorrectly claim that the method will not return null when + in fact it can. Thanks to Rick Riemer for reporting! + + + ResponseHighlightingInterceptor has been modified based on consensus + on Zulip with Grahame that requests that have a parameter of + _format=json]]> or + _format=xml]]> will output raw FHIR content + instead of HTML highlighting the content as they previously did. + HTML content can now be forced via the (previously existing) + _format=html]]> or via the two newly added + values + _format=html/json]]> and + _format=html/xml]]>. Because of this + change, the custom + _raw=true]]> mode has been deprecated and + will be removed at some point. + + + Operation definitions (e.g. for $everything operation) in the generated + server conformance statement should not include the $ prefix in the operation + name or code. Thanks to Dion McMurtrie for reporting! + + + Server generated OperationDefinition resources did not validate + due to some missing elements (kind, status, etc.). + Thanks to + Michael Lawley for reporting! + + + Operations that are defined on multiple resource provider types with + the same name (e.g. "$everything") are now automatically exposed by the server + as separate OperationDefinition resources per resource type. Thanks to + Michael Lawley for reporting! + + + OperationDefinition resources generated automatically by the server for operations + that are defined within resource/plain providers incorrectly stated that + the maximum cardinality was "*" for non-collection types with no explicit + maximum stated, which is not the behaviour that the JavaDoc on the + annotation describes. Thanks to Michael Lawley + for reporting! + + + Server parameters annotated with + @Since]]> + or + @Count]]> + which are of a FHIR type such as IntegerDt or DateTimeType will + now be set to null if the client's URL does not + contain this parameter. Previously they would be populated + with an empty instance of the FHIR type, which was inconsistent with + the way other server parameters worked. + + + Server now supports the _at parameter (including multiple repetitions) + for history operation + + + + AuthorizationInterceptor can now allow or deny requests to extended + operations (e.g. $everything) + + + DecimalType used BigDecimal constructor instead of valueOf method to + create a BigDecimal from a double, resulting in weird floating point + conversions. Thanks to Craig McClendon for reporting! + + + Remove the depdendency on a method from commons-lang3 3.3 which was + causing issues on some Android phones which come with an older version + of this library bundled. Thanks to Paolo Perliti for reporting! + + + Parser is now better able to handle encoding fields which have been + populated with a class that extends the expected class + + + When declaring a child with + order=Child.REPLACE_PARENT]]> + the serialized form still put the element at the + end of the resource instead of in the correct + order + + + Fix STU3 JPA resource providers to allow validate operation + at instance level + +
    + + + Security Fix: XML parser was vulnerable to XXE (XML External Entity) + processing, which could result in local files on disk being disclosed. + See this page]]> + for more information. + Thanks to Jim Steel for reporting! + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Hibernate (JPA, Web Tester): 5.0.7 -> 5.1.0
  • +
  • Spring (JPA, Web Tester): 4.2.4 -> 4.2.5
  • +
  • SLF4j (All): 1.7.14 -> 1.7.21
  • + + ]]> +
    + + Support comments when parsing and encoding both JSON and XML. Comments are retrieved + and added to the newly created methods + IBase#getFormatCommentsPre() and + IBase#getFormatCommentsPost() + + + Added options to the CLI upload-examples command which allow it to cache + the downloaded content file, or use an arbitrary one. Thanks to Adam Carbone + for the pull request! + + + REST search parameters with a prefix/comparator had not been updated to use + the DSTU2 style prefixes (gt2011-01-10) instead of the DSTU1 style prefixes + (>2011-01-01). The client has been updated so that it uses the new prefixes + if the client has a DSTU2+ context. The server has been updated so that it now + supports both styles. +
    ]]> + As a part of this change, a new enum called + ParamPrefixEnum]]> + has been introduced. This enum replaces the old + QuantityCompararatorEnum]]> + which has a typo in its name and can not represent several new prefixes added since + DSTU1. +
    + + JPA server number and quantity search params now follow the rules for the + use of precision in search terms outlined in the + search page]]> of the + FHIR specification. For example, previously a 1% tolerance was applied for + all searches (10% for approximate search). Now, a tolerance which respects the + precision of the search term is used (but still 10% for approximate search). + + + Fix a failure starting the REST server if a method returns an untyped List, which + among other things prevented resource provider added to the server + as CDI beans in a JBoss enviroment. Thanks to GitHub user fw060 (Fei) for + reporting and figuring out exactly why this wasn't working! + + + JPA server now supports :above and :below qualifiers on URI search params + + + Add optional support (disabled by default for now) to JPA server to support + inline references containing search URLs. These URLs will be resolved when + a resource is being created/updated and replaced with the single matching + resource. This is being used as a part of the May 2016 Connectathon for + a testing scenario. + + + The server no longer adds a + WWW-Authenticate]]> + header to the response if any resource provider code throws an + AuthenticationException]]>. This header is + used for interactive authentication, which isn't generally + appropriate for FHIR. We added code to add this header a long time + ago for testing purposes and it never got removed. Please let us + know if you need the ability to add this header automatically. Thanks + to Lars Kristian Roland for pointing this out. + + + In the client, the create/update operations on a Binary resource + (which use the raw binary's content type as opposed to the FHIR + content type) were not including any request headers (Content-Type, + User-Agent, etc.) Thanks to Peter Van Houte of Agfa Healthcare for + reporting! + + + Handling of Binary resources containing embedded FHIR resources for + create/update/etc operations has been corrected per the FHIR rules + outlined at + Binary Resource]]> + in both the client and server. +
    ]]> + Essentially, if the Binary contains something + that isn't FHIR (e.g. an image with an image content-type) the + client will send the raw data with the image content type to the server. The + server will place the content type and raw data into a Binary resource instance + and pass those to the resource provider. This part was already correct previous + to 1.5. +
    ]]> + On the other hand, if the Binary contains a FHIR content type, the Binary + is now sent by the client to the server as a Binary resource with a FHIR content-type, + and the embedded FHIR content is contained in the appropriate fields. The server + will pass this "outer" Binary resource to the resource provider code. +
    + + The RequestDetails and ActionRequestDetails objects which are passed to + server interceptor methods and may also be used as server provider method + arguments now has a new method + Map<String, String> getUserData() + ]]> + which can be used to pass data and objects between interceptor methods to + to providers. This can be useful, for instance, if an authorization + interceptor wants to pass the logged in user's details to other parts + of the server. + + + IServerInterceptor#incomingRequestPreHandled() is called + for a @Validate method, the resource was not populated in the + ActionRequestDetails argument. Thanks to Ravi Kuchi for reporting! + ]]> + + + [baseUrl]/metadata with an HTTP method + other than GET (e.g. POST, PUT) should result in an HTTP 405. Thanks to + Michael Lawley for reporting! + ]]> + + + Fix a server exception when trying to automatically add the profile tag + to a resource which already has one or more profiles set. Thanks to + Magnus Vinther for reporting! + + + QuantityParam parameters being used in the RESTful server were ignoring + the + :missing]]> + qualifier. Thanks to Alexander Takacs for reporting! + + + Annotation client failed with an exception if the response contained + extensions on fields in the resonse Bundle (e.g. Bundle.entry.search). + Thanks to GitHub user am202 for reporting! + + + Primitive elements with no value but an extension were sometimes not + encoded correctly in XML, and sometimes not parsed correctly in JSON. + Thanks to Bill de Beaubien for reporting! + + + The Web Testing UI has long had an issue where if you click on a button which + navigates to a new page (e.g. search, read, etc) and then click the back button + to return to the original page, the button you clicked remains disabled and can't + be clicked again (on Firefox and Safari). This is now fixed. Unfortunately the fix means that the + buttom will no longer show a "loading" spinner, but there doesn't seem to + be another way of fixing this. Thanks to Mark Scrimshire for reporting! + + + Extensions found while parsing an object that doesn't support extensions are now + reported using the IParserErrorHandler framework in the same way that + other similar errors are handled. This allows the parser to be more lenient + when needed. + + + Improve error message if incorrect type is placed in a list field in the data model. Java + uses generics to prevent this at compile time, but if someone is in an environment without + generics this helps improve the error message at runtime. Thanks to Hugo Soares for + suggesting. + + + Prevent an unneeded warning when parsing a resource containing + a declared extension. Thanks to Matt Blanchette for reporting! + + + Web Tester UI did not invoke VRead even if a version ID was specified. Thanks + to Poseidon for reporting! + + + Per discussion on the FHIR implementer chat, the JPA server no + longer includes _revinclude matches in the Bundle.total count, or the + page size limit. + + + JPA server now persists search results to the database in a new table where they + can be temporaily preserved. This makes the JPA server much more scalable, since it + no longer needs to store large lists of pages in memory between search invocations. +
    ]]> + Old searches are deleted after an hour by default, but this can be changed + via a setting in the DaoConfig. +
    + + JPA servers' resource version history mechanism + has been adjusted so that the history table + keeps a record of all versions including the + current version. This has the very helpful + side effect that history no longer needs to be + paged into memory as a complete set. Previously + history had a hard limit of only being able to + page the most recent 20000 entries. Now it has + no limit. + + + JPA server returned the wrong Bundle.type value (COLLECTION, should be SEARCHSET) + for $everything operation responses. Thanks to Sonali Somase for reporting! + + + REST and JPA server should reject update requests where the resource body does not + contain an ID, or contains an ID which does not match the URL. Previously these + were accepted (the URL ID was trusted) which is incorrect according to the + FHIR specification. Thanks to GitHub user ametke for reporting! +
    ]]> + As a part of this change, server error messages were also improved for + requests where the URL does not contain an ID but needs to (e.g. for + an update) or contains an ID but shouldn't (e.g. for a create) +
    + + When fields of type BoundCodeDt (e.g. Patient.gender) + are serialized and deserialized using Java's native + object serialization, the enum binder was not + serialized too. This meant that values for the + field in the deserialized object could not be + modified. Thanks to Thomas Andersen for reporting! + + + REST Server responded to HTTP OPTIONS requests with + any URI as being a request for the server's + Conformance statement. This is incorrect, as only + a request for OPTIONS [base url]]]> should be treated as such. Thanks to Michael Lawley for reporting! + + + REST annotation style client was not able to handle extended operations + ($foo) where the response from the server was a raw resource instead + of a Parameters resource. Thanks to Andrew Michael Martin for reporting! + + + JPA server applies _lastUpdated filter inline with other searches wherever possible + instead of applying this filter as a second query against the results of the + first query. This should improve performance when searching against large + datasets. + + + Parsers have new method + setDontEncodeElements]]> + which can be used to force the parser to not encode certain elements + in a resource when serializing. For example this can be used to omit + sensitive data or skip the resource metadata. + + + JPA server database design has been adjusted + so that different tables use different sequences + to generate their indexes, resulting in more sequential + resource IDs being assigned by the server + + + Server now correctly serves up Binary resources + using their native content type (instead of as a + FHIR resource) if the request contains an accept + header containing "application/xml" as some browsers + do. + + + DSTU2 resources now have a + getMeta()]]> method which returns a + modifiable view of the resource metadata for convenience. This + matches the equivalent method in the DSTU3 structures. + + + Add a new method to FhirContext called + setDefaultTypeForProfile + ]]> + which can be used to specify that when recources are received which declare + support for specific profiles, a specific custom structures should be used + instead of the default. For example, if you have created a custom Observation + class for a specific profile, you could use this method to cause your custom + type to be used by the parser for resources in a search bundle you receive. +
    + See the documentation page on + Profiles and Extensions + for more information. + ]]> +
    + + Parsing/Encoding a custom resource type which extends a + base type sometimes caused the FhirContext to treat all future + parses of the same resource as using the custom type even when + this was not wanted. +
    ]]> + Custom structures may now be explicitly declared by profile + using the + setDefaultTypeForProfile + ]]> + method. +
    ]]> + This issue was discovered and fixed as a part of the implementation of issue #315. +
    + + Set up the tinder plugin to work as an ant task + as well as a Maven plugin, and to use external + sources. Thanks to Bill Denton for the pull + request! + + + JPA server now allows searching by token + parameter using a system only and no code, + giving a search for any tokens which match + the given token with any code. Previously the + expected behaviour for this search + was not clear in the spec and HAPI had different + behaviour from the other reference servers. + + + Introduce a JAX-RS client provider which can be used instead of the + default Apache HTTP Client provider to provide low level HTTP + services to HAPI's REST client. See + JAX-RS & Alternate HTTP Client Providers]]> + for more information. +
    ]]> + This is useful in cases where you have other non-FHIR REST clients + using a JAX-RS provider and want to take advantage of the + rest of the framework. +
    ]]> + Thanks to Peter Van Houte from Agfa for the amazing work! +
    + + Parser failed with a NPE while encoding resources if the + resource contained a null extension. Thanks to + steve1medix for reporting! + + + In generated model classes (DSTU1/2) don't + use BoundCodeDt and BoundCodeableConceptDt for + coded fields which use example bindings. Thanks + to GitHub user Ricq for reporting! + + + @Operation will now infer the maximum number of repetitions + of their parameters by the type of the parameter. Previously if + a default max() value was not specified in the + @OperationParam annotation on a parameter, the maximum + was assumed to be 1. Now, if a max value is not explicitly specified + and the type of the parameter is a basic type (e.g. StringDt) the + max will be 1. If the parameter is a collection type (e.g. List<StringDt>) + the max will be * + ]]> + + + @Operation + may now use search parameter types, such as + TokenParam and + TokenAndListParam as values. Thanks to + Christian Ohr for reporting! + ]]> + + + Add databases indexes to JPA module search index tables + for the RES_ID column on each. This should help + performance when searching over large datasets. + Thanks to Emmanuel Duviviers for the suggestion! + + + DateTimeType should fail to parse 1974-12-25+10:00 as this is not + a valid time in FHIR. Thanks to Grahame Grieve for reporting! + + + When parsing a Bundle resource, if the Bundle.entry.request.url contains a UUID + but the resource body has no ID, the Resource.id will be populated with the ID from the + Bundle.entry.request.url. This is helpful when round tripping Bundles containing + UUIDs. + + + When parsing a DSTU3 bundle, references between resources did not have + the actual resource instance populated into the reference if the + IDs matched as they did in DSTU1/2. + + + Contained resource references on DSTU3 + resources were not serialized correctly when + using the Json Parser. Thanks to GitHub user + @fw060 for reporting and supplying a patch + which corrects the issue! + + + DSTU3 model classes equalsShallow and equalsDeep both did not work + correctly if a field was null in one object, but contained an empty + object in the other (e.g. a StringType with no actual value in it). These + two should be considered equal, since they would produce the exact same + wire format.
    ]]> + Thanks to GitHub user @ipropper for reporting and providing + a test case! +
    + + JPA server now supports searching for _tag:not=[tag]]]> + which enables finding resources that to not have a given tag/profile/security tag. + Thanks to Lars Kristian Roland for the suggestion! + + + Extensions containing resource references did not get encoded correctly + some of the time. Thanks to Poseidon for reporting! + + + Parsers (both XML and JSON) encoded the first few elements of DSTU3 structures in the wrong order: + Extensions were placed before any other content, which is incorrect (several + elements come first: meta, text, etc.) + + + In server implementations, the Bundle.entry.fullUrl was not getting correctly + populated on Hl7OrgDstu2 servers. Thanks to Christian Ohr for reporting! + + + Ensure that element IDs within resources (i.e. IDs on elements other than the + resource itself) get serialized and parsed correctly. Previously, these didn't get + serialized in a bunch of circumstances. Thanks to Vadim Peretokin for reporting + and providing test cases! + + + Improve CLI error message if the tool can't bind to the requested port. Thanks + to Claude Nanjo for the suggestion! + + + Server param of _summary=text]]> did not + include mandatory elements in return as well as + the text element, even though the FHIR specification + required it. + + + Remove invalid resource type "Documentation" from DSTU2 + structures. + + + JPA server did not respect target types for search parameters. E.g. Appointment:patient has + a path of "Appointment.participant.actor" and a target type of "Patient". The search path + was being correctly handled, but the target type was being ignored. + + + RestfulServer now manually parses URL parameters instead of relying on the container's + parsed parameters. This is useful because many Java servlet containers (e.g. Tomcat, Glassfish) + default to ISO-8859-1 encoding for URLs insetad of the UTF-8 encoding specified by + FHIR. + + + ResponseHighlightingInterceptor now doesn't highlight if the request + has an Origin header, since this probably denotes an AJAX request. + +
    + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Hibernate (JPA, Web Tester): 5.0.3 -> 5.0.7
  • +
  • Springframework (JPA, Web Tester): 4.2.2 -> 4.2.4
  • +
  • Phloc-Commons (Schematron Validator): 4.3.6 -> 4.4.4
  • +
  • Apache httpclient (Client): 4.4 -> 4.5.1
  • +
  • Apache httpcore (Client): 4.4 -> 4.4.4
  • +
  • SLF4j (All): 1.7.13 -> 1.7.14
  • + + ]]> +
    + + Remove a dependency on a Java 1.7 class + (ReflectiveOperationException) in several spots in the + codebase. This dependency was accidentally introduced in + 1.3, and animal-sniffer-plugin failed to detect it (sigh). + + + Add two new server interceptors: + RequestValidatingInterceptor + and + ResponseValidatingInterceptor + ]]> + which can be used to validate incoming requests or outgoing responses using the standard FHIR validation + tools. See the + Server Validation Page + ]]> + for examples of how to use these interceptors. These intereptors have both + been enabled on the + public test page. + ]]> + + + Make IBoundCodeableConcept and IValueSetEnumBinder serializable, + fixing an issue when trying to serialize model classes containing + bound codes. Thanks to Nick Peterson for the Pull Request! + + + Introduce a JAX-RS version of the REST server, which can be used + to deploy the same resource provider implementations which work + on the existing REST server into a JAX-RS (e.g. Jersey) environment. + Thanks to Peter Van Houte from Agfa for the amazing work! + + + CLI now supports writing to file:// URL for 'upload-examples' command + + + GZipped content is now supported for client-to-server uploads (create, update, transaction, etc.). + The server will not automatically detect compressed incoming content and decompress it (this can be + disabled using a RestfulServer configuration setting). A new client interceptor has been added + which compresses outgoing content from the client. + + + JPA server transaction attempted to validate resources twice each, + with one of these times being before anything had been committed to the + database. This meant that if a transaction contained both a Questionnaire + and a QuestionnaireResponse, it would fail because the QuestionnaireResponse + validator wouldn't be able to find the questionnaire. This is now corrected. + + + Add a new method to the generic/fluent client for searching: + .count(int)
    ]]> + This replaces the existing ".limitTo(int)" method which has + now been deprocated because it was badly named and undocumented. +
    + + Profile validator has been configured to allow extensions even if they + aren't explicitly declared in the profile. + + + Add a constraint that the Maven build will only run in JDK 8+. HAPI + remains committed to supporting JDK 6+ in the compiled library, but these + days it can only be built using JDK 8. Thanks to joelsch for the PR! + + + When serializing a value[x] field, if the value type was a profiled type (e.g. markdown is a + profile of string) HAPI 1.3 would use the base type in the element name, e.g. + valueString instead of valueMarkdown. After discussion with Grahame, this appears to + be incorrect behaviour so it has been fixed. + + + Support target parameter type in _include / _revinclude values, e.g. + _include=Patient:careProvider:Organization. Thanks to Joe Portner + for reporting! + + + Use ResponseHighlighterInterceptor in the hapi-fhir-jpaserver-example + project to provide nice syntax highlighting. Thanks to Rob Hausam for + noting that this wasn't there. + + + Introduce custom @CoverageIgnore annotation to hapi-fhir-base in order to + remove dependency on cobertura during build and in runtime. + + + Server-generated conformance statements incorrectly used /Profile/ instead + of /StructureDefinition/ in URL links to structures. + + + JsonParser has been changed so that when serializing numbers it will use + plain format (0.001) instead of scientific format (1e-3). The latter is + valid JSON, and the parser will still correctly parse either format (all + clients should be prepared to) but this change makes serialized + resources appear more consistent between XML and JSON. As a result of this + change, trailing zeros will now be preserved when serializing as well. + + + Add DSTU3 example to hapi-fhir-jpaserver-example. Thanks to Karl + Davis for the Pull Request! + + + RestfulServer#setUseBrowserFriendlyContentTypes has been deprecated and its + functionality removed. The intention of this feature was that if it + detected a request coming in from a browser, it would serve up JSON/XML + using content types that caused the browsers to pretty print. But + each browser has different rules for when to pretty print, and + after we wrote that feature both Chrome and FF changed their rules to break it anyhow. + ResponseHighlightingInterceptor provides a better implementation of + this functionality and should be used instead. + + + Narrative generator framework has removed the + ability to generate resource titles. This + functionality was only useful for DSTU1 + implementations and wasn't compatible + with coming changes to that API. + + + Remove dependency on Servlet-API 3.0+ by using methods available in 2.5 where possible. + Note that we continue to use Servlet-API 3.0+ features in some parts of the JPA API, so + running in an old serlvet container should be tested well before use. Thanks to Bill Denton + for reporting! + + + Add new methods to RestfulClientFactory allowing you to configure the size of the + client pool used by Apache HttpClient. Thanks to Matt Blanchette for the pull + request! + + + Add support for new modifier types on Token search params in Server and + annotation client. + + + Server conformance statement should include search parameter chains if the + chains are explicitly defined via @Search(whitelist={....}). Thanks to lcamilo15 + for reporting! + + + Remove afterPropertiesSet() call in Java config for JPA + server's EntityManagerFactory. This doesn't need to be called + manually, the the manual call led to a warning about + the EntityManager being created twice. + + + Allow server to correctly figure out it's own address even if the container provides + a Servlet Context Path which does not include the root. Thanks to Petro Mykhaylyshyn + for the pull request! + +
    + + + Bump the version of a few dependencies to the + latest versions (dependent HAPI modules listed in brackets): + +
  • Commons-lang3 (Core): 3.3.2 -> 3.4
  • +
  • Logback (Core): 1.1.2 -> 1.1.3
  • +
  • SLF4j (Core): 1.7.102 -> 1.7.12
  • +
  • Springframework (JPA, Web Tester): 4.1.5 -> 4.2.2
  • +
  • Hibernate (JPA, Web Tester): 4.2.17 -> 5."
  • +
  • Hibernate Validator (JPA, Web Tester): 5.2.1 -> 5.2.2
  • +
  • Derby (JPA, CLI, Public Server): 10.11.1.1 -> 10.12.1.1
  • +
  • Jetty (JPA, CLI, Public Server): 9.2.6.v20141205 -> 9.3.4.v20151007
  • + + ]]> +
    + + JPA and Tester Overlay now use Spring Java config files instead + of the older XML config files. All example projects have been updated. + + + JPA server removes duplicate resource index entries before storing them + (e.g. if a patient has the same name twice, only one index entry is created + for that name) + + + JPA server did not correctly index search parameters of type "reference" where the + path had multiple entries (i.e. "Resource.path1 | Resource.path2") + + + JPA server _history operations (server, type, instance) not correctly set the + Bundle.entry.request.method to POST or PUT for create and updates of the resource. + + + Support AND/OR on _id search parameter in JPA + + + Constructor for DateRanfeParam which dates in two DateParam instances was ignoring + comparators on the DateParam. + + + In JSON parsing, finding an object where an array was expected led to an unhelpful + error message. Thanks to Avinash Shanbhag for reporting! + + + JPA server gave an unhelpful error message if $meta-add or $meta-delete were called + with no meta elements in the input Parameters + + + Narrative generator did not include OperationOutcome.issue.diagnostics in the + generated narrative. + + + Clients (generic and annotation) did not populate the Accept header on outgoing + requests. This is now populated to indicate that the client supports both XML and + JSON unless the user has explicitly requested one or the other (in which case the + appropriate type only will be send in the accept header). Thanks to + Avinash Shanbhag for reporting! + + + QuestionnaireResponse validator now allows responses to questions of + type OPENCHOICE to be of type 'string' + + + JPA server should reject resources with a reference that points to an incorrectly typed + resource (e.g. points to Patient/123 but resource 123 is actually an Observation) or points + to a resource that is not valid in the location it is found in (e.g. points to Patient/123 but + the field supposed to reference an Organization). Thanks to Bill de Beaubien for reporting! + + + In server, if a client request is received and it has an Accept header indicating + that it supports both XML and JSON with equal weight, the server's default is used instead of the first entry in the list. + + + JPA server now supports searching with sort by token, quantity, + number, Uri, and _lastUpdated (previously only string, date, and _id + were supported) + + + Fix issue in JPA where a search with a _lastUpdated filter which matches no results + would crash if the search also had a _sort + + + Fix several cases where invalid requests would cause an HTTP 500 instead of + a more appropriate 400/404 in the JPA server (vread on invalid version, + delete with no ID, etc.) + + + Fix narrative generation for DSTU2 Medication resource + + + Profile validator now works for valuesets which use + v2 tables + + + JPA server Patient/[id]/$everything operation now supports + _lastUpdated filtering and _sort'ing of results. + + + Fix parser issue where profiled choice element datatypes (e.g. value[x] where one allowable + type is Duration, which is a profile of Quantity) get incorrectly encoded using the + profiled datatype name instead of the base datatype name as required by the FHIR + spec. Thanks to Nehashri Puttu Lokesh for reporting! + + + Some generated Enum types in DSTU2 HAPI structures + did not have latest valueset definitions applied. Thanks + to Bill de Beaubien for reporting! + + + JPA server can now successfully search for tokens pointing at code values + (values with no explicit system but an implied one, such as Patient.gender) + even if the system is supplied in the query. + + + Correct issues with Android library. Thanks to + Thomas Andersen for the submission! + + + JPA server incorrectly rejected match URLs + if they did not contain a question mark. Thanks + to Bill de Beaubien for reporting! + + + Remove invalid entries in OSGi Manifest. Thanks + to Alexander Kley for the fix! + + + JPA server now supports $everything on Patient and Encounter types (patient and encounter instance was already supported) + + + Generic client operation invocations now + have an additional inline method for generating the input + Parameters using chained method calls instead + of by passing a Parameters resource in + + + Parsing an XML resource where the XHTML + namespace was declared before the beginning + of the narrative section caused an invalid + re-encoding when encoding to JSON. + + + Conditional deletes in JPA did not correctly + process if the condition had a chain or a + qualifier, e.g. "Patient?organization.name" or + "Patient.identifier:missing" + + + Generic/fluent client search can now be + performed using a complete URL supplied + by user code. Thanks to Simone Heckmann + pointing out that this was needed! + + + Refactor JPA $everything operations so that + they perform better + + + Server operation methods can now declare the + ID optional, via + @IdParam(optional=true) + meaning that the same operation can also be invoked + at the type level. + + + Make JPA search queries with _lastUpdated parameter a bit more efficient + + + Clean up Android project to make it more lightweight and remove a + number of unneeded dependencies. Thanks to Thomas Andersen + for the pull request! + + + Fix a crash when encoding a Binary resource in JSON encoding + if the resource has no content-type + + + JPA server now supports read/history/search in transaction entries + by calling the actual implementing method in the server (previously + the call was simulated, which meant that many features did not work) + + + ResourceReferenceDt#loadResource(IRestfulClient) did not + use the client's read functionality, so it did not + handle JSON responses or use interceptors. Thanks to + JT for reporting! + + + JPA server maximumn length for a URI search parameter has been reduced from + 256 to 255 in order to accomodate MySQL's indexing requirements + + + Server failed to respond correctly to compartment search operations + if the same provider also contained a read operation. Thanks to GitHub user + @am202 for reporting! + + + Fix issue in testpage-overlay's new Java configuration where only the first + configured server actually gets used. + + + Introduce + IJpaServerInterceptor]]> + interceptors for JPA server which can be used for more fine grained operations. + + + Parser (XML and JSON) shouldn't encode an ID tag in resources + which are part of a bundle when the resource has a UUID/OID + ID. + + + Add ability for a server REST resource provider @Search method + to declare that it should allow even parameters it doesn't + understand. + + + Correctly set the Bundle.type value on all pages of a search result in + the server, and correcltly set the same value in JPA server $everything + results. + + + JPA $everything operations now support new parameters _content + and _text, which work the same way as the same parameters on a + search. This is experimental, since it is not a part of the core + FHIR specification. + + + Process "Accept: text/xml" and "Accept: text/json" headers was + wanting the equivalent FHIR encoding styles. These are not + correct, but the intention is clear so we will honour them + just to be helpful. + + + Generated Enum types for some ValueSets did not include all + codes (specifically, ValueSets which defined concepts containing + child concepts did not result in Enum values for the child concepts) + + + In the JPA server, order of transaction processing should be + DELETE, POST, PUT, GET, and the order should not matter + within entries with the same verb. Thanks to Bill de Beaubien + for reporting! + + + Add the ability to wire JPA conformance providers + using Spring (basically, add default constructors + and setters to the conformance providers). Thanks + to C. Mike Bylund for the pull request! + +
    + + + JPA server now validates QuestionnaireAnswers for conformance to their respective Questionnaire + if one is declared. + + + SyntaxHighlightingInterceptor now also highlights OperationOutcome responses for errors/exceptions. + + + Model classes do not use BoundCodeableConcept for example bindings that do not + actually point to any codes (e.g. Observation.interpretation). Thanks + to GitHub user @steve1medix for reporting! + + + Server now exports operations as separate resources instead of as contained resources + within Conformance + + + Add new operation $get-resource-counts which will replace the resource + count extensions exported in the Conformance statement by the JPA + server. + + + JPA server sorting often returned unexpected orders when multiple + indexes of the same type were found on the same resource (e.g. multiple string indexed fields). Thanks to Travis Cummings for reporting! + + + Add another method to IServerInterceptor which converts an exception generated on the server + into a BaseServerResponseException. This is useful so that servers using ResponseHighlighterInterceptor + will highlight exceptions even if they aren't created with an OperationOutcome. + + + XmlParser and JsonParser in DSTU2 mode should not encode empty + tags in resource. Thanks to Bill De Beaubien for reporting! + + + OperationDefinitions generated by server did not properly document + their return parameters or the type of their input parameters. + + + Operations in server generated conformance statement should only + appear once per name, since the name needs to be unique. + + + Resources and datatypes are now serializable. This is an + experimental feature which hasn't yet been extensively tested. Please test and give us your feedback! + + + Switch REST server to using HttpServletRequest#getContextPath() to get + the servlet's context path. This means that the server should behave more + predictably, and should work in servlet 2.4 environments. Thanks to + Ken Zeisset for the suggestion! + + + Vagrant environment now has an apt recipt to ensure that + package lists are up to date. Thanks to GitHub user + Brian S. Corbin (@corbinbs) for thr contribution! + + + JPA server and generic client now both support the _tag search parameter + + + Add support for BATCH mode to JPA server transaction operation + + + Server was not correctly unescaping URL parameter values with + a trailing comma or an escaped backslash. Thanks to GitHub user + @SherryH for all of her help in diagnosing this issue! + + + Avoid crash when parsing if an invalid child element is found in + a resource reference. + + + Create new android specialty libraries for DSTU1 and DSTU2 + + + Throwing a server exception (e.g. AuthenticationException) in a server interceptor's + incomingRequestPreProcessed method resulted in the server returning an HTTP 500 instead + of the appropriate error code for the exception being thrown. Thanks to Nagesh Bashyam + for reporting! + + + Fix issue in JSON parser where invalid contained resources (missing + a resourceType element) fail to parse with a confusing NullPointerException. + Thanks to GitHub user @hugosoares for reporting! + + + JPA server now implements the $validate-code operation + + + HAPI-FHIR now has support for _summary and _elements parameters, in server, client, + and JPA server. + + + _revinclude results from JPA server should have a Bundle.entry.search.mode of + "include" and not "match". Thanks to Josh Mandel for reporting! + + + Resource references using resource instance objects instead of resource IDs + will correctly qualify the IDs with the resource type if they aren't already qualified + + + Testpage Overlay project now properly allows a custom client + factory to be used (e.g. for custom authentication, etc.) Thanks + to Chin Huang (@pukkaone) for the pull request! + + + JPA server should reject IDs containing invalid characters (e.g. "abc:123") + but should allow client assigned IDs that contain text but do not start with + text. Thanks to Josh Mandel for reporting! + + + :text modifier on server and JPA server did not work correctly. Thanks to + Josh Mandel for reporting! + + + Fix issue in client where parameter values containing a comma were + sometimes double escaped. + + + _include parameters now support the new _include:recurse=FOO]]> + syntax that has been introduced in DSTU2 in the Client, Server, and JPA Server modules. + Non-recursive behaviour is now the default (previously it was recursive) and :recurse + needs to be explicitly stated in order to support recursion. + + + New operations added to JPA server to force re-indexing of all + resources (really only useful after indexes change or bugs are + fixed) + + + JPA server did not correctly index search parameters + of type "URI". Thanks to David Hay for reporting! Note that if you are using the JPA server, this change means that + there are two new tables added to the database schema. Updating existing resources in the database may fail unless you + set default values for the resource + table by issuing a SQL command similar to the following (false may be 0 or something else, depending on the database platform in use) + update hfj_resource set sp_coords_present = false;
    + update hfj_resource set sp_uri_present = false;
    ]]> +
    + + FIx issue in JPA server where profile declarations, tags, and + security labels were not always properly removed by an update that + was trying to remove them. Also don't store duplicates. + + + Instance $meta operations on JPA server did not previously return the + resource version and lastUpdated time + + + Server responses populate Bundle.entry.fullUrl if possible. Thanks + to Bill de Beaubien for reporting! + + + XML parser failed to initialize in environments where a very old Woodstox + library is in use (earlier than 4.0). Thanks to Bill de Beaubien for + reporting! + + + Invalid/unexpected attributes found when parsing composite elements + should be logged or reported to the parser error handler + + + JPA server can now store Conformance resources, per a request + from David Hay + + + ResponseHighlightingInterceptor now skips handling responses if it + finds a URL parameter of _raw=true]]> (in other + words, if this parameter is found, the response won't be returned as + HTML even if the request is detected as coming from a browser. + + + RestfulServer now supports dynamically adding and removing resource providers + at runtime. Thanks to Bill Denton for adding this. + + + JPA server now correctly suppresses contents of deleted resources + in history + + + JPA server returned deleted resources in search results when using the _tag, _id, _profile, or _security search parameters + + + Fix issue with build on Windows. Thanks to Bryce van Dyk for the pull request! + + + JPA server now supports $validate operation completely, including delete mode + and profile validation using the RI InstanceValidator + +
    + + + Add support for reference implementation structures. + + + Parsers did not encode the resource meta element if the resource + had tags but no other meta elements. Thanks to Bill de Beaubien and + Claude Nanjo for finding this. + + + Correct performance issue with :missing=true search requests where the parameter is a resource link. Thanks to wanghaisheng for all his help in testing this. + + + The self link in the Bundle returned by searches on the server does not respect the + server's address strategy (which resulted in an internal IP being shown on fhirtest.uhn.ca) + + + Introduce ResponseHighlighterInterceptor, which provides syntax highlighting on RESTful server responses + if the server detects that the request is coming from a browser. This interceptor has been added + to fhirtest.uhn.ca responses. + + + Performing a create operation in a client used an incorrect URL if the + resource had an ID set. ID should be ignored for creates. Thanks to + Peter Girard for reporting! + + + Add better addXXX() methods to structures, which take the datatype being added as a parameter. Thanks to Claude Nanjo for the + suggestion! + + + Add a new parser validation mechanism (see the + validation page]]> for info) which can be + used to validate resources as they are being parsed, and optionally fail if invalid/unexpected + elements are found in resource bodies during parsing. + + + IParser#parseResource(Class, String) method, which is used to parse a resource into the given + structure will now throw a DataFormatException if the structure is for the wrong type of + resource for the one actually found in the input String (or Reader). For example, if a Patient + resource is being parsed into Organization.class this will now cause an error. Previously, + the XML parser would ignore the type and the JSON parser would fail. This also caused + operations to not parse correctly if they returned a resource type other than + parameters with JSON encoding (e.g. the $everything operation on UHN's test server). + Thanks to Avinash Shanbhag for reporting! + + + Web tester UI now supports _revinclude + + + Support link elements in Bundle.entry when parsing in DSTU2 mode + using the old (non-resource) Bundle class. Thanks to GitHub user + @joedai for reporting! + + + LoggingInterceptor for server now supports logging DSTU2 extended operations by name + + + Woodstox XML parser has a default setting to limit the maximum + length of an attribute to 512kb. This caused issues handling + large attachments, so this setting has been increased to 100Mb. + Thanks to Nikos Kyriakoulakos for reporting! + + + Some HTML entities were not correctly converted during parsing. Thanks to + Nick Kitto for reporting! + + + In the JPA Server: + Transactions creating resources with temporary/placeholder resource IDs + and other resources with references to those placeholder IDs previously + did not work if the reference did not contain the resource type + (e.g. Patient/urn:oid:0.1.2.3 instead of urn:oid:0.1.2.3). The + latter is actually the correct way of specifying a reference to a + placeholder, but the former was the only way that worked. Both forms + now work, in order to be lenient. Thanks to Bill De Beaubien for + reporting! + + + When parsing Bundles, if Bundle.entry.base is set to "cid:" (for DSTU1) + or "urn:uuid:" / "urn:oid:" (for DSTU2) this is now correctly passed as + the base in resource.getId(). Conversely, when + encoding bundles, if a resource ID has a base defined, + and Bundle.entry.base is empty, it will now be + automatically set by the parser. + + + Add fluent client method for validate operation, and support the + new DSTU2 style extended operation for $validate if the client is + in DSTU2 mode. Thanks to Eric from the FHIR Skype Implementers chat for + reporting. + + + Server now supports complete Accept header content negotiation, including + q values specifying order of preference. Previously the q value was ignored. + + + Server in DSTU2 mode now indicates that whether it has support for Transaction operation or not. Thanks to Kevin Paschke for pointing out that this wasn't working! + + + Questionnaire.title now gets correctly indexed in JPA server (it has no path, so it is a special case) + + + JPA server now supports ifNoneMatch in GET within a transaction request. + + + DateRangeParam now supports null values in the constructor for lower or upper bounds (but + still not both) + + + Generic/fluent client and JPA server now both support _lastUpdated search parameter + which was added in DSTU2 + + + JPA server now supports sorting on reference parameters. Thanks to + Vishal Kachroo for reporting that this wasn't working! + + + Prevent Last-Updated header in responses coming back to the client from + overwriting the 'lastUpdated' value in the meta element in DSTU2 + resources. This is important because 'lastUpdated' can have more + precision than the equivalent header, but the client previously + gave the header priority. + + + JPA server supports _count parameter in transaction containing search URL (nested search) + + + DSTU2 servers now indicate support for conditional create/update/delete in their + conformance statement. + + + Support for the Prefer header has been added to the server, client, and + JPA modules. + + + JPA server failed to search for deep chained parameters across multiple references, + e.g. "Location.partof.partof.organization". Thanks to Ismael Sarmento Jr for + reporting! + + + Prevent crash when encoding resources with contained resources + if the contained resources contained a circular reference to each other + + + Add $meta, $meta-add, and $meta-delete operations to generic client + + + + + Bump the version of a few dependencies to the + latest versions: + +
  • Phloc-commons (for schematron validation) 4.3.5 -> 4.3.6
  • +
  • Apache HttpClient 4.3.6 -> 4.4
  • +
  • Woodstox 4.4.0 -> 4.4.1
  • +
  • SLF4j 1.7.9 -> 1.7.10
  • +
  • Spring (used in hapi-fhir-jpaserver-base module) 4.1.3.RELEASE -> 4.1.5.RELEASE
  • + + ]]> +
    + + Add support for "profile" and "tag" elements in the resource Meta block + when parsing DSTU2 structures. + + + When a user manually creates the list of contained resources in a resource, + the encoder fails to encode any resources that don't have a '#' at the + start of their ID. This is unintuitive, so we now assume that '123' means '#123'. + Thanks to myungchoi for reporting and providing a test case! + + + Add methods for setting the default encoding (XML/JSON) and + oretty print behaviour in the Fluent Client. Thanks to Stackoverflow + user ewall for the idea. + + + JPA Server did not mark a resource as "no longer deleted" if it + was updated after being deleted. Thanks to Elliott Lavy and Lloyd + McKenzie for reporting! + + + Fix regression in 0.9 - Server responds with an HTTP 500 and a NullPointerException instead of an HTTP 400 and a useful error message if the client requests an unknown resource type + + + Add support for + _revinclude]]> + parameter in client, server, and JPA. + + + Include constants on resources (such as + Observation.INCLUDE_VALUE_STRING]]>) + have been switched in the DSTU2 structures to use + the new syntax required in DSTU2: [resource name]:[search param NAME] + insead of the DSTU1 style [resource name].[search param PATH] + + + When encoding resources, the parser will now convert any resource + references to versionless references automatically (i.e. it will + omit the version part automatically if one is present in the reference) + since references between resources must be versionless. Additionally, + references in server responses will omit the server base URL part of the + reference if the base matches the base for the server giving + the response. + + + Narrative generator incorrectly sets the Resource.text.status to 'generated' even if the + given resource type does not have a template (and therefore no narrative is actually generated). + Thanks to Bill de Beaubien for reporting! + + + Searching in JPA server with no search parameter returns deleted resources when it should exclude them. + + + Remove Eclipse and IntelliJ artifacts (.project, *.iml, etc) from version control. Thanks + to Doug Martin for the suggestion! + + + REST server methods may now have a parameter of + type NarrativeModeEnum which will be populated with + the value of the _narrative URL parameter + if one was supplied. Annotation client methods + may also include a parameter of this type, and it + will be used to populate this parameter on the request + URL if it is not null. Thanks to Neal Acharya for the + idea! + + + Android JAR now includes servlet-API classes, as the project will not + work without them. Thanks + + + Requested _include values are preserved across paging links when the + server returns multiple pages. Thanks to Bill de Beaubien for + reporting! + + + Add new server address strategy "ApacheProxyAddressStrategy" which uses + headers "x-forwarded-host" and "x-forwarded-proto" to determine the + server's address. This is useful if you are deploying a HAPI FHIR + server behind an Apache proxy (e.g. for load balancing or other reasons). + Thanks to Bill de Beaubien for contributing! + + + Resource references between separate resources found in a single + bundle did not get populated with the actual resource when parsing a + DSTU2 style bundle. Thanks to Nick Peterson for reporting and figuring + out why none of our unit tests were actually catching the problem! + + + JSON encoder did not encode contained resources when encoding + a DSTU2 style bundle. Thanks to Mohammad Jafari and baopingle + for all of their help in tracking this issue down and developing + useful unit tests to demonstrate it. + + + Client now supports invoking transcation using a DSTU2-style + Bundle resource as the input. + + + JPA Server $everything operation could sometimes include a duplicate copy of + the main focus resource if it was referred to in a deep chain. Thanks + to David Hay for reporting! + + + JPA Server $everything operation now allows a _count parameter + + + JPA server failed to index resources containing ContactPointDt elements with + populated values (e.g. Patient.telecom). Thanks to Mohammad Jafari for reporting! + + + Add a new configuration method on the parsers, + setStripVersionsFromReferences(boolean)]]> which + configures the parser to preserve versions in resource reference links when + encoding. By default, these are removed. + + + Terser's IModelVisitor now supplies to the path to the element. This is + an API change, but I don't think there are many users of the IModelVisitor yet. + Please let us know if this is a big hardship and we can find an alternate way + of making this change. + + + Prevent server from returning a Content-Location header for search + response when using the DSTU2 bundle format + + + JPA server (uhnfhirtest.uhn.ca) sometimes included an empty + "text" element in Bundles being returned. + + + Add a framework for the Web Tester UI to allow its internal FHIR client to + be configured (e.g. to add an authorization interceptor so that it adds + credentials to client requests it makes). Thanks to Harsha Kumara for + the suggestion! + + + Fix regression in early 1.0 builds where resource type sometimes does not get + populated in a resource ID when the resource is parsed. Thanks to + Nick Peterson for reporting, and for providing a test case! + + + Allow fluent/generic client users to execute a transaction using a raw string (containing a bundle resource) + as input instead of a Bundle resource class instance. + + + Disable date validation in the web tester UI, so that it is possible to + enter partial dates, or dates without times, or even test out invalid date + options. + + + Make BaseElement#getUndeclaredExtensions() and BaseElement#getUndeclaredExtensions() return + a mutable list so that it is possible to delete extensions from a resource instance. + + + Server conformance statement check in clients (this is the check + where the first time a given FhirContext is used to access a given server + base URL, it will first check the server's Conformance statement to ensure + that it supports the correct version of FHIR) now uses any + registered client interceptors. In addition, IGenericClient now has a method + "forceConformanceCheck()" which manually triggers this check. Thanks to + Doug Martin for reporting and suggesting! + + + Rename the Spring Bean definition for the JPA server EntityManager from + "myEntityManagerFactory" to just "entityManagerFactory" as this is the + default bean name expected in other parts of the Spring framework. + Thanks to Mohammad Jafari for the suggestion! + + + Improve error message when a user tries to perform a create/update with an invalid + or missing Content-Type header. Thanks to wanghaisheng for reporting! (This was + actually a three part bug, so the following two fixes also reference this + bug number) + + + Add support for :missing qualifier in generic/fluent client. + + + Add support for :missing qualifier in JPA server. + + + Add a new configuration method on the parsers, + setStripVersionsFromReferences(boolean)]]> which + configures the parser to preserve versions in resource reference links when + encoding. By default, these are removed. + + + Add an exception for RESTful clients/servers to represent the + HTTP 403 Forbidden status code. Thanks to Joel Costigliola for + the patch! + + + Transaction server operations incorrectly used the "Accept" header instead of the "Content-Type" header to determine the + POST request encoding. Thanks to Rene Spronk for providing a test case! + +
    + + + Support for DSTU2 features introduced: New resource definitions, Bundle resource, + encoding changes (ID in resource bodt, meta tag) + + + Fix an issue encoding extensions on primitive types in JSON. Previously the "_value" object + would be an array even if the field it was extending was not repeatable. This is not correct + according to the specification, nor can HAPI's parser parse this correctly. The encoder + has been corrected, and the parser has been adjusted to be able to handle resources with + extensions encoded in this way. Thanks to Mohammad Jafari for reporting! + + + Library now checks if custom resource types can be instantiated on startup + (e.g. because they don't have a no-argument constructor) in order to + avoid failing later + + + Bump a few dependency JARs to the latest versions in Maven POM: + +
  • SLF4j (in base module) - Bumped to 1.7.9
  • +
  • Apache HTTPClient (in base module) - Bumped to 4.3.6
  • +
  • Hibernate (in JPA module) - Bumped to 4.3.7
  • + + ]]> +
    + + IdDt failed to recognize local identifiers containing fragments that look like + real identifiers as being local identifiers even though they started with '#'. + For example, a local resource reference of "#aa/_history/aa" would be incorrectly + parsed as a non-local reference. + Thanks to Mohammad Jafari for reporting! + + + Last-Modified]]> + header in server was incorrectly using FHIR date format instead + of RFC-1123 format. + + + Server create and update methods failed with an IllegalArgumentException if + the method type was a custom resource definition type (instead of a built-in + HAPI type). Thanks to Neal Acharya for the analysis. + + + JPA server module now supports + _include]]> + value of + *]]>. Thanks to Bill de Beaubien for reporting! + + + IdDt method + + returned String (unlike all of the other "withFoo" methods on that class), + and did not work correctly if the IdDt already had a server base. This + has been corrected. Note that the return type for this method has been + changed, so code may need to be updated. + + + In previous versions of HAPI, the XML parser encoded multiple contained + resources in a single + <contained></contained>]]> + tag, even though the FHIR specification rerquires a separate + <contained></contained>]]> + tag for each resource. This has been corrected. Note that the parser will + correctly parse either form (this has always been the case) so this + change should not cause any breakage in HAPI based trading partners, but + may cause issues if other applications have been coded to depend on the + incorrect behaviour. Thanks to Mochaholic for reporting! + + + Custom/user defined resource definitions which contained more than one + child with no order defined failed to initialize properly. Thanks to + Andy Huang for reporting and figuring out where the + problem was! + + + RESTful Client now queries the server (only once per server base URL) to ensure that + the given server corresponds to the correct version of the FHIR specification, as + defined by the FhirContext. This behaviour can be disabled by setting the + appropriate configuration on the + RestfulClientConfig. Thanks to Grahame Grieve for the suggestion! + + + JPA module now supports deleting resource via transaction + + + DateClientParam#second() incorrectly used DAY precision instead + of SECOND precision. Thanks to Tom Wilson for the pull request! + + + Fix issue where HAPI failed to initialize correctly if Woodstox library was not on the classpath, even + if StAX API was configured to use a different provider. Thanks to + James Butler for reporting and figuring out where the issue was! + + + Calling BaseDateTimeDt#setValue(Date, TemporalPrecisionEnum) did not always actually respect + the given precision when the value was encoded. Thanks to jacksonjesse for + reporting! + + + Encoders (both XML and JSON) will no longer encode contained resources if they are + not referenced anywhere in the resource via a local reference. This is just a convenience + for users who have parsed a resource with contained resources and want to remove some + before re-encoding. Thanks to Alexander Kley for reporting! + + + Add support for DSTU2 style security labels in the parser and encoder. Thanks to + Mohammad Jafari for the contribution! + + + Server requests for Binary resources where the client has explicitly requested XML or JSON responses + (either with a _format]]> URL parameter, or an Accept]]> request header) + will be responded to using the Binary FHIR resource type instead of as Binary blobs. This is + in accordance with the recommended behaviour in the FHIR specification. + + + Add new properties to RestfulServer: "DefaultResponseEncoding", which allows + users to configure a default encoding (XML/JSON) to use if none is specified in the + client request. Currently defaults to XML. Also "DefaultPrettyPrint", which specifies + whether to pretty print responses by default. Both properties can be overridden + on individual requets using the appropriate Accept header or request URL parameters. + + + Add support for quantity search params in FHIR tester UI + + + Add support for FHIR "extended operations" as defined in the FHIR DSTU2 + specification, for the Generic Client, Annotation Client, and + Server. + + + Observation.applies[x] and other similar search fields with multiple allowable + value types were not being correctly indexed in the JPA server. + + + DateClientParam.before() incorrectly placed "<=" instead of + "<" in the request URL. Thanks to Ryan for reporting! + + + Server now only automatically adds _include resources which are provided + as references if the client request actually requested that specific include. + See RestfulServer + + + User defined resource types which contain extensions that use a bound code type + (e.g. an BoundCodeDt with a custom Enum) failed to parse correctly. Thanks + to baopingle for reporting and providing a test case! + + + Sorting is now supported in the Web Testing UI (previously a button existed for sorting, but it didn't do anything) + + + Server will no longer include stack traces in the OperationOutcome returned to the client + when an exception is thrown. A new interceptor called ExceptionHandlingInterceptor has been + created which adds this functionality back if it is needed (e.g. for DEV setups). See the + server interceptor documentation for more information. Thanks to Andy Huang for the suggestion! + +
    + + + API CHANGE:]]> The "FHIR structures" for DSTU1 (the classes which model the + resources and composite datatypes) have been moved out of the core JAR into their + own JAR, in order to allow support for DEV resources, and DSTU2 resources when thast + version is finalized. See the + DSTU2 page]]> + for more information. + + + Deprocated API Removal: The following classes (which were deprocated previously) + have now been removed: +
      +
    • ISecurityManager: If you are using this class, the same functionality + is available through the more general purpose + server interceptor + capabilities. +
    • CodingListParam: This class was made redundant by the + TokenOrListParam + class, which can be used in its place. +
    + ]]> +
    + + API Change: The IResource#getResourceMetadata() method has been changed + from returning + Map<ResourceMetadataKeyEnum<?>, Object> + to returning a new type called + ResourceMetadataMap. This new type implements + Map<ResourceMetadataKeyEnum<?>, Object> + itself, so this change should not break existing code, but may + require a clean build in order to run correctly. + ]]> + + + Profile generation on the server was not working due to IdDt being + incorrectly used. Thanks to Bill de Beaubien for the pull request! + + + Profiles did not generate correctly if a resource definition class had a + defined extension which was of a composite type. Thanks to Bill de Beaubien for the pull request! + + + Remove unnecessary IOException from narrative generator API. Thanks to + Petro Mykhailysyn for the pull request! + + + Introduced a new + @ProvidesResources]]> annotation which can be added to + resource provider and servers to allow them to declare additional resource + classes they are able to serve. This is useful if you have a server which can + serve up multiple classes for the same resource type (e.g. a server that sometimes + returns a default Patient, but sometimes uses a custom subclass). + Thanks to Bill de Beaubien for the pull request! + + + Introduced a new + @Destroy]]> annotation which can be added to + a resource provider method. This method will be called by the server when it + is being closed/destroyed (e.g. when the application is being undeployed, the + container is being shut down, etc.) + Thanks to Bill de Beaubien for the pull request! + + + Add a new method to the server interceptor + framework which allows interceptors to be notified of any exceptions and + runtime errors within server methods. Interceptors may optionally also + override the default error handling behaviour of the RestfulServer. + + + Add constants to BaseResource for the "_id" search parameter which all resources + should support. + + + DateRangeParam parameters on the server now return correct + getLowerBoundAsInstant()]]> + and + getUpperBoundAsInstant()]]> + values if a single unqualified value is passed in. For example, if + a query containing + &birthdate=2012-10-01]]> + is received, previously these two methods would both return the same + value, but with this fix + getUpperBoundAsInstant()]]> + now returns the instant at 23:59:59.9999. + + + Resource fields with a type of "*" (or Any) sometimes failed to parse if a + value type of "code" was used. Thanks to Bill de Beaubien for reporting! + + + Remove dependency on JAXB libraries, which were used to parse and encode + dates and times (even in the JSON parser). JAXB is built in to most JDKs + but the version bundled with IBM's JDK is flaky and resulted in a number + of problems when deploying to Websphere. + + + Primitive datatypes now preserve their original string value when parsing resources, + as well as containing the "parsed value". For instance, a DecimalDt field value of + 1.0000]]> will be parsed into the corresponding + decimal value, but will also retain the original value with the corresponding + level of precision. This allows vadliator rules to be applied to + original values as received "over the wire", such as well formatted but + invalid dates, e.g. "2001-15-01". Thanks to Joe Athman for reporting and + helping to come up with a fix! + + + When using Generic Client, if performing a + or operation using a String as the resource body, + the client will auto-detect the FHIR encoding style and send an appropriate + header. + + + JPA module (and public HAPI-FHIR test server) were unable to process resource types + where at least one search parameter has no path specified. These now correctly save + (although the server does not yet process these params, and it should). Thanks to + GitHub user shvoidlee for reporting and help with analysis! + + + Generic/Fluent Client "create" and "update" method requests were not setting a content type header + + + DateDt left precision value as in the constructor + . + + + RESTful server now doesn't overwrite resource IDs if they are absolute. In other words, if + a server's Resource Provider returns a resource with ID "Patient/123" it will be translated to + "[base url]/Patient/123" but if the RP returns ID "http://foo/Patient/123" the ID will be + returned exactly as is. Thanks to Bill de Beaubien for the suggestion! + + + JPA module Transaction operation was not correctly replacing logical IDs + beginning with "cid:" with server assigned IDs, as required by the + specification. + + + did not visit or find children in contained resources when + searching a resource. This caused server implementations to not always return contained + resources when they are included with a resource being returned. + + + Add a method which returns the name of the + resource in question (e.g. "Patient", or "Observation"). This is intended as a + convenience to users. + + + Do not strip version from resource references in resources returned + from server search methods. Thanks to Bill de Beaubien for reporting! + + + Correct an issue with the validator where changes to the underlying + OperationOutcome produced by a validation cycle cause the validation + results to be incorrect. + + + Client interceptors registered to an interface based client instance + were applied to other client instances for the same client interface as well. (Issue + did not affect generic/fluent clients) + + + DateDt, DateTimeDt and types InstantDt types now do not throw an exception + if they are used to parse a value with the wrong level of precision for + the given type but do throw an exception if the wrong level of precision + is passed into their constructors.
    ]]> + This means that HAPI FHIR can now successfully parse resources from external + sources that have the wrong level of precision, but will generate a validation + error if the resource is validated. Thanks to Alexander Kley for the suggestion! +
    + + Encoding a Binary resource without a content type set should not result in a NullPointerException. Thanks + to Alexander Kley for reporting! + + + Server gives a more helpful error message if multiple IResourceProvider implementations + are provided for the same resource type. Thanks to wanghaisheng for the idea! + + + Bring DSTU1 resource definitions up to version 0.0.82-2929]]> + Bring DEV resource definitions up to 0.4.0-3775]]> + Thanks to crinacimpian for reporting! + + + JPA server did not correctly process _include requests if included + resources were present with a non-numeric identifier. Thanks to + Bill de Beaubien for reporting! + + + Client requests which include a resource/bundle body (e.g. create, + update, transaction) were not including a charset in the content type + header, leading to servers incorrectly assuming ISO-8859/1. Thanks to + shvoidlee for reporting! + + + Clean up the way that Profile resources are automatically exported + by the server for custom resource profile classes. See the + @ResourceDef]]> + JavaDoc for information on how this works. + + + Add convenience methods to TokenOrListParam to test whether any of a set of tokens match + the given requested list. + + + Add a protected method to RestfulServer which allows developers to + implement their own method for determining which part of the request + URL is the FHIR request path (useful if you are embedding the RestulServer inside + of another web framework). Thanks to Harsha Kumara for the pull request! + +
    + + + API CHANGE:]]> The TagList class previously implemented ArrayList semantics, + but this has been replaced with LinkedHashMap semantics. This means that the list of + tags will no longer accept duplicate tags, but that tag order will still be + preserved. Thanks to Bill de Beaubien for reporting! + + + Server was incorrectly including contained resources being returned as both contained resources, and as + top-level resources in the returned bundle for search operations. + Thanks to Bill de Beaubien for reporting! This also fixes Issue #20, thanks to + lephty for reporting! + + + Documentation fixes + + + Add a collection of new methods on the generic client which support the + read, + read, + and search + ]]> + operations using an absolute URL. This allows developers to perform these operations using + URLs they obtained from other sources (or external resource references within resources). In + addition, the existing read/vread operations will now access absolute URL references if + they are passed in. Thanks to Doug Martin of the Regenstrief Center for Biomedical Informatics + for contributing this implementation! + + + Server implementation was not correctly figuring out its own FHIR Base URL when deployed + on Amazon Web Service server. Thanks to Jeffrey Ting and Bill De Beaubien of + Systems Made Simple for their help in figuring out this issue! + + + XML Parser failed to encode fields with both a resource reference child and + a primitive type child. Thanks to Jeffrey Ting and Bill De Beaubien of + Systems Made Simple for their help in figuring out this issue! + + + HAPI now runs successfully on Servlet 2.5 containers (such as Tomcat 6). Thanks to + Bernard Gitaadji for reporting and diagnosing the issue! + + + Summary (in the bundle entry) is now encoded by the XML and JSON parsers if supplied. Thanks to David Hay of + Orion Health for reporting this! + + + Conformance profiles which are automatically generated by the server were missing a few mandatory elements, + which meant that the profile did not correctly validate. Thanks to Bill de Beaubien of Systems Made Simple + for reporting this! + + + XHTML (in narratives) containing escapable characters (e.g. < or ") will now always have those characters + escaped properly in encoded messages. + + + Resources containing entities which are not valid in basic XML (e.g. &sect;) will have those + entities converted to their equivalent unicode characters when resources are encoded, since FHIR does + not allow extended entities in resource instances. + + + Add a new client interceptor which adds HTTP Authorization Bearer Tokens (for use with OAUTH2 servers) + to client requests. + + + Add phloc-commons dependency explicitly, which resolves an issue building HAPI from source on + some platforms. Thanks to Odysseas Pentakalos for the patch! + + + HAPI now logs a single line indicating the StAX implementation being used upon the + first time an XML parser is created. + + + Update methods on the server did not return a "content-location" header, but + only a "location" header. Both are required according to the FHIR specification. + Thanks to Bill de Beaubien of Systems Made Simple for reporting this! + + + Parser failed to correctly read contained Binary resources. Thanks to Alexander Kley for + the patch! + + + Calling encode multiple times on a resource with contained resources caused the contained + resources to be re-added (and the actual message to grow) with each encode pass. Thanks to + Alexander Kley for the test case! + + + JSON-encoded contained resources with the incorrect "_id" element (which should be "id", but some + incorrect examples exist on the FHIR specification) now parse correctly. In other words, HAPI + previously only accepted the correct "id" element, but now it also accepts the incorrect + "_id" element just to be more lenient. + + + Several unit tests failed on Windows (or any platform with non UTF-8 default encoding). This may + have also caused resource validation to fail occasionally on these platforms as well. + Thanks to Bill de Beaubien for reporting! + + + toString() method on TokenParam was incorrectly showing the system as the value. + Thanks to Bill de Beaubien for reporting! + + + Documentation on contained resources contained a typo and did not actually produce contained resources. Thanks + to David Hay of Orion Health for reporting! + + + Add a + Vagrant]]> + based environment (basically a fully built, self contained development environment) for + trying out the HAPI server modules. Thanks to Preston Lee for the pull request, and for + offering to maintain this! + + + Change validation API so that it uses a return type instead of exceptions to communicate + validation failures. Thanks to Joe Athman for the pull request! + + + Add a client interceptor which adds an HTTP cookie to each client request. Thanks to + Petro Mykhailysyn for the pull request! + + + + + + Add server interceptor framework, and new interceptor for logging incoming + requests. + + + Add server validation framework for validating resources against the FHIR schemas and schematrons + + + Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University + Health Network for reporting! + + + Create method was incorrectly returning an HTTP 204 on sucessful completion, but + should be returning an HTTP 200 per the FHIR specification. Thanks to wanghaisheng + for reporting! + + + FHIR Tester UI now correctly sends UTF-8 charset in responses so that message payloads containing + non US-ASCII characters will correctly display in the browser + + + JSON parser was incorrectly encoding extensions on composite elements outside the element itself + (as is done correctly for non-composite elements) instead of inside of them. Thanks to David Hay of + Orion for reporting this! + + + Contained/included resource instances received by a client are now automatically + added to any ResourceReferenceDt instancea in other resources which reference them. + + + Add documentation on how to use eBay CORS Filter to support Cross Origin Resource + Sharing (CORS) to server. CORS support that was built in to the server itself has + been removed, as it did not work correctly (and was reinventing a wheel that others + have done a great job inventing). Thanks to Peter Bernhardt of Relay Health for all the assistance + in testing this! + + + IResource interface did not expose the getLanguage/setLanguage methods from BaseResource, + so the resource language was difficult to access. + + + JSON Parser now gives a more friendly error message if it tries to parse JSON with invalid use + of single quotes + + + Transaction server method is now allowed to return an OperationOutcome in addition to the + incoming resources. The public test server now does this in order to return status information + about the transaction processing. + + + Update method in the server can now flag (via a field on the MethodOutcome object being returned) + that the result was actually a creation, and Create method can indicate that it was actually an + update. This has no effect other than to switch between the HTTP 200 and HTTP 201 status codes on the + response, but this may be useful in some circumstances. + + + Annotation client search methods with a specific resource type (e.g. List<Patient> search()) + won't return any resources that aren't of the correct type that are received in a response + bundle (generally these are referenced resources, so they are populated in the reference fields instead). + Thanks to Tahura Chaudhry of University Health Network for the unit test! + + + Added narrative generator template for OperationOutcome resource + + + Date/time types did not correctly parse values in the format "yyyymmdd" (although the FHIR-defined format + is "yyyy-mm-dd" anyhow, and this is correctly handled). Thanks to Jeffrey Ting of Systems Made Simple + for reporting! + + + Server search method for an unnamed query gets called if the client requests a named query + with the same parameter list. Thanks to Neal Acharya of University Health Network for reporting! + + + Category header (for tags) is correctly read in client for "read" operation + + + Transaction method in server can now have parameter type Bundle instead of + List<IResource> + + + HAPI parsers now use field access to get/set values instead of method accessors and mutators. + This should give a small performance boost. + + + JSON parser encodes resource references incorrectly, using the name "resource" instead + of the name "reference" for the actual reference. Thanks to + Ricky Nguyen for reporting and tracking down the issue! + + + Rename NotImpementedException to NotImplementedException (to correct typo) + + + Server setUseBrowserFriendlyContentType setting also respected for errors (e.g. OperationOutcome with 4xx/5xx status) + + + Fix performance issue in date/time datatypes where pattern matchers were not static + + + Server now gives a more helpful error message if a @Read method has a search parameter (which is invalid, but + previously lead to a very unhelpful error message). Thanks to Tahura Chaudhry of UHN for reporting! + + + Resource of type "List" failed to parse from a bundle correctly. Thanks to David Hay of Orion Health + for reporting! + + + QuantityParam correctly encodes approximate (~) prefix to values + + + If a server defines a method with parameter "_id", incoming search requests for that method may + get delegated to the wrong method. Thanks to Neal Acharya for reporting! + + + SecurityEvent.Object structural element has been renamed to + SecurityEvent.ObjectElement to avoid conflicting names with the + java Object class. Thanks to Laurie Macdougall-Sookraj of UHN for + reporting! + + + Text/narrative blocks that were created with a non-empty + namespace prefix (e.g. <xhtml:div xmlns:xhtml="...">...</xhtml:div>) + failed to encode correctly (prefix was missing in encoded resource) + + + Resource references previously encoded their children (display and reference) + in the wrong order so references with both would fail schema validation. + + + SecurityEvent resource's enums now use friendly enum names instead of the unfriendly + numeric code values. Thanks to Laurie MacDougall-Sookraj of UHN for the + suggestion! + + + + + HAPI has a number of RESTful method parameter types that have similar but not identical + purposes and confusing names. A cleanup has been undertaken to clean this up. + This means that a number of existing classes + have been deprocated in favour of new naming schemes. +
    ]]> + All annotation-based clients and all server search method parameters are now named + (type)Param, for example: StringParam, TokenParam, etc. +
    ]]> + All generic/fluent client method parameters are now named + (type)ClientParam, for example: StringClientParam, TokenClientParam, etc. +
    ]]> + All renamed classes have been retained and deprocated, so this change should not cause any issues + for existing applications but those applications should be refactored to use the + new parameters when possible. +
    + + Allow server methods to return wildcard generic types (e.g. List<? extends IResource>) + + + Search parameters are not properly escaped and unescaped. E.g. for a token parameter such as + "&identifier=system|codepart1\|codepart2" + + + Add support for OPTIONS verb (which returns the server conformance statement) + + + Add support for CORS headers in server + + + Bump SLF4j dependency to latest version (1.7.7) + + + Add interceptor framework for clients (annotation based and generic), and add interceptors + for configurable logging, capturing requests and responses, and HTTP basic auth. + + + Transaction client invocations with XML encoding were using the wrong content type ("application/xml+fhir" instead + of the correct "application/atom+xml"). Thanks to David Hay of Orion Health for surfacing this one! + + + Bundle entries now support a link type of "search". Thanks to David Hay for the suggestion! + + + If a client receives a non 2xx response (e.g. HTTP 500) and the response body is a text/plain message or + an OperationOutcome resource, include the message in the exception message so that it will be + more conveniently displayed in logs and other places. Thanks to Neal Acharya for the suggestion! + + + Read invocations in the client now process the "Content-Location" header and use it to + populate the ID of the returned resource. Thanks to Neal Acharya for the suggestion! + + + Fix issue where vread invocations on server incorrectly get routed to instance history method if one is + defined. Thanks to Neal Acharya from UHN for surfacing this one! + + + Binary reads on a server not include the Content-Disposition header, to prevent HTML in binary + blobs from being used for nefarious purposes. See + FHIR Tracker Bug 3298]]> + for more information. + + + Support has been added for using an HTTP proxy for outgoing requests. + + + Fix: Primitive extensions declared against custom resource types + are encoded even if they have no value. Thanks to David Hay of Orion for + reporting this! + + + Fix: RESTful server deployed to a location where the URL to access it contained a + space (e.g. a WAR file with a space in the name) failed to work correctly. + Thanks to David Hay of Orion for reporting this! + +
    + + + BREAKING CHANGE:]]>: IdDt has been modified so that it + contains a partial or complete resource identity. Previously it contained + only the simple alphanumeric id of the resource (the part at the end of the "read" URL for + that resource) but it can now contain a complete URL or even a partial URL (e.g. "Patient/123") + and can optionally contain a version (e.g. "Patient/123/_history/456"). New methods have + been added to this datatype which provide just the numeric portion. See the JavaDoc + for more information. + + + API CHANGE:]]>: Most elements in the HAPI FHIR model contain + a getId() and setId() method. This method is confusing because it is only actually used + for IDREF elements (which are rare) but its name makes it easy to confuse with more + important identifiers. For this reason, these methods have been deprocated and replaced with + get/setElementSpecificId() methods. The old methods will be removed at some point. Resource + types are unchanged and retain their get/setId methods. + + + Allow use of QuantityDt as a service parameter to support the "quantity" type. Previously + QuantityDt did not implement IQueryParameterType so it was not valid, and there was no way to + support quantity search parameters on the server (e.g. Observation.value-quantity) + + + Introduce StringParameter type which can be used as a RESTful operation search parameter + type. StringParameter allows ":exact" matches to be specified in clients, and handled in servers. + + + Parsers (XML/JSON) now support deleted entries in bundles + + + Transaction method now supported in servers + + + Support for Binary resources added (in servers, clients, parsers, etc.) + + + Support for Query resources fixed (in parser) + + + Nested contained resources (e.g. encoding a resource with a contained resource that itself contains a resource) + now parse and encode correctly, meaning that all contained resources are placed in the "contained" element + of the root resource, and the parser looks in the root resource for all container levels when stitching + contained resources back together. + + + Server methods with @Include parameter would sometimes fail when no _include was actually + specified in query strings. + + + Client requests for IdentifierDt types (such as Patient.identifier) did not create the correct + query string if the system is null. + + + Add support for paging responses from RESTful servers. + + + Don't fail on narrative blocks in JSON resources with only an XML declaration but no content (these are + produced by the Health Intersections server) + + + Server now automatically compresses responses if the client indicates support + + + Server failed to support optional parameters when type is String and :exact qualifier is used + + + Read method in client correctly populated resource ID in returned object + + + Support added for deleted-entry by/name, by/email, and comment from Tombstones spec + + + + + + + + + +
    diff --git a/src/site/fml/hapi-fhir-faq.fml b/src/site/fml/hapi-fhir-faq.fml index 6122d411250..87d90f4013e 100644 --- a/src/site/fml/hapi-fhir-faq.fml +++ b/src/site/fml/hapi-fhir-faq.fml @@ -81,6 +81,23 @@ + + Using HAPI + + + What JDK version does HAPI support? + + +

    + HAPI supports JDK 1.6 for the entire library, except for the CLI tool which is 1.8. +

    +

    + Note that the HAPI library itself also requires a 1.8 JDK to build, since the unit tests + have JDK 1.8 dependencies. +

    +
    +
    +
    JPA Server diff --git a/src/site/xdoc/doc_rest_client_examples.xml b/src/site/xdoc/doc_rest_client_examples.xml index 570b7ef1bbf..91bf9665bb9 100644 --- a/src/site/xdoc/doc_rest_client_examples.xml +++ b/src/site/xdoc/doc_rest_client_examples.xml @@ -53,7 +53,7 @@ - +