Improved error messages for #305

This commit is contained in:
jamesagnew 2016-03-11 07:56:00 -05:00
parent ed92f64e52
commit 232afee955
38 changed files with 1124 additions and 438 deletions

View File

@ -53,7 +53,7 @@ public class HapiLocalizer {
formatString = "!MESSAGE!";
}
format = new MessageFormat(formatString);
format = new MessageFormat(formatString.trim());
myKeyToMessageFormat.put(theQualifiedKey, format);
return format.format(theParameters).toString();
} else {

View File

@ -170,6 +170,9 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
myUnqualifiedId = theId;
myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionId, null);
myHaveComponentParts = true;
if (isBlank(myBaseUrl) && isBlank(myResourceType) && isBlank(myUnqualifiedId) && isBlank(myUnqualifiedVersionId)) {
myHaveComponentParts = false;
}
}
/**

View File

@ -77,6 +77,8 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public abstract class BaseParser implements IParser {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseParser.class);
private IIdType myEncodeForceResourceId;
private ContainedResources myContainedResources;
private FhirContext myContext;
private Set<String> myEncodeElements;
@ -414,6 +416,11 @@ public abstract class BaseParser implements IParser {
return myEncodeElementsAppliesToResourceTypes;
}
@Override
public IIdType getEncodeForceResourceId() {
return myEncodeForceResourceId;
}
protected IParserErrorHandler getErrorHandler() {
return myErrorHandler;
}
@ -622,6 +629,12 @@ public abstract class BaseParser implements IParser {
}
}
@Override
public BaseParser setEncodeForceResourceId(IIdType theEncodeForceResourceId) {
myEncodeForceResourceId = theEncodeForceResourceId;
return this;
}
@Override
public IParser setOmitResourceId(boolean theOmitResourceId) {
myOmitResourceId = theOmitResourceId;

View File

@ -27,6 +27,7 @@ import java.util.Set;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.model.api.Bundle;
@ -83,6 +84,17 @@ public interface IParser {
*/
Set<String> getEncodeElementsAppliesToResourceTypes();
/**
* If not set to null (as is the default) this ID will be used as the ID in any
* resources encoded by this parser
*/
IIdType getEncodeForceResourceId();
/**
* Which encoding does this parser instance produce?
*/
EncodingEnum getEncoding();
/**
* Returns true if resource IDs should be omitted
*
@ -226,6 +238,11 @@ public interface IParser {
*/
void setEncodeElementsAppliesToResourceTypes(Set<String> theEncodeElementsAppliesToResourceTypes);
/**
* When encoding, force this resource ID to be encoded as the resource ID
*/
IParser setEncodeForceResourceId(IIdType theForceResourceId);
/**
* If set to <code>true</code> (default is <code>false</code>) the ID of any resources being encoded will not be
* included in the output. Note that this does not apply to contained resources, only to root resources. In other
@ -294,10 +311,4 @@ public interface IParser {
* values.
*/
IParser setSuppressNarratives(boolean theSuppressNarratives);
/**
* Which encoding does this parser instance produce?
*/
EncodingEnum getEncoding();
}

View File

@ -93,7 +93,6 @@ import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
@ -800,8 +799,12 @@ public class JsonParser extends BaseParser implements IParser {
}
}
if (isOmitResourceId() && !theContainedResource) {
resourceId = null;
if (!theContainedResource) {
if (isOmitResourceId()) {
resourceId = null;
} else if (getEncodeForceResourceId() != null) {
resourceId = getEncodeForceResourceId();
}
}
encodeResourceToJsonStreamWriter(theResDef, theResource, theEventWriter, theObjectNameOrNull, theContainedResource, resourceId);

View File

@ -80,7 +80,6 @@ import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -787,8 +786,12 @@ public class XmlParser extends BaseParser implements IParser {
}
}
if (isOmitResourceId() && !theIncludedResource) {
resourceId = null;
if (!theIncludedResource) {
if (isOmitResourceId()) {
resourceId = null;
} else if (getEncodeForceResourceId() != null) {
resourceId = getEncodeForceResourceId();
}
}
encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId);

View File

@ -2170,6 +2170,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
if (myId == null) {
myId = myResource.getIdElement();
}
if (myId == null || myId.hasIdPart() == false) {
throw new InvalidRequestException("No ID supplied for resource to update, can not invoke server");
}
@ -2215,7 +2216,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
}
@Override
public IUpdateExecutable withId(IdDt theId) {
public IUpdateExecutable withId(IIdType theId) {
if (theId == null) {
throw new NullPointerException("theId can not be null");
}

View File

@ -1,30 +1,10 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 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 ca.uhn.fhir.model.primitive.IdDt;
import org.hl7.fhir.instance.model.api.IIdType;
public interface IUpdateTyped extends IUpdateExecutable {
IUpdateExecutable withId(IdDt theId);
IUpdateExecutable withId(IIdType theId);
IUpdateExecutable withId(String theId);

View File

@ -28,6 +28,7 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -61,6 +62,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
private final List<? extends IBaseResource> myResources;
private final TagList myTagList;
private final String myUrlPath;
private IIdType myForceResourceId;
public BaseHttpClientInvocationWithContents(FhirContext theContext, Bundle theBundle) {
super(theContext);
@ -73,6 +75,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
myBundleType = null;
}
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
super(theContext);
myResource = theResource;
@ -200,7 +203,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
if (encoding == null) {
encoding = EncodingEnum.XML;
}
String contents = parseContents(thePrettyPrint, encoding);
String contents = encodeContents(thePrettyPrint, encoding);
String contentType = getContentType(encoding);
return httpClient.createByteRequest(getContext(), contents, contentType, encoding);
}
@ -214,7 +217,12 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
}
}
private String parseContents(Boolean thePrettyPrint, EncodingEnum encoding) {
/**
* Get the HTTP request type.
*/
protected abstract RequestTypeEnum getRequestType();
private String encodeContents(Boolean thePrettyPrint, EncodingEnum encoding) {
IParser parser;
if (encoding == EncodingEnum.JSON) {
@ -227,6 +235,10 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
parser.setPrettyPrint(thePrettyPrint);
}
if (myForceResourceId != null) {
parser.setEncodeForceResourceId(myForceResourceId);
}
parser.setOmitResourceId(myOmitResourceId);
if (myTagList != null) {
return parser.encodeTagListToString(myTagList);
@ -249,6 +261,10 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
}
}
public void setForceResourceId(IIdType theId) {
myForceResourceId = theId;
}
public void setIfNoneExistParams(Map<String, List<String>> theIfNoneExist) {
myIfNoneExistParams = theIfNoneExist;
}
@ -261,9 +277,4 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
myOmitResourceId = theOmitResourceId;
}
/**
* Get the HTTP request type.
*/
protected abstract RequestTypeEnum getRequestType();
}

View File

@ -49,13 +49,11 @@ import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.IRestfulServer;
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.util.OperationOutcomeUtil;
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
@ -107,6 +105,17 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
if (getMatchingOperation() != null && !getMatchingOperation().equals(theRequest.getOperation())) {
return false;
}
/*
* Note: Technically this will match an update (PUT) method even if
* there is no ID in the URL - We allow this here because there is no
* better match for that, and this allows the update/PUT method to give
* a helpful error if the client has forgotten to include the
* ID in the URL.
*
* It's also needed for conditional update..
*/
return true;
}

