Response writing is fixed
This commit is contained in:
parent
6d866b81b6
commit
15ae763313
|
@ -45,7 +45,9 @@ public enum ResourceMetadataKeyEnum {
|
|||
|
||||
/**
|
||||
* The value for this key is the bundle entry <b>Updated</b> time. This
|
||||
* is defined by FHIR as "Last Updated for resource".
|
||||
* is defined by FHIR as "Last Updated for resource". This value is also
|
||||
* used for populating the "Last-Modified" header in the case of methods
|
||||
* that return a single resource (read, vread, etc.)
|
||||
* <p>
|
||||
* Values for this key are of type {@link InstantDt}
|
||||
* </p>
|
||||
|
|
|
@ -445,7 +445,6 @@ class ParserState<T extends IElement> {
|
|||
// ignore by default
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void endingElement() throws DataFormatException {
|
||||
// ignore by default
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.method;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
@ -82,6 +83,20 @@ public abstract class BaseMethodBinding {
|
|||
*/
|
||||
public abstract String getResourceName();
|
||||
|
||||
protected Object invokeServerMethod(Object theResourceProvider, Object[] theMethodParams) {
|
||||
try {
|
||||
return getMethod().invoke(theResourceProvider, theMethodParams);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof BaseServerResponseException) {
|
||||
throw (BaseServerResponseException)e.getCause();
|
||||
} else {
|
||||
throw new InternalErrorException("Failed to call access method", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new InternalErrorException("Failed to call access method", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object getProvider() {
|
||||
return myProvider;
|
||||
|
|
|
@ -59,7 +59,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceVersionNotSpecifiedException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
||||
public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
||||
abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||
private List<IParameter> myParameters;
|
||||
private boolean myReturnVoid;
|
||||
|
@ -146,19 +146,16 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
Object[] params = new Object[myParameters.size()];
|
||||
for (int i = 0; i < myParameters.size(); i++) {
|
||||
IParameter param = myParameters.get(i);
|
||||
if (param != null) {
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, null);
|
||||
}
|
||||
}
|
||||
|
||||
addParametersForServerRequest(theRequest, params);
|
||||
|
||||
MethodOutcome response;
|
||||
try {
|
||||
response = (MethodOutcome) this.getMethod().invoke(getProvider(), params);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
MethodOutcome response = (MethodOutcome) invokeServerMethod(getProvider(), params);
|
||||
|
||||
if (response == null) {
|
||||
if (myReturnVoid == false) {
|
||||
|
|
|
@ -22,7 +22,6 @@ package ca.uhn.fhir.rest.method;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -44,13 +43,13 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
||||
public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
|
||||
private int myResourceParameterIndex;
|
||||
private String myResourceName;
|
||||
|
||||
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
|
||||
super(theMethod, theContext, theMethodAnnotation, theProvider);
|
||||
|
||||
|
||||
ResourceParameter resourceParameter = null;
|
||||
|
||||
int index = 0;
|
||||
|
@ -77,7 +76,7 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
|
|||
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
EncodingUtil encoding = BaseMethodBinding.determineResponseEncoding(theRequest.getServletRequest(), theRequest.getParameters());
|
||||
|
@ -97,20 +96,10 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
|
|||
|
||||
MethodOutcome response;
|
||||
try {
|
||||
response = (MethodOutcome) this.getMethod().invoke(getProvider(), params);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof UnprocessableEntityException) {
|
||||
streamOperationOutcome((UnprocessableEntityException)e.getCause(), theServer, encoding, theResponse);
|
||||
return;
|
||||
}
|
||||
if (e.getCause() instanceof BaseServerResponseException) {
|
||||
throw (BaseServerResponseException)e.getCause();
|
||||
}
|
||||
throw new InternalErrorException(e);
|
||||
response = (MethodOutcome) invokeServerMethod(getProvider(), params);
|
||||
} catch (BaseServerResponseException e) {
|
||||
streamOperationOutcome(e, theServer, encoding, theResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
|
@ -151,20 +140,30 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
|
|||
// getMethod().in
|
||||
}
|
||||
|
||||
private void streamOperationOutcome(UnprocessableEntityException theE, RestfulServer theServer, EncodingUtil theEncoding, HttpServletResponse theResponse) throws IOException {
|
||||
private void streamOperationOutcome(BaseServerResponseException theE, RestfulServer theServer, EncodingUtil theEncoding, HttpServletResponse theResponse) throws IOException {
|
||||
theResponse.setStatus(theE.getStatusCode());
|
||||
|
||||
theServer.addHapiHeader(theResponse);
|
||||
|
||||
theResponse.setContentType(theEncoding.getResourceContentType());
|
||||
IParser parser = theEncoding.newParser(theServer.getFhirContext());
|
||||
if (theE.getOperationOutcome() != null) {
|
||||
theResponse.setContentType(theEncoding.getResourceContentType());
|
||||
IParser parser = theEncoding.newParser(theServer.getFhirContext());
|
||||
|
||||
Writer writer = theResponse.getWriter();
|
||||
try {
|
||||
parser.encodeResourceToWriter(theE.getOperationOutcome(), writer);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
Writer writer = theResponse.getWriter();
|
||||
try {
|
||||
parser.encodeResourceToWriter(theE.getOperationOutcome(), writer);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
} else {
|
||||
theResponse.setContentType(Constants.CT_TEXT);
|
||||
Writer writer = theResponse.getWriter();
|
||||
try {
|
||||
writer.append(theE.getMessage());
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -185,5 +184,4 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
|
|||
return createClientInvocation(theArgs, resource, resourceName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingUtil;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
|
@ -62,7 +64,7 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
public abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||
|
||||
protected static final Set<String> ALLOWED_PARAMS;
|
||||
static {
|
||||
|
@ -72,13 +74,16 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
set.add(Constants.PARAM_PRETTY);
|
||||
ALLOWED_PARAMS = Collections.unmodifiableSet(set);
|
||||
}
|
||||
private MethodReturnTypeEnum myMethodReturnType;
|
||||
|
||||
private MethodReturnTypeEnum myMethodReturnType;
|
||||
private String myResourceName;
|
||||
private List<IParameter> myParameters;
|
||||
|
||||
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(theMethod, theConetxt, theProvider);
|
||||
|
||||
myParameters = ParameterUtil.getResourceParameters(theMethod);
|
||||
|
||||
Class<?> methodReturnType = theMethod.getReturnType();
|
||||
if (Collection.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.LIST_OF_RESOURCES;
|
||||
|
@ -87,7 +92,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
} else if (Bundle.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
|
||||
} else {
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: "
|
||||
+ theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
||||
if (theReturnResourceType != null) {
|
||||
|
@ -136,6 +142,13 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
case RESOURCE: {
|
||||
IResource resource = parser.parseResource(theResponseReader);
|
||||
|
||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
InstantDt lmValue = new InstantDt(lmHeaders.get(0));
|
||||
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, lmValue);
|
||||
}
|
||||
|
||||
switch (getMethodReturnType()) {
|
||||
case BUNDLE:
|
||||
return Bundle.withSingleResource(resource);
|
||||
|
@ -151,14 +164,14 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
throw new IllegalStateException("Should not get here!");
|
||||
}
|
||||
|
||||
public abstract List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException, InternalErrorException;
|
||||
public abstract List<IResource> invokeServer(Object theResourceProvider, Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
|
||||
// Pretty print
|
||||
Map<String, String[]> params = theRequest.getParameters();
|
||||
String[] pretty = params.remove(Constants.PARAM_PRETTY);
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] pretty = requestParams.remove(Constants.PARAM_PRETTY);
|
||||
boolean prettyPrint = false;
|
||||
if (pretty != null && pretty.length > 0) {
|
||||
if ("true".equals(pretty[0])) {
|
||||
|
@ -167,7 +180,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
|
||||
// Narrative mode
|
||||
String[] narrative = params.remove(Constants.PARAM_NARRATIVE);
|
||||
String[] narrative = requestParams.remove(Constants.PARAM_NARRATIVE);
|
||||
NarrativeModeEnum narrativeMode = null;
|
||||
if (narrative != null && narrative.length > 0) {
|
||||
narrativeMode = NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
|
||||
|
@ -177,7 +190,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
|
||||
// Determine response encoding
|
||||
EncodingUtil responseEncoding = determineResponseEncoding(theRequest.getServletRequest(), params);
|
||||
EncodingUtil responseEncoding = determineResponseEncoding(theRequest.getServletRequest(), requestParams);
|
||||
|
||||
// Is this request coming from a browser
|
||||
String uaHeader = theRequest.getServletRequest().getHeader("user-agent");
|
||||
|
@ -186,7 +199,16 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
List<IResource> result = invokeServer(getProvider(), theRequest);
|
||||
// Method params
|
||||
Object[] params = new Object[myParameters.size()];
|
||||
for (int i = 0; i < myParameters.size(); i++) {
|
||||
IParameter param = myParameters.get(i);
|
||||
if (param != null) {
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, null);
|
||||
}
|
||||
}
|
||||
|
||||
List<IResource> result = invokeServer(getProvider(), theRequest, params);
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE:
|
||||
streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode);
|
||||
|
@ -219,7 +241,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
return (IdDt) retValObj;
|
||||
}
|
||||
}
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + IdDt.class.getCanonicalName());
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected "
|
||||
+ IdDt.class.getCanonicalName());
|
||||
}
|
||||
|
||||
private InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
||||
|
@ -235,7 +258,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
return (InstantDt) retValObj;
|
||||
}
|
||||
}
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + InstantDt.class.getCanonicalName());
|
||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected "
|
||||
+ InstantDt.class.getCanonicalName());
|
||||
}
|
||||
|
||||
private IParser getNewParser(EncodingUtil theResponseEncoding, boolean thePrettyPrint, NarrativeModeEnum theNarrativeMode) {
|
||||
|
@ -252,8 +276,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == NarrativeModeEnum.SUPPRESS);
|
||||
}
|
||||
|
||||
private void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser,
|
||||
NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
private void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase,
|
||||
String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
assert !theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
@ -298,10 +322,10 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
b.append(resId);
|
||||
|
||||
/*
|
||||
* If this is a history operation, we add the version of the
|
||||
* resource to the self link to indicate the version
|
||||
* If this is a history operation, we add the version of the resource to the self link to indicate the version
|
||||
*/
|
||||
if (getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_INSTANCE || getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_TYPE || getSystemOperationType() == RestfulOperationSystemEnum.HISTORY_SYSTEM) {
|
||||
if (getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_INSTANCE || getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_TYPE
|
||||
|| getSystemOperationType() == RestfulOperationSystemEnum.HISTORY_SYSTEM) {
|
||||
IdDt versionId = getIdFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.VERSION_ID);
|
||||
if (versionId != null) {
|
||||
b.append('/');
|
||||
|
@ -363,7 +387,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
}
|
||||
|
||||
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint,
|
||||
boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
|
@ -375,6 +400,11 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
|||
}
|
||||
theHttpResponse.setCharacterEncoding("UTF-8");
|
||||
|
||||
InstantDt lastUpdated = getInstantFromMetadataOrNullIfNone(theResource.getResourceMetadata(), ResourceMetadataKeyEnum.UPDATED);
|
||||
if (lastUpdated != null) {
|
||||
theHttpResponse.addHeader(Constants.HEADER_LAST_MODIFIED, lastUpdated.getValueAsString());
|
||||
}
|
||||
|
||||
PrintWriter writer = theHttpResponse.getWriter();
|
||||
try {
|
||||
if (theNarrativeMode == NarrativeModeEnum.ONLY) {
|
||||
|
|
|
@ -57,11 +57,11 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException,
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest, Object[] theMethodParams) throws InvalidRequestException,
|
||||
InternalErrorException {
|
||||
IResource conf;
|
||||
try {
|
||||
conf = (Conformance) getMethod().invoke(theResourceProvider);
|
||||
conf = (Conformance) invokeServerMethod(theResourceProvider, theMethodParams);
|
||||
} catch (Exception e) {
|
||||
throw new InternalErrorException("Failed to call access method", e);
|
||||
}
|
||||
|
|
|
@ -170,13 +170,12 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] args = new Object[getMethod().getParameterTypes().length];
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
if (myCountParamIndex != null) {
|
||||
String[] countValues = theRequest.getParameters().remove(Constants.PARAM_COUNT);
|
||||
if (countValues.length > 0 && StringUtils.isNotBlank(countValues[0])) {
|
||||
try {
|
||||
args[myCountParamIndex] = new IntegerDt(countValues[0]);
|
||||
theMethodParams[myCountParamIndex] = new IntegerDt(countValues[0]);
|
||||
} catch (DataFormatException e) {
|
||||
throw new InvalidRequestException("Invalid _count parameter value: " + countValues[0]);
|
||||
}
|
||||
|
@ -186,7 +185,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
String[] sinceValues = theRequest.getParameters().remove(Constants.PARAM_SINCE);
|
||||
if (sinceValues.length > 0 && StringUtils.isNotBlank(sinceValues[0])) {
|
||||
try {
|
||||
args[mySinceParamIndex] = new InstantDt(sinceValues[0]);
|
||||
theMethodParams[mySinceParamIndex] = new InstantDt(sinceValues[0]);
|
||||
} catch (DataFormatException e) {
|
||||
throw new InvalidRequestException("Invalid _since parameter value: " + sinceValues[0]);
|
||||
}
|
||||
|
@ -194,20 +193,11 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
if (myIdParamIndex!=null) {
|
||||
args[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response;
|
||||
try {
|
||||
response = getMethod().invoke(theResourceProvider, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new InternalErrorException(e);
|
||||
theMethodParams[myIdParamIndex] = theRequest.getId();
|
||||
}
|
||||
|
||||
Object response = invokeServerMethod(theResourceProvider, theMethodParams);
|
||||
|
||||
return toResourceList(response);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
private Integer myIdIndex;
|
||||
private Integer myVersionIdIndex;
|
||||
private int myParameterCount;
|
||||
|
||||
public ReadMethodBinding(Class<? extends IResource> theAnnotatedResourceType, Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(theAnnotatedResourceType, theMethod, theContext, theProvider);
|
||||
|
@ -55,7 +54,6 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
myIdIndex = idIndex;
|
||||
myVersionIdIndex = versionIdIndex;
|
||||
myParameterCount = getMethod().getParameterTypes().length;
|
||||
|
||||
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
||||
if (!IdDt.class.equals(parameterTypes[myIdIndex])) {
|
||||
|
@ -107,19 +105,13 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException, InternalErrorException {
|
||||
Object[] params = new Object[myParameterCount];
|
||||
params[myIdIndex] = theRequest.getId();
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
theMethodParams[myIdIndex] = theRequest.getId();
|
||||
if (myVersionIdIndex != null) {
|
||||
params[myVersionIdIndex] = theRequest.getVersion();
|
||||
theMethodParams[myVersionIdIndex] = theRequest.getVersion();
|
||||
}
|
||||
|
||||
Object response;
|
||||
try {
|
||||
response = getMethod().invoke(theResourceProvider, params);
|
||||
} catch (Exception e) {
|
||||
throw new InternalErrorException("Failed to call access method", e);
|
||||
}
|
||||
Object response = invokeServerMethod(theResourceProvider, theMethodParams);
|
||||
|
||||
return toResourceList(response);
|
||||
}
|
||||
|
|
|
@ -105,36 +105,12 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest) throws InvalidRequestException,
|
||||
public List<IResource> invokeServer(Object theResourceProvider, Request theRequest, Object[] theMethodParams) throws InvalidRequestException,
|
||||
InternalErrorException {
|
||||
assert theRequest.getId() == null;
|
||||
assert theRequest.getVersion() == null;
|
||||
|
||||
Object[] params = new Object[myParameters.size()];
|
||||
for (int i = 0; i < myParameters.size(); i++) {
|
||||
IParameter param = myParameters.get(i);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, null);
|
||||
}
|
||||
|
||||
Object response;
|
||||
try {
|
||||
Method method = this.getMethod();
|
||||
response = method.invoke(theResourceProvider, params);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause != null) {
|
||||
if (cause instanceof BaseServerResponseException) {
|
||||
throw (BaseServerResponseException)cause;
|
||||
} else {
|
||||
throw new InternalErrorException(cause);
|
||||
}
|
||||
}
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
Object response = invokeServerMethod(theResourceProvider, theMethodParams);
|
||||
|
||||
return toResourceList(response);
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ public class Constants {
|
|||
public static final String PARAM_COUNT = "_count";
|
||||
public static final String PARAM_SINCE = "_since";
|
||||
public static final String PARAM_SEARCH = "_search";
|
||||
public static final String HEADER_LAST_MODIFIED = "Last-Modified";
|
||||
public static final String HEADER_LAST_MODIFIED_LOWERCASE = HEADER_LAST_MODIFIED.toLowerCase();
|
||||
|
||||
static {
|
||||
Map<String, EncodingUtil> valToEncoding = new HashMap<String, EncodingUtil>();
|
||||
|
|
|
@ -53,10 +53,10 @@ public class ResourceBinding {
|
|||
ourLog.debug("Looking for a handler for {}", theRequest);
|
||||
for (BaseMethodBinding rm : methods) {
|
||||
if (rm.matches(theRequest)) {
|
||||
ourLog.info("Handler {} matches", rm);
|
||||
ourLog.debug("Handler {} matches", rm);
|
||||
return rm;
|
||||
} else {
|
||||
ourLog.info("Handler {} does not match", rm);
|
||||
ourLog.trace("Handler {} does not match", rm);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.server.exceptions;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
|
@ -25,6 +27,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int myStatusCode;
|
||||
private final OperationOutcome myOperationOutcome;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -37,8 +40,23 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
public BaseServerResponseException(int theStatusCode, String theMessage) {
|
||||
super(theMessage);
|
||||
myStatusCode = theStatusCode;
|
||||
myOperationOutcome=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theStatusCode
|
||||
* The HTTP status code corresponding to this problem
|
||||
* @param theMessage
|
||||
* The message
|
||||
*/
|
||||
public BaseServerResponseException(int theStatusCode, String theMessage, OperationOutcome theOperationOutcome) {
|
||||
super(theMessage);
|
||||
myStatusCode = theStatusCode;
|
||||
myOperationOutcome=theOperationOutcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -51,6 +69,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
public BaseServerResponseException(int theStatusCode, String theMessage, Throwable theCause) {
|
||||
super(theMessage, theCause);
|
||||
myStatusCode = theStatusCode;
|
||||
myOperationOutcome=null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,6 +83,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
public BaseServerResponseException(int theStatusCode, Throwable theCause) {
|
||||
super(theCause.toString(), theCause);
|
||||
myStatusCode = theStatusCode;
|
||||
myOperationOutcome=null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,4 +93,11 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
return myStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OperationOutcome} resource if any which was supplied in the response,
|
||||
* or <code>null</code>
|
||||
*/
|
||||
public OperationOutcome getOperationOutcome() {
|
||||
return myOperationOutcome;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,49 +34,35 @@ public class UnprocessableEntityException extends BaseServerResponseException {
|
|||
private static final String DEFAULT_MESSAGE = "Unprocessable Entity";
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final OperationOutcome myOperationOutcome;
|
||||
|
||||
/**
|
||||
* Constructor which accepts an {@link OperationOutcome} resource which will be supplied in the response
|
||||
*/
|
||||
public UnprocessableEntityException(OperationOutcome theOperationOutcome) {
|
||||
super(422, theOperationOutcome == null || theOperationOutcome.getIssueFirstRep().getDetails().isEmpty() ? DEFAULT_MESSAGE : theOperationOutcome.getIssueFirstRep().getDetails().getValue());
|
||||
if (theOperationOutcome == null) {
|
||||
myOperationOutcome = new OperationOutcome();
|
||||
} else {
|
||||
myOperationOutcome = theOperationOutcome;
|
||||
}
|
||||
super(422, DEFAULT_MESSAGE, theOperationOutcome == null ? new OperationOutcome() : theOperationOutcome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which accepts a String describing the issue. This string will be translated into an {@link OperationOutcome} resource which will be supplied in the response.
|
||||
*/
|
||||
public UnprocessableEntityException(String theMessage) {
|
||||
super(422, theMessage);
|
||||
|
||||
myOperationOutcome = new OperationOutcome();
|
||||
myOperationOutcome.addIssue().setDetails(theMessage);
|
||||
super(422, DEFAULT_MESSAGE, toOperationOutcome(theMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which accepts an array of Strings describing the issue. This strings will be translated into an {@link OperationOutcome} resource which will be supplied in the response.
|
||||
*/
|
||||
public UnprocessableEntityException(String... theMessage) {
|
||||
super(422, theMessage != null && theMessage.length > 0 ? theMessage[0] : DEFAULT_MESSAGE);
|
||||
|
||||
myOperationOutcome = new OperationOutcome();
|
||||
if (theMessage != null) {
|
||||
for (String next : theMessage) {
|
||||
myOperationOutcome.addIssue().setDetails(next);
|
||||
}
|
||||
}
|
||||
super(422, DEFAULT_MESSAGE, toOperationOutcome(theMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OperationOutcome} resource if any which was supplied in the response. Will not return null.
|
||||
*/
|
||||
public OperationOutcome getOperationOutcome() {
|
||||
return myOperationOutcome;
|
||||
private static OperationOutcome toOperationOutcome(String... theMessage) {
|
||||
OperationOutcome operationOutcome = new OperationOutcome();
|
||||
if (theMessage != null) {
|
||||
for (String next : theMessage) {
|
||||
operationOutcome.addIssue().setDetails(next);
|
||||
}
|
||||
}
|
||||
return operationOutcome;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -375,6 +375,9 @@ public class ClientTest {
|
|||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
Header[] headers = new Header[1];
|
||||
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "2011-01-02T22:01:02");
|
||||
when(httpResponse.getAllHeaders()).thenReturn(headers);
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
|
@ -385,6 +388,9 @@ public class ClientTest {
|
|||
assertEquals("http://foo/Patient/111", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||
|
||||
InstantDt lm = (InstantDt) response.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
assertEquals("2011-01-02T22:01:02", lm.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -728,6 +728,9 @@ public class ResfulServerMethodTest {
|
|||
Patient patient = (Patient) ourCtx.newXmlParser().parseBundle(responseContent).getEntries().get(0).getResource();
|
||||
assertEquals("someQueryNoParams", patient.getName().get(1).getFamilyAsSingleString());
|
||||
|
||||
InstantDt lm = (InstantDt) patient.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
assertEquals("2011-01-02T22:01:02", lm.getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1104,6 +1107,7 @@ public class ResfulServerMethodTest {
|
|||
public Patient getPatientNoParams() {
|
||||
Patient next = getIdToPatient().get("1");
|
||||
next.addName().addFamily("someQueryNoParams");
|
||||
next.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt("2011-01-02T22:01:02"));
|
||||
return next;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue