diff --git a/hapi-fhir-base/.classpath b/hapi-fhir-base/.classpath index 550e3f2ae04..3e3200180cf 100644 --- a/hapi-fhir-base/.classpath +++ b/hapi-fhir-base/.classpath @@ -6,7 +6,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/hapi-fhir-base/.project b/hapi-fhir-base/.project index ea43e2c9d18..790dcdc0123 100644 --- a/hapi-fhir-base/.project +++ b/hapi-fhir-base/.project @@ -15,26 +15,6 @@ - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder.launch - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (1).launch - - - org.eclipse.jem.workbench.JavaEMFNature diff --git a/hapi-fhir-jpaserver-base/.classpath b/hapi-fhir-jpaserver-base/.classpath index dcca171a6c6..23e1b60a004 100644 --- a/hapi-fhir-jpaserver-base/.classpath +++ b/hapi-fhir-jpaserver-base/.classpath @@ -7,15 +7,15 @@ - + - - - + + + diff --git a/hapi-fhir-jpaserver-base/.project b/hapi-fhir-jpaserver-base/.project index 8f94e87b636..5c22a3e455c 100644 --- a/hapi-fhir-jpaserver-base/.project +++ b/hapi-fhir-jpaserver-base/.project @@ -16,26 +16,6 @@ - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder (1).launch - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.eclipse.m2e.core.maven2Builder (2).launch - - - org.eclipse.jem.workbench.JavaEMFNature 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 75128bbfd60..6b2878a8b98 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 @@ -174,8 +174,7 @@ public abstract class BaseHapiFhirDao implements IDao { RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); for (RuntimeSearchParam nextSpDef : def.getSearchParams()) { - - + if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.REFERENCE) { continue; } @@ -193,7 +192,7 @@ public abstract class BaseHapiFhirDao implements IDao { String[] nextPathsSplit = nextPathsUnsplit.split("\\|"); for (String nextPath : nextPathsSplit) { nextPath = nextPath.trim(); - + List> allowedTypesInField = null; for (Object nextObject : extractValues(nextPath, theResource)) { if (nextObject == null) { @@ -219,7 +218,8 @@ public abstract class BaseHapiFhirDao implements IDao { try { resourceDefinition = getContext().getResourceDefinition(typeString); } catch (DataFormatException e) { - throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextValue.getReference().getValue()); + throw new InvalidRequestException( + "Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextValue.getReference().getValue()); } Class type = resourceDefinition.getImplementingClass(); @@ -253,15 +253,16 @@ public abstract class BaseHapiFhirDao implements IDao { String resName = targetResourceDef.getName(); throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); } - + if (!typeString.equals(target.getResourceType())) { - throw new UnprocessableEntityException("Resource contains reference to " + nextValue.getReference().getValue() + " but resource with ID " + nextValue.getReference().getIdPart() + " is actually of type " + target.getResourceType()); + throw new UnprocessableEntityException("Resource contains reference to " + nextValue.getReference().getValue() + " but resource with ID " + nextValue.getReference().getIdPart() + + " is actually of type " + target.getResourceType()); } - + /* * Is the target type an allowable type of resource for the path where it is referenced? */ - + if (allowedTypesInField == null) { BaseRuntimeChildDefinition childDef = getContext().newTerser().getDefinition(theResource.getClass(), nextPath); if (childDef instanceof RuntimeChildResourceDefinition) { @@ -272,19 +273,19 @@ public abstract class BaseHapiFhirDao implements IDao { allowedTypesInField.add(IBaseResource.class); } } - + boolean acceptableLink = false; - for(Class next : allowedTypesInField) { + for (Class next : allowedTypesInField) { if (next.isAssignableFrom(targetResourceDef.getImplementingClass())) { acceptableLink = true; break; } } - + if (!acceptableLink) { throw new UnprocessableEntityException("Invalid reference found at path '" + nextPath + "'. Resource type '" + targetResourceDef.getName() + "' is not valid for this path"); } - + nextEntity = new ResourceLink(nextPath, theEntity, target); } else { if (!multiType) { @@ -683,11 +684,9 @@ public abstract class BaseHapiFhirDao implements IDao { } /** - * This method is called when an update to an existing resource detects that the resource supplied for update is - * missing a tag/profile/security label that the currently persisted resource holds. + * This method is called when an update to an existing resource detects that the resource supplied for update is missing a tag/profile/security label that the currently persisted resource holds. *

- * The default implementation removes any profile declarations, but leaves tags and security labels in place. - * Subclasses may choose to override and change this behaviour. + * The default implementation removes any profile declarations, but leaves tags and security labels in place. Subclasses may choose to override and change this behaviour. *

* * @param theEntity @@ -695,8 +694,7 @@ public abstract class BaseHapiFhirDao implements IDao { * @param theTag * The tag * @return Retturns true if the tag should be removed - * @see Updates to Tags, Profiles, and Security - * Labels for a description of the logic that the default behaviour folows. + * @see Updates to Tags, Profiles, and Security Labels for a description of the logic that the default behaviour folows. */ protected boolean shouldDroppedTagBeRemovedOnUpdate(ResourceTable theEntity, ResourceTag theTag) { if (theTag.getTag().getTagType() == TagTypeEnum.PROFILE) { @@ -709,6 +707,10 @@ public abstract class BaseHapiFhirDao implements IDao { RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(theResourceType); SearchParameterMap paramMap = translateMatchUrl(theMatchUrl, resourceDef); + + if (paramMap.isEmpty()) { + throw new InvalidRequestException("Invalid match URL[" + theMatchUrl + "] - URL has no search parameters"); + } IFhirResourceDao dao = getDao(theResourceType); Set ids = dao.searchForIdsWithAndOr(paramMap); @@ -719,23 +721,28 @@ public abstract class BaseHapiFhirDao implements IDao { public static SearchParameterMap translateMatchUrl(String theMatchUrl, RuntimeResourceDefinition resourceDef) { SearchParameterMap paramMap = new SearchParameterMap(); List parameters; - try { - String matchUrl = theMatchUrl; - if (matchUrl.indexOf('?') == -1) { - throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: URL does not contain any parameters ('?' not detected)"); - } - matchUrl = matchUrl.replace("|", "%7C"); - matchUrl = matchUrl.replace("=>=", "=%3E%3D"); - matchUrl = matchUrl.replace("=<=", "=%3C%3D"); - matchUrl = matchUrl.replace("=>", "=%3E"); - matchUrl = matchUrl.replace("=<", "=%3C"); - parameters = URLEncodedUtils.parse(new URI(matchUrl), "UTF-8"); - } catch (URISyntaxException e) { - throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - Error was: " + e.toString()); + String matchUrl = theMatchUrl; + int questionMarkIndex = matchUrl.indexOf('?'); + if (questionMarkIndex != -1) { + matchUrl = matchUrl.substring(questionMarkIndex + 1); } + matchUrl = matchUrl.replace("|", "%7C"); + matchUrl = matchUrl.replace("=>=", "=%3E%3D"); + matchUrl = matchUrl.replace("=<=", "=%3C%3D"); + matchUrl = matchUrl.replace("=>", "=%3E"); + matchUrl = matchUrl.replace("=<", "=%3C"); + if (matchUrl.contains(" ")) { + throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - URL is invalid (must not contain spaces)"); + } + + parameters = URLEncodedUtils.parse((matchUrl), Constants.CHARSET_UTF8, '&'); ArrayListMultimap nameToParamLists = ArrayListMultimap.create(); for (NameValuePair next : parameters) { + if (isBlank(next.getValue())) { + continue; + } + String paramName = next.getName(); String qualifier = null; for (int i = 0; i < paramMap.size(); i++) { @@ -779,11 +786,11 @@ public abstract class BaseHapiFhirDao implements IDao { } continue; } - + if (nextParamName.startsWith("_")) { continue; } - + RuntimeSearchParam paramDef = resourceDef.getSearchParam(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); @@ -1030,8 +1037,7 @@ public abstract class BaseHapiFhirDao implements IDao { } } else if (theForHistoryOperation) { /* - * If the create and update times match, this was when the resource was created - * so we should mark it as a POST. Otherwise, it's a PUT. + * If the create and update times match, this was when the resource was created so we should mark it as a POST. Otherwise, it's a PUT. */ Date published = theEntity.getPublished().getValue(); Date updated = theEntity.getUpdated().getValue(); @@ -1041,7 +1047,7 @@ public abstract class BaseHapiFhirDao implements IDao { ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.put(res, BundleEntryTransactionMethodEnum.PUT); } } - + res.setId(theEntity.getIdDt()); ResourceMetadataKeyEnum.VERSION.put(res, Long.toString(theEntity.getVersion())); @@ -1125,8 +1131,9 @@ public abstract class BaseHapiFhirDao implements IDao { } @SuppressWarnings("unchecked") - protected ResourceTable updateEntity(final IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, Date theUpdateTime) { - + protected ResourceTable updateEntity(final IResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, + boolean theUpdateVersion, Date theUpdateTime) { + /* * This should be the very first thing.. */ @@ -1134,14 +1141,15 @@ public abstract class BaseHapiFhirDao implements IDao { validateResourceForStorage((T) theResource, theEntity); String resourceType = myContext.getResourceDefinition(theResource).getName(); if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) { - throw new UnprocessableEntityException("Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]"); + throw new UnprocessableEntityException( + "Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]"); } } if (theEntity.getPublished() == null) { theEntity.setPublished(theUpdateTime); } - + if (theUpdateHistory) { final ResourceHistoryTable historyEntry = theEntity.toHistory(); myEntityManager.persist(historyEntry); @@ -1238,7 +1246,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setResourceLinks(links); theEntity.setHasLinks(links.isEmpty() == false); theEntity.setIndexStatus(INDEX_STATUS_INDEXED); - + } else { populateResourceIntoEntity(theResource, theEntity); @@ -1261,7 +1269,7 @@ public abstract class BaseHapiFhirDao implements IDao { } else { theEntity = myEntityManager.merge(theEntity); - + postUpdate(theEntity, (T) theResource); } @@ -1354,37 +1362,37 @@ public abstract class BaseHapiFhirDao implements IDao { } /** - * Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the - * first time. + * Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the first time. * * @param theEntity * The resource - * @param theResource The resource being persisted + * @param theResource + * The resource being persisted */ protected void postUpdate(ResourceTable theEntity, T theResource) { // nothing } /** - * Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the - * first time. + * Subclasses may override to provide behaviour. Called when a resource has been inserved into the database for the first time. * * @param theEntity * The resource - * @param theResource The resource being persisted + * @param theResource + * The resource being persisted */ protected void postPersist(ResourceTable theEntity, T theResource) { // nothing } /** - * This method is invoked immediately before storing a new resource, or an update to an existing resource to allow - * the DAO to ensure that it is valid for persistence. By default, checks for the "subsetted" tag and rejects - * resources which have it. Subclasses should call the superclass implementation to preserve this check. + * This method is invoked immediately before storing a new resource, or an update to an existing resource to allow the DAO to ensure that it is valid for persistence. By default, checks for the + * "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 - * @param theEntityToSave TODO + * @param theEntityToSave + * TODO */ protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) { IResource res = (IResource) theResource; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java index 580a0a8ad74..873d6270991 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java @@ -56,6 +56,7 @@ import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; import ca.uhn.fhir.model.dstu2.resource.Subscription; import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortSpec; @@ -129,7 +130,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2 toPurge = mySubscriptionTableDao.findInactiveBeforeCutoff(cutoff); for (SubscriptionTable subscriptionTable : toPurge) { final IdDt subscriptionId = subscriptionTable.getSubscriptionResource().getIdDt(); - ourLog.info("Deleting inactive subscription {} - Created {}, last client poll {}", new Object[] { subscriptionId.toUnqualified(), subscriptionTable.getCreated(), subscriptionTable.getLastClientPoll() }); + ourLog.info("Deleting inactive subscription {} - Created {}, last client poll {}", + new Object[] { subscriptionId.toUnqualified(), subscriptionTable.getCreated(), subscriptionTable.getLastClientPoll() }); TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); txTemplate.execute(new TransactionCallback() { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java index e94f476224f..b54426020a9 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java @@ -1,19 +1,32 @@ package ca.uhn.fhir.jpa.dao; +import java.io.IOException; +import java.io.InputStream; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.AfterClass; +import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.rest.server.IBundleProvider; public class BaseJpaTest { + public static String loadClasspath(String resource) throws IOException { + InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream(resource); + if (bundleRes == null) { + throw new NullPointerException("Can not load " + resource); + } + String bundleStr = IOUtils.toString(bundleRes); + return bundleStr; + } + @AfterClass public static void afterClassShutdownDerby() throws SQLException { // try { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java index eccde1dc555..38d2f69887e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu1Test.java @@ -18,7 +18,6 @@ import java.util.Date; import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.AfterClass; @@ -28,7 +27,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.entity.TagTypeEnum; -import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.IResource; @@ -346,8 +344,8 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest { @Test public void testTransactionWithCidIds2() throws Exception { - InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/dstu1_bundle.xml"); - String bundleStr = IOUtils.toString(bundleRes); + String resource = "/dstu1_bundle.xml"; + String bundleStr = loadClasspath(resource); Bundle bundle = ourFhirContext.newXmlParser().parseBundle(bundleStr); List res = new ArrayList(); @@ -363,6 +361,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest { assertThat(encodeResourceToString, not(containsString("smsp"))); } + /** * This is the correct way to do this, not {@link #testTransactionWithCidIds()} */ diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java index 4ab80bb4565..2027d7037ba 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java @@ -44,6 +44,7 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; +import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest; import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryResponse; import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; @@ -354,6 +355,42 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test { } } + @Test + public void testTransactionCreateWithInvalidMatchUrl() { + String methodName = "testTransactionCreateWithInvalidMatchUrl"; + Bundle request = new Bundle(); + + Patient p; + p = new Patient(); + p.addIdentifier().setSystem("urn:system").setValue(methodName); + EntryRequest entry = request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST); + + try { + entry.setIfNoneExist("Patient?identifier identifier" + methodName); + mySystemDao.transaction(request); + fail(); + } catch (InvalidRequestException e) { + assertEquals("Failed to parse match URL[Patient?identifier identifiertestTransactionCreateWithInvalidMatchUrl] - URL is invalid (must not contain spaces)", e.getMessage()); + } + + try { + entry.setIfNoneExist("Patient?identifier="); + mySystemDao.transaction(request); + fail(); + } catch (InvalidRequestException e) { + assertEquals("Invalid match URL[Patient?identifier=] - URL has no search parameters", e.getMessage()); + } + + try { + entry.setIfNoneExist("Patient?foo=bar"); + mySystemDao.transaction(request); + fail(); + } catch (InvalidRequestException e) { + assertEquals("Failed to parse match URL[Patient?foo=bar] - Resource type Patient does not have a parameter with name: foo", e.getMessage()); + } + } + + public void testTransactionCreateWithDuplicateMatchUrl02() { String methodName = "testTransactionCreateWithDuplicateMatchUrl02"; Bundle request = new Bundle(); 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 25a25cff4ce..2142bd27f9a 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 @@ -1619,6 +1619,20 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { } + @Test + public void testTransaction() throws Exception { + String contents = loadClasspath("/update.xml"); + HttpPost post = new HttpPost(ourServerBase); + post.setEntity(new StringEntity(contents, ContentType.create("application/xml+fhir", "UTF-8"))); + CloseableHttpResponse resp = ourHttpClient.execute(post); + try { + assertEquals(200, resp.getStatusLine().getStatusCode()); + String output= IOUtils.toString(resp.getEntity().getContent()); + ourLog.info(output); + } finally { + resp.close(); + } + } @Test public void testUpdateRejectsInvalidTypes() throws InterruptedException { diff --git a/hapi-fhir-jpaserver-base/src/test/resources/update.xml b/hapi-fhir-jpaserver-base/src/test/resources/update.xml new file mode 100644 index 00000000000..d739fa8b378 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/test/resources/update.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + o + + + diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/logback.xml b/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/logback.xml index 652e8e884b3..8f569a59655 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/logback.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/resources/logback.xml @@ -9,6 +9,24 @@ + + + DEBUG + + ${fhir.logdir}/subscription.log + + ${fhir.logdir}/subscription.%i.log.zip + 1 + 10 + + + 5MB + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{req.remoteAddr}] [%X{req.userAgent}] %-5level %logger{36} %msg%n + + + DEBUG @@ -39,19 +57,25 @@ - - - + + + + + + + + + + + - - + + - - - + - + \ No newline at end of file diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 84547808dc1..7754e200f34 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -115,6 +115,11 @@ 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! +