View File

@ -1,5 +1,8 @@
package ca.uhn.fhir.rest.method;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isBlank;
/*
* #%L
* HAPI FHIR - Core Library
@ -28,12 +31,14 @@ import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.ResourceParameter;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
@ -42,6 +47,7 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
private int myResourceParameterIndex = -1;
private Class<? extends IBaseResource> myResourceType;
private Class<? extends IIdType> myIdParamType;
private int myConditionalUrlIndex = -1;
@SuppressWarnings("unchecked")
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
@ -63,6 +69,8 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
myResourceType = resourceParameter.getResourceType();
myResourceParameterIndex = index;
} else if (next instanceof ConditionalParamBinder) {
myConditionalUrlIndex = index;
}
index++;
}
@ -86,30 +94,28 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
}
@Override
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
/*
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
*/
if (myResourceParameterIndex != -1) {
theDetails.setResource((IBaseResource) theMethodParams[myResourceParameterIndex]);
} else {
theDetails.setResource(ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType));
}
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
if (myIdParamIndex != null) {
theParams[myIdParamIndex] = MethodUtil.convertIdToType(theRequest.getId(), myIdParamType);
}
if (myResourceParameterIndex != -1) {
IBaseResource resource = ((IBaseResource) theParams[myResourceParameterIndex]);
String resourceId = resource.getIdElement().getIdPart();
String urlId = theRequest.getId() != null ? theRequest.getId().getIdPart() : null;
if (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
resource.setId(urlId);
} else {
String matchUrl = null;
if (myConditionalUrlIndex != -1) {
matchUrl = (String) theParams[myConditionalUrlIndex];
matchUrl = defaultIfBlank(matchUrl, null);
}
validateResourceIdAndUrlIdForNonConditionalOperation(resourceId, urlId, matchUrl);
}
}
}
@Override
public String getResourceName() {
return myResourceName;
@ -126,4 +132,27 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
return retVal;
}
@Override
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
/*
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
*/
if (myResourceParameterIndex != -1) {
theDetails.setResource((IBaseResource) theMethodParams[myResourceParameterIndex]);
} else {
theDetails.setResource(ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType));
}
}
/**
* Subclasses may override
*/
@SuppressWarnings("unused")
protected void validateResourceIdAndUrlIdForNonConditionalOperation(String theResourceId, String theUrlId, String theMatchUrl) {
// nothing by default
}
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.method;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
* #%L
* HAPI FHIR - Core Library
@ -30,6 +32,7 @@ import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
@ -37,16 +40,6 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
super(theMethod, theContext, Create.class, theProvider);
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.CREATE;
}
@Override
protected Set<RequestTypeEnum> provideAllowableRequestTypes() {
return Collections.singleton(RequestTypeEnum.POST);
}
@Override
protected BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource theResource) {
FhirContext context = getContext();
@ -68,4 +61,26 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
return null;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.CREATE;
}
@Override
protected Set<RequestTypeEnum> provideAllowableRequestTypes() {
return Collections.singleton(RequestTypeEnum.POST);
}
@Override
protected void validateResourceIdAndUrlIdForNonConditionalOperation(String theResourceId, String theUrlId, String theMatchUrl) {
if (isNotBlank(theUrlId)) {
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "idInUrlForCreate", theUrlId);
throw new InvalidRequestException(msg);
}
if (isNotBlank(theResourceId)) {
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "idInBodyForCreate", theResourceId);
throw new InvalidRequestException(msg);
}
}
}

View File

