Response writing is fixed

This commit is contained in:
jamesagnew 2014-04-24 17:27:25 -04:00
parent 6d866b81b6
commit 15ae763313
16 changed files with 165 additions and 141 deletions

View File

@ -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>

View File

@ -445,7 +445,6 @@ class ParserState<T extends IElement> {
// ignore by default
}
@SuppressWarnings("unused")
public void endingElement() throws DataFormatException {
// ignore by default
}

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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>();

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}