@ -261,6 +261,8 @@ public class MethodUtil {
retVal = new HttpPutClientInvocation(theContext, theResourceBody, false, urlExtension);
}
retVal.setForceResourceId(theId);
if (theId.hasVersionIdPart()) {
if (theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
retVal.addHeader(Constants.HEADER_IF_MATCH, '"' + theId.getVersionIdPart() + '"');

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.rest.method;
import static org.apache.commons.lang3.StringUtils.isBlank;
/*
* #%L
* HAPI FHIR - Core Library
@ -48,11 +49,6 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
myIdParameterIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.UPDATE;
}
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
/*
@ -92,9 +88,13 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
}
}
if (myIdParameterIndex != null) {
theParams[myIdParameterIndex] = theRequest.getId();
}
super.addParametersForServerRequest(theRequest, theParams);
}
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
// TODO Auto-generated method stub
return super.incomingServerRequestMatchesMethod(theRequest);
}
@Override
@ -116,6 +116,16 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
return retVal;
}
@Override
protected String getMatchingOperation() {
return null;
}
@Override
public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.UPDATE;
}
/*
* @Override public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) { if
* (super.incomingServerRequestMatchesMethod(theRequest)) { if (myVersionIdParameterIndex != null) { if
@ -129,8 +139,21 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
}
@Override
protected String getMatchingOperation() {
return null;
protected void validateResourceIdAndUrlIdForNonConditionalOperation(String theResourceId, String theUrlId, String theMatchUrl) {
if (isBlank(theMatchUrl)) {
if (isBlank(theResourceId)) {
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "noIdInBodyForUpdate");
throw new InvalidRequestException(msg);
}
if (isBlank(theUrlId)) {
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "noIdInUrlForUpdate");
throw new InvalidRequestException(msg);
}
if (!theResourceId.equals(theUrlId)) {
String msg = getContext().getLocalizer().getMessage(BaseOutcomeReturningMethodBindingWithResourceParam.class, "incorrectIdForUpdate", theResourceId, theUrlId);
throw new InvalidRequestException(msg);
}
}
}
}

View File

@ -14,6 +14,11 @@ ca.uhn.fhir.rest.client.GenericClient.cannotDetermineResourceTypeFromUri=Unable
ca.uhn.fhir.rest.client.RestfulClientFactory.failedToRetrieveConformance=Failed to retrieve the server's metadata statement during client initialization. URL used was: {0}
ca.uhn.fhir.rest.client.RestfulClientFactory.wrongVersionInConformance=The server at base URL "{0}" returned a conformance statement indicating that it supports FHIR version "{1}" which corresponds to {2}, but this client is configured to use {3} (via the FhirContext).
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.incorrectIdForUpdate=Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of "{0}" does not match URL ID of "{1}"
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.noIdInBodyForUpdate=Can not update resource, resource body must contain an ID element for update (PUT) operation
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.noIdInUrlForUpdate=Can not update resource, request URL must contain an ID element for update (PUT) operation (it must be of the form [base]/[resource type]/[id])
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.idInUrlForCreate=Can not create resource with ID "{0}", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)
ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.idInBodyForCreate=Can not create resource with ID "{0}", an ID element must not be supplied in the resource body on a create (POST) operation
ca.uhn.fhir.rest.method.OperationMethodBinding.methodNotSupported=HTTP Method {0} is not allowed for this operation. Allowed method(s): {1}
ca.uhn.fhir.rest.method.OperationParameter.urlParamNotPrimitive=Can not invoke operation {0} using HTTP GET because parameter {1} is not a primitive datatype
@ -60,8 +65,6 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithInvalidId=Can not
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.incorrectResourceType=Incorrect resource type detected for endpoint, found {0} but expected {1}
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which contain at least one non-numeric character
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.incorrectIdForUpdate=Update failed: resource body ID of "{0}" does not match URL ID of "{1}"
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.missingIdForUpdate=Update failed: resource body does not have an ID
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidParameterChain=Invalid parameter chain: {0}
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidVersion=Version "{0}" is not valid for resource {1}
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true

View File

@ -33,13 +33,13 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsResponseException;
import ca.uhn.fhir.jaxrs.server.test.RandomServerPortProvider;
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsConformanceRestProvider;
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPageProvider;
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProvider;
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
@ -68,59 +68,64 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AbstractJaxRsResourceProviderTest {
private TestJaxRsMockPatientRestProvider mock;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AbstractJaxRsResourceProviderTest.class);
private ArgumentCaptor<IdDt> idCaptor;
private ArgumentCaptor<Patient> patientCaptor;
private static IGenericClient client;
private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final String PATIENT_NAME = "Van Houte";
private static int ourPort;
private static String serverBase;
private static Server jettyServer;
private TestJaxRsMockPatientRestProvider mock;
private ArgumentCaptor<IdDt> idCaptor;
private ArgumentCaptor<Patient> patientCaptor;
@BeforeClass
public static void setUpClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
System.out.println(ourPort);
jettyServer = new Server(ourPort);
jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
//@formatter:off
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
StringUtils.join(Arrays.asList(
TestJaxRsMockPatientRestProvider.class.getCanonicalName(),
JaxRsExceptionInterceptor.class.getCanonicalName(),
TestJaxRsConformanceRestProvider.class.getCanonicalName(),
TestJaxRsMockPageProvider.class.getCanonicalName()
), ";"));
//@formatter:on
jettyServer.start();
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
serverBase = "http://localhost:" + ourPort + "/";
client = ourCtx.newRestfulGenericClient(serverBase);
client.setEncoding(EncodingEnum.JSON);
client.registerInterceptor(new LoggingInterceptor(true));
private void compareResultId(int id, IResource resource) {
assertEquals(id, resource.getId().getIdPartAsLong().intValue());
}
@AfterClass
public static void tearDownClass() throws Exception {
try {
jettyServer.destroy();
} catch (Exception e) {
private void compareResultUrl(String url, IResource resource) {
assertEquals(url, resource.getId().getValueAsString().substring(serverBase.length() - 1));
}
private Patient createPatient(long id) {
Patient theResource = new Patient();
theResource.setId(new IdDt(id));
return theResource;
}
private List<Patient> createPatients(int firstId, int lastId) {
List<Patient> result = new ArrayList<Patient>(lastId - firstId);
for (long i = firstId; i <= lastId; i++) {
result.add(createPatient(i));
}
return result;
}
/** Find By Id */
@Test
public void findUsingGenericClientById() {
when(mock.find(any(IdDt.class))).thenReturn(createPatient(1));
Patient result = client.read(Patient.class, "1");
compareResultId(1, result);
compareResultUrl("/Patient/1", result);
reset(mock);
when(mock.find(withId(result.getId()))).thenReturn(createPatient(1));
result = (Patient) client.read(new UriDt(result.getId().getValue()));
compareResultId(1, result);
compareResultUrl("/Patient/1", result);
}
private Bundle getPatientBundle(int size) {
Bundle result = new Bundle();
for (long i = 0; i < size; i++) {
Patient patient = createPatient(i);
Entry entry = new Entry().setResource(patient);
result.addEntry(entry);
}
return result;
}
@Before
@ -131,6 +136,130 @@ public class AbstractJaxRsResourceProviderTest {
reset(mock);
}
/** Conditional Creates */
@Test
public void testConditionalCreate() throws Exception {
Patient toCreate = createPatient(1);
MethodOutcome outcome = new MethodOutcome();
toCreate.getIdentifierFirstRep().setValue("myIdentifier");
outcome.setResource(toCreate);
when(mock.create(patientCaptor.capture(), eq("Patient?_format=json&identifier=2"))).thenReturn(outcome);
client.setEncoding(EncodingEnum.JSON);
MethodOutcome response = client.create().resource(toCreate).conditional()
.where(Patient.IDENTIFIER.exactly().identifier("2")).prefer(PreferReturnEnum.REPRESENTATION).execute();
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifierFirstRep().getValue());
IResource resource = (IResource) response.getResource();
compareResultId(1, resource);
}
/** Conformance - Server */
@Test
public void testConformance() {
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
assertEquals(conf.getRest().get(0).getResource().get(0).getType().toString(), "Patient");
}
@Test
public void testCreatePatient() throws Exception {
Patient toCreate = createPatient(1);
MethodOutcome outcome = new MethodOutcome();
toCreate.getIdentifierFirstRep().setValue("myIdentifier");
outcome.setResource(toCreate);
when(mock.create(patientCaptor.capture(), isNull(String.class))).thenReturn(outcome);
client.setEncoding(EncodingEnum.JSON);
final MethodOutcome response = client.create().resource(toCreate).prefer(PreferReturnEnum.REPRESENTATION)
.execute();
IResource resource = (IResource) response.getResource();
compareResultId(1, resource);
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifierFirstRep().getValue());
}
@Test
public void testDeletePatient() {
when(mock.delete(idCaptor.capture())).thenReturn(new MethodOutcome());
final BaseOperationOutcome results = client.delete().resourceById("Patient", "1").execute();
assertEquals("1", idCaptor.getValue().getIdPart());
}
/** Extended Operations */
@Test
public void testExtendedOperations() {
// prepare mock
Parameters resultParameters = new Parameters();
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringDt("outputValue"));
when(mock.someCustomOperation(any(IdDt.class), eq(new StringDt("myAwesomeDummyValue")))).thenReturn(resultParameters);
// Create the input parameters to pass to the server
Parameters inParams = new Parameters();
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
//invoke
Parameters outParams = client.operation().onInstance(new IdDt("Patient", "1")).named("$someCustomOperation")
.withParameters(inParams).execute();
//verify
assertEquals("outputValue", ((StringDt)outParams.getParameter().get(0).getValue()).getValueAsString());
}
@Test
public void testExtendedOperationsUsingGet() {
// prepare mock
Parameters resultParameters = new Parameters();
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringDt("outputValue"));
when(mock.someCustomOperation(any(IdDt.class), eq(new StringDt("myAwesomeDummyValue")))).thenReturn(resultParameters);
// Create the input parameters to pass to the server
Parameters inParams = new Parameters();
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
// invoke
Parameters outParams = client.operation().onInstance(new IdDt("Patient", "1")).named("$someCustomOperation")
.withParameters(inParams).useHttpGet().execute();
// verify
assertEquals("outputValue", ((StringDt)outParams.getParameter().get(0).getValue()).getValueAsString());
}
/** Search using other query options */
public void testOther() {
// missing
}
@Test
public void testRead() {
when(mock.find(idCaptor.capture())).thenReturn(createPatient(1));
final Patient patient = client.read(Patient.class, "1");
compareResultId(1, patient);
compareResultUrl("/Patient/1", patient);
assertEquals("1", idCaptor.getValue().getIdPart());
}
/** Search - Compartments */
@Test
public void testSearchCompartements() {
when(mock.searchCompartment(any(IdDt.class))).thenReturn(Arrays.asList((IResource) createPatient(1)));
Bundle response = client.search().forResource(Patient.class).withIdAndCompartment("1", "Condition")
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).execute();
IResource resource = response.getEntry().get(0).getResource();
compareResultId(1, resource);
compareResultUrl("/Patient/1", resource);
}
/** */
@Test
public void testSearchPost() {
when(mock.search(any(StringParam.class), Matchers.isNull(StringAndListParam.class)))
.thenReturn(createPatients(1, 13));
Bundle result = client.search().forResource("Patient").usingStyle(SearchStyleEnum.POST)
.returnBundle(Bundle.class).execute();
IResource resource = result.getEntry().get(0).getResource();
compareResultId(1, resource);
compareResultUrl("/Patient/1", resource);
}
/** Search/Query - Type */
@Test
public void testSearchUsingGenericClientBySearch() {
@ -189,34 +318,6 @@ public class AbstractJaxRsResourceProviderTest {
assertNull(nextPage.getLink(Bundle.LINK_NEXT));
}
/** Search using other query options */
public void testOther() {
// missing
}
/** */
@Test
public void testSearchPost() {
when(mock.search(any(StringParam.class), Matchers.isNull(StringAndListParam.class)))
.thenReturn(createPatients(1, 13));
Bundle result = client.search().forResource("Patient").usingStyle(SearchStyleEnum.POST)
.returnBundle(Bundle.class).execute();
IResource resource = result.getEntry().get(0).getResource();
compareResultId(1, resource);
compareResultUrl("/Patient/1", resource);
}
/** Search - Compartments */
@Test
public void testSearchCompartements() {
when(mock.searchCompartment(any(IdDt.class))).thenReturn(Arrays.asList((IResource) createPatient(1)));
Bundle response = client.search().forResource(Patient.class).withIdAndCompartment("1", "Condition")
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).execute();
IResource resource = response.getEntry().get(0).getResource();
compareResultId(1, resource);
compareResultUrl("/Patient/1", resource);
}
/** Search - Subsetting (_summary and _elements) */
@Test
@Ignore
@ -225,70 +326,6 @@ public class AbstractJaxRsResourceProviderTest {
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).execute();
}
@Test
public void testCreatePatient() throws Exception {
Patient toCreate = createPatient(1);
MethodOutcome outcome = new MethodOutcome();
toCreate.getIdentifierFirstRep().setValue("myIdentifier");
outcome.setResource(toCreate);
when(mock.create(patientCaptor.capture(), isNull(String.class))).thenReturn(outcome);
client.setEncoding(EncodingEnum.JSON);
final MethodOutcome response = client.create().resource(toCreate).prefer(PreferReturnEnum.REPRESENTATION)
.execute();
IResource resource = (IResource) response.getResource();
compareResultId(1, resource);
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifierFirstRep().getValue());
}
/** Conditional Creates */
@Test
public void testConditionalCreate() throws Exception {
Patient toCreate = createPatient(1);
MethodOutcome outcome = new MethodOutcome();
toCreate.getIdentifierFirstRep().setValue("myIdentifier");
outcome.setResource(toCreate);
when(mock.create(patientCaptor.capture(), eq("Patient?_format=json&identifier=2"))).thenReturn(outcome);
client.setEncoding(EncodingEnum.JSON);
MethodOutcome response = client.create().resource(toCreate).conditional()
.where(Patient.IDENTIFIER.exactly().identifier("2")).prefer(PreferReturnEnum.REPRESENTATION).execute();
assertEquals("myIdentifier", patientCaptor.getValue().getIdentifierFirstRep().getValue());
IResource resource = (IResource) response.getResource();
compareResultId(1, resource);
}
/** Find By Id */
@Test
public void findUsingGenericClientById() {
when(mock.find(any(IdDt.class))).thenReturn(createPatient(1));
Patient result = client.read(Patient.class, "1");
compareResultId(1, result);
compareResultUrl("/Patient/1", result);
reset(mock);
when(mock.find(withId(result.getId()))).thenReturn(createPatient(1));
result = (Patient) client.read(new UriDt(result.getId().getValue()));
compareResultId(1, result);
compareResultUrl("/Patient/1", result);
}
@Test
public void testUpdateById() throws Exception {
when(mock.update(idCaptor.capture(), patientCaptor.capture())).thenReturn(new MethodOutcome());
client.update("1", createPatient(2));
assertEquals("1", idCaptor.getValue().getIdPart());
compareResultId(1, patientCaptor.getValue());
}
@Test
public void testDeletePatient() {
when(mock.delete(idCaptor.capture())).thenReturn(new MethodOutcome());
final BaseOperationOutcome results = client.delete().resourceById("Patient", "1").execute();
assertEquals("1", idCaptor.getValue().getIdPart());
}
/** Transaction - Server */
@Ignore
@Test
@ -305,49 +342,21 @@ public class AbstractJaxRsResourceProviderTest {
ca.uhn.fhir.model.api.Bundle response = client.transaction().withBundle(bundle).execute();
}
/** Conformance - Server */
@Test
public void testConformance() {
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
assertEquals(conf.getRest().get(0).getResource().get(0).getType().toString(), "Patient");
}
/** Extended Operations */
@Test
public void testExtendedOperations() {
// prepare mock
Parameters resultParameters = new Parameters();
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringDt("outputValue"));
when(mock.someCustomOperation(any(IdDt.class), eq(new StringDt("myAwesomeDummyValue")))).thenReturn(resultParameters);
// Create the input parameters to pass to the server
Parameters inParams = new Parameters();
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
//invoke
Parameters outParams = client.operation().onInstance(new IdDt("Patient", "1")).named("$someCustomOperation")
.withParameters(inParams).execute();
//verify
assertEquals("outputValue", ((StringDt)outParams.getParameter().get(0).getValue()).getValueAsString());
public void testUpdateById() throws Exception {
when(mock.update(idCaptor.capture(), patientCaptor.capture())).thenReturn(new MethodOutcome());
client.update("1", createPatient(1));
assertEquals("1", idCaptor.getValue().getIdPart());
compareResultId(1, patientCaptor.getValue());
}
@Test
public void testExtendedOperationsUsingGet() {
// prepare mock
Parameters resultParameters = new Parameters();
resultParameters.addParameter().setName("return").setResource(createPatient(1)).setValue(new StringDt("outputValue"));
when(mock.someCustomOperation(any(IdDt.class), eq(new StringDt("myAwesomeDummyValue")))).thenReturn(resultParameters);
// Create the input parameters to pass to the server
Parameters inParams = new Parameters();
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
// invoke
Parameters outParams = client.operation().onInstance(new IdDt("Patient", "1")).named("$someCustomOperation")
.withParameters(inParams).useHttpGet().execute();
// verify
assertEquals("outputValue", ((StringDt)outParams.getParameter().get(0).getValue()).getValueAsString());
@Ignore
public void testUpdateByWrongId() throws Exception {
when(mock.update(idCaptor.capture(), patientCaptor.capture())).thenReturn(new MethodOutcome());
client.update("1", createPatient(2));
assertEquals("1", idCaptor.getValue().getIdPart());
compareResultId(1, patientCaptor.getValue());
}
@Test
@ -360,15 +369,6 @@ public class AbstractJaxRsResourceProviderTest {
assertEquals("2", idCaptor.getValue().getVersionIdPart());
}
@Test
public void testRead() {
when(mock.find(idCaptor.capture())).thenReturn(createPatient(1));
final Patient patient = client.read(Patient.class, "1");
compareResultId(1, patient);
compareResultUrl("/Patient/1", patient);
assertEquals("1", idCaptor.getValue().getIdPart());
}
@Test
public void testXFindUnknownPatient() {
try {
@ -382,40 +382,12 @@ public class AbstractJaxRsResourceProviderTest {
}
}
private Bundle getPatientBundle(int size) {
Bundle result = new Bundle();
for (long i = 0; i < size; i++) {
Patient patient = createPatient(i);
Entry entry = new Entry().setResource(patient);
result.addEntry(entry);
}
return result;
}
private List<Patient> createPatients(int firstId, int lastId) {
List<Patient> result = new ArrayList<Patient>(lastId - firstId);
for (long i = firstId; i <= lastId; i++) {
result.add(createPatient(i));
}
return result;
}
private Patient createPatient(long id) {
Patient theResource = new Patient();
theResource.setId(new IdDt(id));
return theResource;
}
private void compareResultId(int id, IResource resource) {
assertEquals(id, resource.getId().getIdPartAsLong().intValue());
}
private void compareResultUrl(String url, IResource resource) {
assertEquals(url, resource.getId().getValueAsString().substring(serverBase.length() - 1));
}
private <T> T withId(final T id) {
return argThat(new BaseMatcher<T>() {
@Override
public void describeTo(Description arg0) {
}
@Override
public boolean matches(Object other) {
IdDt thisId;
@ -429,11 +401,48 @@ public class AbstractJaxRsResourceProviderTest {
}
return thisId.getIdPartAsLong().equals(otherId.getIdPartAsLong());
}
@Override
public void describeTo(Description arg0) {
}
});
}
@BeforeClass
public static void setUpClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
System.out.println(ourPort);
jettyServer = new Server(ourPort);
jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
//@formatter:off
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
StringUtils.join(Arrays.asList(
TestJaxRsMockPatientRestProvider.class.getCanonicalName(),
JaxRsExceptionInterceptor.class.getCanonicalName(),
TestJaxRsConformanceRestProvider.class.getCanonicalName(),
TestJaxRsMockPageProvider.class.getCanonicalName()
), ";"));
//@formatter:on
jettyServer.start();
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
serverBase = "http://localhost:" + ourPort + "/";
client = ourCtx.newRestfulGenericClient(serverBase);
client.setEncoding(EncodingEnum.JSON);
client.registerInterceptor(new LoggingInterceptor(true));
}
@AfterClass
public static void tearDownClass() throws Exception {
try {
jettyServer.destroy();
} catch (Exception e) {
}
}
}

View File

@ -971,15 +971,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return create(theResource, null, thePerformIndexing, theRequestDetails);
}
} else {
/* Note: resourcdeId will not be null or empty here, because
* we check it and reject requests in BaseOutcomeReturningMethodBindingWithResourceParam
*/
//
resourceId = theResource.getIdElement();
if (resourceId == null || isBlank(resourceId.getIdPart())) {
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "missingIdForUpdate");
throw new InvalidRequestException(msg);
}
if (!theResource.getIdElement().getIdPart().equals(theRequestDetails.getId().getIdPart())) {
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "incorrectIdForUpdate", theResource.getIdElement().getIdPart(), theRequestDetails.getId().getIdPart());
throw new InvalidRequestException(msg);
}
try {
entity = readEntityLatestVersion(resourceId);

View File

@ -38,6 +38,7 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Test;
@ -486,11 +487,11 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertEquals(400, response.getStatusLine().getStatusCode());
String respString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(respString);
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
assertThat(respString, containsString("Can not create resource with ID[2], ID must not be supplied on a create (POST) operation"));
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
} finally {
response.getEntity().getContent().close();
response.close();
@ -2017,9 +2018,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("<pre>Can not update a resource with no ID</pre>"));
assertThat(responseString, containsString("<OperationOutcome"));
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertThat(oo.getIssue().get(0).getDiagnostics(), containsString("Can not update resource, resource body must contain an ID element for update (PUT) operation"));
} finally {
response.close();
}
@ -2110,6 +2111,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
Date before = new Date();
Thread.sleep(100);
pt.setId(id);
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient/" + id.getIdPart());
put.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + '=' + Constants.HEADER_PREFER_RETURN_REPRESENTATION);
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));

View File

@ -483,18 +483,19 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
@Test
public void testCreateResourceWithNumericId() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"><id value=\"2\"/></Patient>";
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertEquals(400, response.getStatusLine().getStatusCode());
String respString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(respString);
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
assertThat(respString, containsString("Can not create resource with ID[2], ID must not be supplied on a create (POST) operation"));
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
} finally {
response.getEntity().getContent().close();
response.close();
@ -2099,7 +2100,30 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("Can not update a resource with no ID"));
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertThat(oo.getIssue().get(0).getDiagnostics(), containsString("Can not update resource, resource body must contain an ID element for update (PUT) operation"));
} finally {
response.close();
}
}
@Test
public void testUpdateInvalidReference2() throws IOException, Exception {
String methodName = "testUpdateInvalidReference2";
Patient pt = new Patient();
pt.setId("2");
pt.addName().addFamily(methodName);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut post = new HttpPut(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("Can not update resource, request URL must contain an ID element for update (PUT) operation (it must be of the form [base]/[resource type]/[id])"));
assertThat(responseString, containsString("<OperationOutcome"));
assertEquals(400, response.getStatusLine().getStatusCode());
} finally {
@ -2107,6 +2131,51 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
}
@Test
public void testUpdateNoIdInBody() throws IOException, Exception {
String methodName = "testUpdateNoIdInBody";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut post = new HttpPut(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertThat(responseString, containsString("Can not update resource, resource body must contain an ID element for update (PUT) operation"));
assertThat(responseString, containsString("<OperationOutcome"));
assertEquals(400, response.getStatusLine().getStatusCode());
} finally {
response.close();
}
}
@Test
public void testUpdateWrongIdInBody() throws IOException, Exception {
String methodName = "testUpdateWrongIdInBody";
Patient pt = new Patient();
pt.setId("333");
pt.addName().addFamily(methodName);
String resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut post = new HttpPut(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(responseString);
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertThat(oo.getIssue().get(0).getDiagnostics(), containsString("Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"333\" does not match URL ID of \"2\""));
} finally {
response.close();
}
}
@Test
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
@ -2116,6 +2185,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
IdType p1id = (IdType) ourClient.create().resource(p1).execute().getId();
Organization p2 = new Organization();
p2.setId(p1id.getIdPart());
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
try {
ourClient.update().resource(p2).withId("Organization/" + p1id.getIdPart()).execute();
@ -2155,7 +2225,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
try {
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newJsonParser().parseResource(OperationOutcome.class, new InputStreamReader(response.getEntity().getContent()));
assertEquals("Update failed: resource body ID of \"FOO\" does not match URL ID of \"" + p1id.getIdPart() + "\"", oo.getIssue().get(0).getDiagnostics());
assertEquals("Can not update resource, resource body must contain an ID element which matches the request URL for update (PUT) operation - Resource body ID of \"FOO\" does not match URL ID of \""+p1id.getIdPart()+"\"", oo.getIssue().get(0).getDiagnostics());
} finally {
response.close();
}
@ -2171,7 +2241,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
try {
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newJsonParser().parseResource(OperationOutcome.class, new InputStreamReader(response.getEntity().getContent()));
assertEquals("Update failed: resource body does not have an ID", oo.getIssue().get(0).getDiagnostics());
assertEquals("Can not update resource, resource body must contain an ID element for update (PUT) operation", oo.getIssue().get(0).getDiagnostics());
} finally {
response.close();
}
@ -2251,6 +2321,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
Date before = new Date();
Thread.sleep(100);
pt = new Patient();
pt.setId(id.getIdPart());
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient/" + id.getIdPart());
put.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RETURN + '=' + Constants.HEADER_PREFER_RETURN_REPRESENTATION);
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -2276,6 +2350,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
public void testUpdateWithClientSuppliedIdWhichDoesntExist() {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2");
MethodOutcome outcome = ourClient.update().resource(p1).withId("testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2").execute();
assertEquals(true, outcome.getCreated().booleanValue());
IdType p1Id = (IdType) outcome.getId();

View File

@ -55,7 +55,7 @@ public class JpaServerDemo extends RestfulServer {
myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext();
/*
* The hapi-fhir-server-resourceproviders-dev.xml file is a spring configuration
* The BaseJavaConfigDstu2.java class is a spring configuration
* file which is automatically generated as a part of hapi-fhir-jpaserver-base and
* contains bean definitions for a resource provider for each resource type
*/

View File

@ -31,6 +31,12 @@ public class IdDtTest {
assertFalse(new IdDt(StringUtils.leftPad("", 65, '0')).isIdPartValid());
}
@Test
public void testConstructorsWithNullArguments() {
IdDt id = new IdDt(null, null, null);
assertEquals(null, id.getValue());
}
@Test
public void testDetectLocal() {
IdDt id;

View File

@ -74,7 +74,6 @@ public class UpdateTest {
}
@Test
public void testUpdateWhichReturnsCreate() throws Exception {
@ -123,23 +122,30 @@ public class UpdateTest {
public void testUpdateNoResponse() throws Exception {
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.addCodedDiagnosis().addCoding().setCode("AAA");
String encoded = ourCtx.newXmlParser().encodeResourceToString(dr);
ourLog.info("OUT: {}", encoded);
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("location").getValue());
IOUtils.closeQuietly(status.getEntity().getContent());
try {
ourLog.info(IOUtils.toString(status.getEntity().getContent()));
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("location").getValue());
} finally {
IOUtils.closeQuietly(status.getEntity().getContent());
}
}
@Test
public void testUpdateWithTagMultiple() throws Exception {
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.addCodedDiagnosis().addCoding().setCode("AAA");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
@ -159,8 +165,8 @@ public class UpdateTest {
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(2, ourReportProvider.getLastTags().size());
assertEquals(new Tag("urn:animals", "Dog", "aa"), ourReportProvider.getLastTags().get(0));
assertEquals(new Tag("urn:animals", "Cat", "bb"), ourReportProvider.getLastTags().get(1));
assertEquals(new Tag("urn:animals", "Dog", "aa"), ourReportProvider.getLastTags().get(0));
assertEquals(new Tag("urn:animals", "Cat", "bb"), ourReportProvider.getLastTags().get(1));
}
@ -168,6 +174,7 @@ public class UpdateTest {
public void testUpdateWithTagSimple() throws Exception {
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.addCodedDiagnosis().addCoding().setCode("AAA");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
@ -185,6 +192,7 @@ public class UpdateTest {
public void testUpdateWithTagWithScheme() throws Exception {
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.addCodedDiagnosis().addCoding().setCode("AAA");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
@ -211,6 +219,7 @@ public class UpdateTest {
public void testUpdateWithTagWithSchemeAndLabel() throws Exception {
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.addCodedDiagnosis().addCoding().setCode("AAA");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
@ -224,7 +233,7 @@ public class UpdateTest {
httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; scheme=\"http://foo\"; label=\"aaaa\"; ");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
status=ourClient.execute(httpPost);
status = ourClient.execute(httpPost);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(1, ourReportProvider.getLastTags().size());
@ -235,12 +244,13 @@ public class UpdateTest {
@Test
public void testUpdateWithVersion() throws Exception {
DiagnosticReport patient = new DiagnosticReport();
patient.getIdentifier().setValue("001");
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.getIdentifier().setValue("001");
HttpPut httpPut = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPut.addHeader("Content-Location", "/DiagnosticReport/001/_history/004");
httpPut.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
httpPut.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPut);
IOUtils.closeQuietly(status.getEntity().getContent());
@ -257,12 +267,13 @@ public class UpdateTest {
@Test()
public void testUpdateWithVersionBadContentLocationHeader() throws Exception {
DiagnosticReport patient = new DiagnosticReport();
patient.getIdentifier().setValue("001");
DiagnosticReport dr = new DiagnosticReport();
dr.setId("001");
dr.getIdentifier().setValue("001");
HttpPut httpPut = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPut.addHeader("Content-Location", "/Patient/001/_history/002");
httpPut.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
httpPut.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse status = ourClient.execute(httpPut);
String responseContent = IOUtils.toString(status.getEntity().getContent());
@ -289,14 +300,15 @@ public class UpdateTest {
fail();
}
@Test
@Test
public void testUpdateWithNoReturn() throws Exception {
Organization patient = new Organization();
patient.addIdentifier().setValue("002");
Organization dr = new Organization();
dr.setId("001");
dr.addIdentifier().setValue("002");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Organization/001");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse status = ourClient.execute(httpPost);
IOUtils.closeQuietly(status.getEntity().getContent());
@ -305,7 +317,6 @@ public class UpdateTest {
status.close();
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
@ -335,9 +346,7 @@ public class UpdateTest {
}
public static class OrganizationResourceProvider implements IResourceProvider
{
public static class OrganizationResourceProvider implements IResourceProvider {
@Override
public Class<? extends IResource> getResourceType() {
@ -364,7 +373,6 @@ public class UpdateTest {
return DiagnosticReport.class;
}
@Update()
public MethodOutcome updateDiagnosticReportWithVersionAndNoResponse(@IdParam IdDt theId, @ResourceParam DiagnosticReport theDr) {
IdDt id = theId;
@ -380,7 +388,7 @@ public class UpdateTest {
}
public static class ObservationProvider implements IResourceProvider{
public static class ObservationProvider implements IResourceProvider {
@Override
public Class<? extends IResource> getResourceType() {
@ -390,7 +398,8 @@ public class UpdateTest {
@Update()
public MethodOutcome updateDiagnosticReportWithVersion(@IdParam IdDt theId, @ResourceParam DiagnosticOrder thePatient) {
/*
* TODO: THIS METHOD IS NOT USED. It's the wrong type (DiagnosticOrder), so it should cause an exception on startup. Also we should detect if there are multiple resource params on an
* TODO: THIS METHOD IS NOT USED. It's the wrong type (DiagnosticOrder), so it should cause an exception on
* startup. Also we should detect if there are multiple resource params on an
* update/create/etc method
*/
IdDt id = theId;
@ -398,7 +407,6 @@ public class UpdateTest {
}
}
public static class PatientProvider implements IResourceProvider {
@Override
@ -406,18 +414,16 @@ public class UpdateTest {
return Patient.class;
}
@Update()
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
IdDt id = theId.withVersion(thePatient.getIdentifierFirstRep().getValue().getValue());
OperationOutcome oo = new OperationOutcome();
oo.addIssue().setDetails("OODETAILS");
if (theId.getValueAsString().contains("CREATE")) {
return new MethodOutcome(id,oo, true);
return new MethodOutcome(id, oo, true);
}
return new MethodOutcome(id,oo);
return new MethodOutcome(id, oo);
}
}

View File

@ -400,6 +400,22 @@ public class JsonParserDstu2Test {
assertThat(encoded, not(containsString("Label")));
}
@Test
public void testEncodeForceResourceId() {
Patient p = new Patient();
p.setId("111");
p.addName().addGiven("GIVEN");
IParser parser = ourCtx.newJsonParser();
parser.setEncodeForceResourceId(new IdDt("222"));
String encoded = parser.encodeResourceToString(p);
ourLog.info(encoded);
assertThat(encoded, containsString("222"));
assertThat(encoded, not(containsString("111")));
}
@Test
public void testEncodeNarrativeSuppressed() throws Exception {
Patient patient = new Patient();

View File

@ -130,7 +130,6 @@ public class XmlParserDstu2Test {
}
@Test
public void testChoiceTypeWithProfiledType() {
//@formatter:off
@ -168,7 +167,6 @@ public class XmlParserDstu2Test {
assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass());
}
@Test
public void testContainedResourceInExtensionUndeclared() {
Patient p = new Patient();
@ -374,11 +372,9 @@ public class XmlParserDstu2Test {
String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(enc, containsString(
"<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString(
"<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/*
* Now parse this back
@ -786,10 +782,8 @@ public class XmlParserDstu2Test {
ourLog.info(encoded);
// @formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -821,10 +815,8 @@ public class XmlParserDstu2Test {
ourLog.info(encoded);
//@formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -859,10 +851,8 @@ public class XmlParserDstu2Test {
ourLog.info(encoded);
//@formatter:on
assertThat(encoded,
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
"</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off
}
@ -965,6 +955,22 @@ public class XmlParserDstu2Test {
}
@Test
public void testEncodeForceResourceId() {
Patient p = new Patient();
p.setId("111");
p.addName().addGiven("GIVEN");
IParser parser = ourCtx.newXmlParser();
parser.setEncodeForceResourceId(new IdDt("222"));
String encoded = parser.encodeResourceToString(p);
ourLog.info(encoded);
assertThat(encoded, containsString("222"));
assertThat(encoded, not(containsString("111")));
}
@Test
public void testEncodeNarrativeSuppressed() {
Patient patient = new Patient();
@ -1647,7 +1653,7 @@ public class XmlParserDstu2Test {
exts = ext.getUndeclaredExtensionsByUrl("http://my.fancy.extension.url");
assertEquals(1, exts.size());
ext = exts.get(0);
assertEquals("myNestedValue", ((StringDt)ext.getValue()).getValue());
assertEquals("myNestedValue", ((StringDt) ext.getValue()).getValue());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
ourLog.info(encoded);
@ -1688,7 +1694,6 @@ public class XmlParserDstu2Test {
}
@Test
public void testParseBundleNewWithPlaceholderIdsInBase1() {
//@formatter:off

View File

@ -97,7 +97,7 @@ public class CreateConditionalTest {
Patient patient = new Patient();
patient.addIdentifier().setValue("002");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2?_format=true&_pretty=true");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient?_format=true&_pretty=true");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
@ -111,8 +111,8 @@ public class CreateConditionalTest {
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue());
assertEquals("Patient/2", ourLastId.toUnqualified().getValue());
assertEquals("Patient/2", ourLastIdParam.toUnqualified().getValue());
assertEquals(null, ourLastId.toUnqualified().getValue());
assertEquals(null, ourLastIdParam);
assertNull(ourLastConditionalUrl);
}

View File

@ -112,6 +112,7 @@ public class ETagServerTest {
@Test
public void testUpdateWithNoVersion() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);
@ -127,6 +128,7 @@ public class ETagServerTest {
@Test
public void testUpdateWithIfMatch() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);
@ -144,6 +146,7 @@ public class ETagServerTest {
@Test
public void testUpdateWithIfMatchPreconditionFailed() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);

View File

@ -1,7 +1,8 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
@ -26,13 +27,6 @@ import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -99,6 +93,7 @@ public class UpdateConditionalTest {
public void testUpdateWithoutConditionalUrl() throws Exception {
Patient patient = new Patient();
patient.setId("2");
patient.addIdentifier().setValue("002");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/2");

View File

@ -13,7 +13,7 @@
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry including="**/*.java" kind="src" path="src/test/resources"/>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>

View File

@ -208,6 +208,9 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
myUnqualifiedId = theId;
myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionId, null);
myHaveComponentParts = true;
if (isBlank(myBaseUrl) && isBlank(myResourceType) && isBlank(myUnqualifiedId) && isBlank(myUnqualifiedVersionId)) {
myHaveComponentParts = false;
}
}
/**

View File

@ -0,0 +1,232 @@
package ca.uhn.fhir.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Reference;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
public class IdTypeDstu3Test {
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeDstu3Test.class);
@Test
public void testDetectLocal() {
IdType id;
id = new IdType("#123");
assertEquals("#123", id.getValue());
assertTrue(id.isLocal());
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
assertTrue(id.isLocal());
id = new IdType("http://example.com/Patient/33#123");
assertEquals("http://example.com/Patient/33#123", id.getValue());
assertFalse(id.isLocal());
}
@Test
public void testConstructorsWithNullArguments() {
IdType id = new IdType(null, null, null);
assertEquals(null, id.getValue());
}
@Test
public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("urn:uuid:", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("cid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("cid:", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("cid:180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());
assertEquals("#", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
assertEquals("180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
}
/**
* See #67
*/
@Test
public void testComplicatedLocal() {
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
assertTrue(id.isLocal());
assertEquals("#", id.getBaseUrl());
assertNull(id.getResourceType());
assertNull(id.getVersionIdPart());
assertEquals("Patient/cid:Patient-72/_history/1", id.getIdPart());
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
assertEquals(id, id2);
id2 = id2.toUnqualified();
assertFalse(id2.isLocal());
assertNull(id2.getBaseUrl());
assertNull(id2.getResourceType());
assertNull(id2.getVersionIdPart());
assertEquals("Patient/cid:Patient-72/_history/1", id2.getIdPart());
}
@Test
public void testDetermineBase() {
IdType rr;
rr = new IdType("http://foo/fhir/Organization/123");
assertEquals("http://foo/fhir", rr.getBaseUrl());
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
assertEquals("http://foo/fhir", rr.getBaseUrl());
rr = new IdType("Organization/123/_history/123");
assertEquals(null, rr.getBaseUrl());
}
@Test
public void testParseValueAbsolute() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("http://foo/fhir/Organization/123");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals("Organization", ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
}
@Test
public void testBigDecimalIds() {
IdType id = new IdType(new BigDecimal("123"));
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
}
@Test
public void testParseValueAbsoluteWithVersion() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("http://foo/fhir/Organization/123/_history/999");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals("Organization", ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
}
@Test
public void testViewMethods() {
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
}
@Test
public void testParseValueWithVersion() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("/123/_history/999");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals(null, ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
}
@Test
public void testParseValueMissingType1() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("/123");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals(null, ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
}
@Test
public void testParseValueMissingType2() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("123");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals(null, ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
}
@Test
public void testParseValueRelative1() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("Organization/123");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals("Organization", ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
}
@Test
public void testParseValueRelative2() {
Patient patient = new Patient();
IdType rr = new IdType();
rr.setValue("/Organization/123");
patient.setManagingOrganization(new Reference(rr));
Patient actual = parseAndEncode(patient);
Reference ref = actual.getManagingOrganization();
assertEquals("Organization", ref.getReferenceElement().getResourceType());
assertEquals("123", ref.getReferenceElement().getIdPart());
}
private Patient parseAndEncode(Patient patient) {
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
ourLog.info("\n" + encoded);
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
}
@BeforeClass
public static void beforeClass() {
ourCtx = FhirContext.forDstu3();
}
}

View File

@ -1,7 +1,9 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -202,6 +204,44 @@ public class GenericClientDstu3Test {
assertEquals("<div>A PATIENT</div>", outputPt.getText().getDivAsString());
}
@Test
public void testUpdateById() throws Exception {
IParser p = ourCtx.newXmlParser();
OperationOutcome conf = new OperationOutcome();
conf.getText().setDivAsString("OK!");
final String respString = p.encodeResourceToString(conf);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
Patient pt = new Patient();
pt.setId("222");
pt.getText().setDivAsString("A PATIENT");
client.update().resource(pt).withId("111").execute();
ourLog.info(Arrays.asList(capt.getAllValues().get(0).getAllHeaders()).toString());
assertEquals("http://example.com/fhir/Patient/111", capt.getAllValues().get(0).getURI().toASCIIString());
validateUserAgent(capt);
assertEquals("application/xml+fhir;charset=utf-8", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue().toLowerCase().replace(" ", ""));
assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue());
String body = extractBodyAsString(capt);
assertThat(body, containsString("<id value=\"111\"/>"));
}
private void validateUserAgent(ArgumentCaptor<HttpUriRequest> capt) {
assertEquals(1, capt.getAllValues().get(0).getHeaders("User-Agent").length);
assertEquals(expectedUserAgent(), capt.getAllValues().get(0).getHeaders("User-Agent")[0].getValue());

View File

@ -0,0 +1,179 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.Patient;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.util.PortUtil;
public class CreateDstu3Test {
private static CloseableHttpClient ourClient;
private static String ourLastConditionalUrl;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateDstu3Test.class);
private static int ourPort;
private static Server ourServer;
private static IdType ourLastId;
private static IdType ourLastIdParam;
private static boolean ourLastRequestWasSearch;
private static FhirContext ourCtx = FhirContext.forDstu3();
@Before
public void before() {
ourLastId = null;
ourLastConditionalUrl = null;
ourLastIdParam = null;
ourLastRequestWasSearch = false;
}
@Test
public void testCreateWithIdInBody() throws Exception {
Patient patient = new Patient();
patient.setId("2");
patient.addIdentifier().setValue("002");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(400, status.getStatusLine().getStatusCode());
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
assertEquals("Can not create resource with ID \"2\", an ID element must not be supplied in the resource body on a create (POST) operation", oo.getIssue().get(0).getDiagnostics());
}
@Test
public void testCreateWithIdInUrl() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setValue("002");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
// httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(400, status.getStatusLine().getStatusCode());
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
}
@Test
public void testCreateWithIdInUrlForConditional() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setValue("002");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2");
httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "Patient?identifier=system%7C001");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(400, status.getStatusLine().getStatusCode());
OperationOutcome oo = ourCtx.newXmlParser().parseResource(OperationOutcome.class, responseContent);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)", oo.getIssue().get(0).getDiagnostics());
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
PatientProvider patientProvider = new PatientProvider();
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
servlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
public static class PatientProvider implements IResourceProvider {
@Override
public Class<Patient> getResourceType() {
return Patient.class;
}
@Search
public List<IResource> search(@OptionalParam(name = "foo") StringDt theString) {
ourLastRequestWasSearch = true;
return new ArrayList<IResource>();
}
@Create()
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @ConditionalUrlParam String theConditional, @IdParam IdType theIdParam) {
ourLastConditionalUrl = theConditional;
ourLastId = thePatient.getIdElement();
ourLastIdParam = theIdParam;
return new MethodOutcome(new IdType("Patient/001/_history/002"));
}
}
}

View File

@ -208,6 +208,9 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
myUnqualifiedId = theId;
myUnqualifiedVersionId = StringUtils.defaultIfBlank(theVersionId, null);
myHaveComponentParts = true;
if (isBlank(myBaseUrl) && isBlank(myResourceType) && isBlank(myUnqualifiedId) && isBlank(myUnqualifiedVersionId)) {
myHaveComponentParts = false;
}
}
/**

View File

@ -38,6 +38,12 @@ public class IdTypeTest {
assertFalse(id.isLocal());
}
@Test
public void testConstructorsWithNullArguments() {
IdType id = new IdType(null, null, null);
assertEquals(null, id.getValue());
}
@Test
public void testDetectLocalBase() {
assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57").getValue());

View File

@ -95,7 +95,7 @@ public class CreateConditionalHl7OrgTest {
Patient patient = new Patient();
patient.addIdentifier().setValue("002");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/2?_format=true&_pretty=true");
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient?_format=true&_pretty=true");
httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
@ -109,8 +109,8 @@ public class CreateConditionalHl7OrgTest {
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue());
assertEquals("Patient/2", ourLastId.toUnqualified().getValue());
assertEquals("Patient/2", ourLastIdParam.toUnqualified().getValue());
assertNull(ourLastId.getValue());
assertNull(ourLastIdParam);
assertNull(ourLastConditionalUrl);
}

View File

@ -39,9 +39,6 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class ETagServerHl7OrgTest {
private static CloseableHttpClient ourClient;
@ -107,6 +104,7 @@ public class ETagServerHl7OrgTest {
@Test
public void testUpdateWithNoVersion() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);
@ -122,6 +120,7 @@ public class ETagServerHl7OrgTest {
@Test
public void testUpdateWithIfMatch() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);
@ -139,6 +138,7 @@ public class ETagServerHl7OrgTest {
@Test
public void testUpdateWithIfMatchPreconditionFailed() throws Exception {
Patient p = new Patient();
p.setId("2");
p.addIdentifier().setSystem("urn:system").setValue("001");
String resBody = ourCtx.newXmlParser().encodeResourceToString(p);

View File

@ -39,9 +39,6 @@ import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class UpdateConditionalHl7OrgDstu2Test {
private static CloseableHttpClient ourClient;
private static String ourLastConditionalUrl;
@ -93,6 +90,7 @@ public class UpdateConditionalHl7OrgDstu2Test {
public void testUpdateWithoutConditionalUrl() throws Exception {
Patient patient = new Patient();
patient.setId("2");
patient.addIdentifier().setValue("002");
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/2");

View File

@ -207,10 +207,14 @@
for $everything operation responses. Thanks to Sonali Somase for reporting!
</action>
<action type="fix" issue="305">
JPA server should reject update requests where the resource body does not
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!
<![CDATA[<br/><br/>]]>
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)
</action>
</release>
<release version="1.4" date="2016-02-04">