Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
jamesagnew 2014-08-06 09:05:21 -04:00
commit 0b7cfec06b
17 changed files with 409 additions and 210 deletions

View File

@ -8,7 +8,25 @@
<body>
<release version="0.6" date="TBD">
<action type="add">
Allow generic client
Allow generic client ... OAUTH
</action>
<action type="fix">
Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University
Health Network for reporting!
</action>
<action type="fix" issue="4">
Create method was incorrectly returning an HTTP 204 on sucessful completion, but
should be returning an HTTP 200 per the FHIR specification. Thanks to wanghaisheng
for reporting!
</action>
<action type="fix">
FHIR Tester UI now correctly sends UTF-8 charset in responses so that message payloads containing
non US-ASCII characters will correctly display in the browser
</action>
<action type="fix">
JSON parser was incorrectly encoding extensions on composite elements outside the element itself
(as is done correctly for non-composite elements) instead of inside of them. Thanks to David Hay of
Orion for reporting this!
</action>
</release>
<release version="0.5" date="2014-Jul-30">

View File

@ -30,6 +30,11 @@ public abstract class BaseRuntimeChildDefinition {
public abstract IAccessor getAccessor();
@Override
public String toString() {
return getClass().getSimpleName()+"[" + getElementName() + "]";
}
public abstract BaseRuntimeElementDefinition<?> getChildByName(String theName);
public abstract BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IElement> theType);

View File

@ -56,6 +56,11 @@ public abstract class BaseRuntimeElementDefinition<T extends IElement> {
myImplementingClass = theImplementingClass;
}
@Override
public String toString() {
return getClass().getSimpleName()+"[" + getName() + "]";
}
public void addExtension(RuntimeChildDeclaredExtensionDefinition theExtension) {
if (theExtension == null) {
throw new NullPointerException();

View File

@ -181,7 +181,7 @@ public class JsonParser extends BaseParser implements IParser {
for (BundleEntry nextEntry : theBundle.getEntries()) {
eventWriter.writeStartObject();
boolean deleted = nextEntry.getDeletedAt() !=null&&nextEntry.getDeletedAt().isEmpty()==false;
boolean deleted = nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false;
if (deleted) {
writeTagWithTextNode(eventWriter, "deleted", nextEntry.getDeletedAt());
}
@ -227,11 +227,16 @@ public class JsonParser extends BaseParser implements IParser {
eventWriter.flush();
}
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName) throws IOException {
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
String theChildName) throws IOException {
switch (theChildDef.getChildType()) {
case PRIMITIVE_DATATYPE: {
IPrimitiveDatatype<?> value = (IPrimitiveDatatype<?>) theValue;
if (isBlank(value.getValueAsString())) {
break;
}
if (value instanceof IntegerDt) {
if (theChildName != null) {
theWriter.write(theChildName, ((IntegerDt) value).getValue());
@ -333,7 +338,8 @@ public class JsonParser extends BaseParser implements IParser {
}
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, List<? extends BaseRuntimeChildDefinition> theChildren) throws IOException {
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
List<? extends BaseRuntimeChildDefinition> theChildren) throws IOException {
for (BaseRuntimeChildDefinition nextChild : theChildren) {
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
INarrativeGenerator gen = myContext.getNarrativeGenerator();
@ -372,14 +378,16 @@ public class JsonParser extends BaseParser implements IParser {
if (childDef == null) {
super.throwExceptionForUnknownChildType(nextChild, type);
}
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
if (extDef.isModifier()) {
addToHeldExtensions(valueIdx, modifierExtensions, extDef, nextValue);
} else {
addToHeldExtensions(valueIdx, extensions, extDef, nextValue);
}
// Don't encode extensions
// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
// if (extDef.isModifier()) {
// addToHeldExtensions(valueIdx, modifierExtensions, extDef, nextValue);
// } else {
// addToHeldExtensions(valueIdx, extensions, extDef, nextValue);
// }
} else {
if (currentChildName == null || !currentChildName.equals(childName)) {
@ -398,7 +406,7 @@ public class JsonParser extends BaseParser implements IParser {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null);
}
if (nextValue instanceof ISupportsUndeclaredExtensions) {
if (nextValue instanceof ISupportsUndeclaredExtensions && primitive) {
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
addToHeldExtensions(valueIdx, ext, extensions);
@ -416,61 +424,41 @@ public class JsonParser extends BaseParser implements IParser {
}
if (extensions.size() > 0 || modifierExtensions.size() > 0) {
// Ignore extensions if we're encoding a resource, since they
// are handled one level up
if (currentChildName != null) {
theEventWriter.writeStartArray('_' + currentChildName);
theEventWriter.writeStartArray('_' + currentChildName);
for (int i = 0; i < valueIdx; i++) {
boolean haveContent = false;
if (extensions.size() > i && extensions.get(i) != null && extensions.get(i).isEmpty() == false) {
haveContent = true;
theEventWriter.writeStartObject();
theEventWriter.writeStartArray("extension");
for (HeldExtension nextExt : extensions.get(i)) {
nextExt.write(theResDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
theEventWriter.writeEnd();
}
if (!haveContent) {
// theEventWriter.writeEnd();
theEventWriter.writeNull();
for (int i = 0; i < valueIdx; i++) {
boolean haveContent = false;
if (extensions.size() > i && extensions.get(i) != null && extensions.get(i).isEmpty() == false) {
haveContent = true;
theEventWriter.writeStartObject();
theEventWriter.writeStartArray("extension");
for (HeldExtension nextExt : extensions.get(i)) {
nextExt.write(theResDef, theResource, theEventWriter);
}
theEventWriter.writeEnd();
theEventWriter.writeEnd();
}
// if (extensions.size() > 0) {
//
// theEventWriter.name(extType);
// theEventWriter.beginArray();
// for (ArrayList<HeldExtension> next : extensions) {
// if (next == null || next.isEmpty()) {
// theEventWriter.nullValue();
// } else {
// theEventWriter.beginArray();
// // next.write(theEventWriter);
// theEventWriter.endArray();
// }
// }
// for (int i = extensions.size(); i < valueIdx; i++) {
// theEventWriter.nullValue();
// }
// theEventWriter.endArray();
// }
theEventWriter.writeEnd();
if (!haveContent) {
// theEventWriter.writeEnd();
theEventWriter.writeNull();
}
}
theEventWriter.writeEnd();
}
}
}
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef) throws IOException, DataFormatException {
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
BaseRuntimeElementCompositeDefinition<?> resDef) throws IOException, DataFormatException {
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, resDef, theResDef, theResource);
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions());
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren());
}
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull, boolean theIsSubElementWithinResource) throws IOException {
private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, String theObjectNameOrNull,
boolean theIsSubElementWithinResource) throws IOException {
if (!theIsSubElementWithinResource) {
super.containResourcesForEncoding(theResource);
}
@ -491,9 +479,8 @@ public class JsonParser extends BaseParser implements IParser {
if (theResource instanceof Binary) {
Binary bin = (Binary) theResource;
theEventWriter.write("contentType", bin.getContentType());
theEventWriter.write("content",bin.getContentAsBase64());
theEventWriter.write("content", bin.getContentAsBase64());
} else {
extractAndWriteExtensionsAsDirectChild(theResource, theEventWriter, resDef, theResDef, theResource);
encodeCompositeElementToStreamWriter(theResDef, theResource, theResource, theEventWriter, resDef);
}
theEventWriter.writeEnd();
@ -506,7 +493,7 @@ public class JsonParser extends BaseParser implements IParser {
JsonGenerator eventWriter = createJsonGenerator(theWriter);
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null,false);
encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null, false);
eventWriter.flush();
}
@ -541,10 +528,10 @@ public class JsonParser extends BaseParser implements IParser {
}
/**
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object
* called _name): resource extensions, and extension extensions
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object called _name): resource extensions, and extension extensions
*/
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef, IResource theResource) throws IOException {
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
IResource theResource) throws IOException {
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
@ -895,7 +882,8 @@ public class JsonParser extends BaseParser implements IParser {
}
}
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) throws IOException {
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
List<HeldExtension> modifierExtensions) throws IOException {
if (extensions.isEmpty() == false) {
theEventWriter.writeStartArray("extension");
for (HeldExtension next : extensions) {

View File

@ -821,10 +821,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
public Bundle execute() {
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
Map<String, List<String>> initial = createExtraParams();
if (initial != null) {
params.putAll(initial);
}
// Map<String, List<String>> initial = createExtraParams();
// if (initial != null) {
// params.putAll(initial);
// }
for (ICriterionInternal next : myCriterion) {
String parameterName = next.getParameterName();

View File

@ -65,7 +65,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
if (!allowVoidReturnType()) {
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName() + " method but it does not return " + MethodOutcome.class);
throw new ConfigurationException("Method " + theMethod.getName() + " in type " + theMethod.getDeclaringClass().getCanonicalName() + " is a @" + theMethodAnnotation.getSimpleName()
+ " method but it does not return " + MethodOutcome.class);
} else if (theMethod.getReturnType() == void.class) {
myReturnVoid = true;
}
@ -92,7 +93,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
}
@Override
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
BaseServerResponseException {
switch (theResponseStatusCode) {
case Constants.STATUS_HTTP_200_OK:
case Constants.STATUS_HTTP_201_CREATED:
@ -148,26 +150,40 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
throw new InternalErrorException("Server method returned invalid resource ID: " + response.getId().getValue());
}
}
if (getResourceOperationType() == RestfulOperationTypeEnum.CREATE) {
switch (getResourceOperationType()) {
case CREATE:
if (response == null) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null, which is not allowed for create operation");
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName()
+ " returned null, which is not allowed for create operation");
}
theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED);
addLocationHeader(theRequest, theResponse, response);
} else if (response == null) {
if (isReturnVoid() == false) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
}
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
} else {
if (response.getOperationOutcome() == null) {
break;
case UPDATE:
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
addLocationHeader(theRequest, theResponse, response);
break;
case VALIDATE:
case DELETE:
default:
if (response == null) {
if (isReturnVoid() == false) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
}
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
} else {
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
}
if (getResourceOperationType() == RestfulOperationTypeEnum.UPDATE) {
addLocationHeader(theRequest, theResponse, response);
if (response.getOperationOutcome() == null) {
theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT);
} else {
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);
}
if (getResourceOperationType() == RestfulOperationTypeEnum.UPDATE) {
addLocationHeader(theRequest, theResponse, response);
}
}
}
@ -200,7 +216,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
}
/**
* @throws IOException
* @throws IOException
*/
protected IResource parseIncomingServerResource(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServer.determineRequestEncoding(theRequest);
@ -210,48 +226,27 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
}
/*
* @Override public void invokeServer(RestfulServer theServer, Request
* theRequest, HttpServletResponse theResponse) throws
* BaseServerResponseException, IOException { Object[] params = new
* Object[getParameters().size()]; for (int i = 0; i <
* getParameters().size(); i++) { IParameter param = getParameters().get(i);
* if (param != null) { params[i] =
* @Override public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException { Object[] params = new
* Object[getParameters().size()]; for (int i = 0; i < getParameters().size(); i++) { IParameter param = getParameters().get(i); if (param != null) { params[i] =
* param.translateQueryParametersIntoServerArgument(theRequest, null); } }
*
* addParametersForServerRequest(theRequest, params);
*
* MethodOutcome response = (MethodOutcome)
* invokeServerMethod(getProvider(), params);
* MethodOutcome response = (MethodOutcome) invokeServerMethod(getProvider(), params);
*
* if (response == null) { if (myReturnVoid == false) { throw new
* ConfigurationException("Method " + getMethod().getName() + " in type " +
* getMethod().getDeclaringClass().getCanonicalName() + " returned null"); }
* else { theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT); } }
* else if (!myReturnVoid) { if (response.isCreated()) {
* theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED); StringBuilder b
* = new StringBuilder(); b.append(theRequest.getFhirServerBase());
* b.append('/'); b.append(getResourceName()); b.append('/');
* b.append(response.getId().getValue()); if (response.getVersionId() !=
* null && response.getVersionId().isEmpty() == false) {
* b.append("/_history/"); b.append(response.getVersionId().getValue()); }
* theResponse.addHeader("Location", b.toString()); } else {
* theResponse.setStatus(Constants.STATUS_HTTP_200_OK); } } else {
* if (response == null) { if (myReturnVoid == false) { throw new ConfigurationException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() +
* " returned null"); } else { theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT); } } else if (!myReturnVoid) { if (response.isCreated()) {
* theResponse.setStatus(Constants.STATUS_HTTP_201_CREATED); StringBuilder b = new StringBuilder(); b.append(theRequest.getFhirServerBase()); b.append('/'); b.append(getResourceName());
* b.append('/'); b.append(response.getId().getValue()); if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) { b.append("/_history/");
* b.append(response.getVersionId().getValue()); } theResponse.addHeader("Location", b.toString()); } else { theResponse.setStatus(Constants.STATUS_HTTP_200_OK); } } else {
* theResponse.setStatus(Constants.STATUS_HTTP_204_NO_CONTENT); }
*
* theServer.addHeadersToResponse(theResponse);
*
* Writer writer = theResponse.getWriter(); try { if (response != null) {
* OperationOutcome outcome = new OperationOutcome(); if
* (response.getOperationOutcome() != null &&
* response.getOperationOutcome().getIssue() != null) {
* outcome.getIssue().addAll(response.getOperationOutcome().getIssue()); }
* EncodingUtil encoding =
* BaseMethodBinding.determineResponseEncoding(theRequest
* .getServletRequest(), theRequest.getParameters());
* theResponse.setContentType(encoding.getResourceContentType()); IParser
* parser = encoding.newParser(getContext());
* parser.encodeResourceToWriter(outcome, writer); } } finally {
* writer.close(); } // getMethod().in }
* Writer writer = theResponse.getWriter(); try { if (response != null) { OperationOutcome outcome = new OperationOutcome(); if (response.getOperationOutcome() != null &&
* response.getOperationOutcome().getIssue() != null) { outcome.getIssue().addAll(response.getOperationOutcome().getIssue()); } EncodingUtil encoding =
* BaseMethodBinding.determineResponseEncoding(theRequest .getServletRequest(), theRequest.getParameters()); theResponse.setContentType(encoding.getResourceContentType()); IParser parser =
* encoding.newParser(getContext()); parser.encodeResourceToWriter(outcome, writer); } } finally { writer.close(); } // getMethod().in }
*/
public boolean isReturnVoid() {
@ -266,10 +261,10 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
b.append('/');
b.append(response.getId().getIdPart());
if (response.getId().hasVersionIdPart()) {
b.append("/"+Constants.PARAM_HISTORY+"/");
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getId().getVersionIdPart());
}else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/"+Constants.PARAM_HISTORY+"/");
} else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/" + Constants.PARAM_HISTORY + "/");
b.append(response.getVersionId().getValue());
}
theResponse.addHeader(Constants.HEADER_LOCATION, b.toString());
@ -350,8 +345,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
protected abstract void addParametersForServerRequest(Request theRequest, Object[] theParams);
/**
* Subclasses may override to allow a void method return type, which is
* allowable for some methods (e.g. delete)
* Subclasses may override to allow a void method return type, which is allowable for some methods (e.g. delete)
*/
protected boolean allowVoidReturnType() {
return false;
@ -360,17 +354,14 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
protected abstract BaseHttpClientInvocation createClientInvocation(Object[] theArgs, IResource resource);
/**
* For servers, this method will match only incoming requests that match the
* given operation, or which have no operation in the URL if this method
* returns null.
* For servers, this method will match only incoming requests that match the given operation, or which have no operation in the URL if this method returns null.
*/
protected abstract String getMatchingOperation();
protected abstract Set<RequestType> provideAllowableRequestTypes();
/**
* Subclasses may override if the incoming request should not contain a
* resource
* Subclasses may override if the incoming request should not contain a resource
*/
protected boolean requestContainsResource() {
return true;
@ -406,7 +397,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
if (StringUtils.isBlank(theLocationHeader)) {
return;
}
theOutcomeToPopulate.setId(new IdDt(theLocationHeader));
String resourceNamePart = "/" + theResourceName + "/";

View File

@ -57,6 +57,17 @@ import ca.uhn.fhir.rest.server.ResourceBinding;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.ExtensionConstants;
/**
* Server FHIR Provider which serves the conformance statement for a RESTful server implementation
*
* <p>
* Note: This class is safe to extend, but it is important to note that the same instance of
* {@link Conformance} is always returned unless {@link #setCache(boolean)} is called with a value
* of <code>false</code>. This means that if you are adding anything to the returned
* conformance instance on each call you should call <code>setCache(false)</code> in
* your provider constructor.
* </p>
*/
public class ServerConformanceProvider {
private volatile Conformance myConformance;
@ -67,6 +78,11 @@ public class ServerConformanceProvider {
myRestfulServer = theRestfulServer;
}
/**
* Actually create and return the conformance statement
*
* See the class documentation for an important note if you are extending this class
*/
@Metadata
public Conformance getServerConformance() {
if (myConformance != null && myCache) {
@ -246,6 +262,9 @@ public class ServerConformanceProvider {
/**
* Sets the cache property (default is true). If set to true, the same response will be returned for each
* invocation.
* <p>
* See the class documentation for an important note if you are extending this class
* </p>
*/
public void setCache(boolean theCache) {
myCache = theCache;

View File

@ -83,6 +83,67 @@ public class JsonParserTest {
}
@Test
public void testEncodeExtensionInCompositeElement() {
Conformance c = new Conformance();
c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c);
ourLog.info(encoded);
encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c);
ourLog.info(encoded);
assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"rest\":[{\"security\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}]}");
}
@Test
public void testEncodeExtensionInPrimitiveElement() {
Conformance c = new Conformance();
c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c);
ourLog.info(encoded);
encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c);
ourLog.info(encoded);
assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}]}");
// Now with a value
ourLog.info("---------------");
c = new Conformance();
c.getAcceptUnknown().setValue(true);
c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c);
ourLog.info(encoded);
encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c);
ourLog.info(encoded);
assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":true,\"_acceptUnknown\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}]}");
}
@Test
public void testEncodeExtensionInResourceElement() {
Conformance c = new Conformance();
// c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
c.addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c);
ourLog.info(encoded);
encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c);
ourLog.info(encoded);
assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}");
}
@Test
public void testEncodeBinaryResource() {
@ -387,7 +448,18 @@ public class JsonParserTest {
assertEquals("Organization/123", ref.getReference().getValue());
}
@Test
public void testEncodeExtensionOnEmptyElement() throws Exception {
ValueSet valueSet = new ValueSet();
valueSet.addTelecom().addUndeclaredExtension(false, "http://foo", new StringDt("AAA"));
String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet);
assertThat(encoded, containsString("\"telecom\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"));
}
@Test
@ -402,11 +474,11 @@ public class JsonParserTest {
code.setDisplay("someDisplay");
code.addUndeclaredExtension(false, "urn:alt", new StringDt("alt name"));
String encoded = new FhirContext().newJsonParser().encodeResourceToString(valueSet);
String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet);
ourLog.info(encoded);
assertThat(encoded, not(containsString("123456")));
assertThat(encoded, containsString("\"define\":{\"concept\":[{\"code\":\"someCode\",\"display\":\"someDisplay\"}],\"_concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}]}]}"));
assertEquals("{\"resourceType\":\"ValueSet\",\"define\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}", encoded);
}
@ -500,32 +572,8 @@ public class JsonParserTest {
given.addUndeclaredExtension(ext2);
String enc = new FhirContext().newJsonParser().encodeResourceToString(patient);
ourLog.info(enc);
//@formatter:off
assertThat(enc, containsString(("{" +
" \"resourceType\":\"Patient\"," +
" \"name\":[" +
" {" +
" \"family\":[" +
" \"Shmoe\"" +
" ]," +
" \"given\":[" +
" \"Joe\"" +
" ]" +
" }" +
" ]," +
" \"_name\":[" +
" {" +
" \"extension\":[" +
" {" +
" \"url\":\"http://examples.com#givenext\"," +
" \"valueString\":\"Hello\"" +
" }" +
" ]" +
" }" +
" ]" +
"}").replaceAll(" +", "")));
//@formatter:on
assertEquals("{\"resourceType\":\"Patient\",\"name\":[{\"extension\":[{\"url\":\"http://examples.com#givenext\",\"valueString\":\"Hello\"}],\"family\":[\"Shmoe\"],\"given\":[\"Joe\"]}]}", enc);
IParser newJsonParser = new FhirContext().newJsonParser();
StringReader reader = new StringReader(enc);
Patient parsed = newJsonParser.parseResource(Patient.class, reader);
@ -837,9 +885,7 @@ public class JsonParserTest {
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
fhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));
IParser jsonParser = fhirCtx.newJsonParser();
IParser jsonParser = fhirCtx.newJsonParser().setPrettyPrint(true);
String encoded = jsonParser.encodeResourceToString(obs);
ourLog.info(encoded);

View File

@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.method.SearchStyleEnum;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -343,6 +344,33 @@ public class GenericClientTest {
}
@SuppressWarnings("unused")
@Test
public void testSearchWithClientEncodingAndPrettyPrintConfig() throws Exception {
String msg = getPatientFeedWithOneResult();
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()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
GenericClient client = (GenericClient) myCtx.newRestfulGenericClient("http://example.com/fhir");
client.setPrettyPrint(true);
client.setEncoding(EncodingEnum.JSON);
//@formatter:off
Bundle response = client.search()
.forResource(Patient.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient?_format=json&_pretty=true", capt.getValue().getURI().toString());
}
@SuppressWarnings("unused")
@Test
public void testSearchByDate() throws Exception {

View File

@ -104,9 +104,10 @@ public class UpdateTest {
HttpResponse status = ourClient.execute(httpPost);
assertEquals(204, status.getStatusLine().getStatusCode());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("location").getValue());
IOUtils.closeQuietly(status.getEntity().getContent());
}
@Test
@ -118,18 +119,20 @@ public class UpdateTest {
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog, Cat");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
CloseableHttpResponse status = ourClient.execute(httpPost);
assertEquals(2, ourReportProvider.getLastTags().size());
assertEquals(new Tag("Dog"), ourReportProvider.getLastTags().get(0));
assertEquals(new Tag("Cat"), ourReportProvider.getLastTags().get(1));
IOUtils.closeQuietly(status.getEntity().getContent());
httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; label=\"aa\", Cat; label=\"bb\"");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
status = ourClient.execute(httpPost);
assertEquals(2, ourReportProvider.getLastTags().size());
assertEquals(new Tag((String) null, "Dog", "aa"), ourReportProvider.getLastTags().get(0));
assertEquals(new Tag((String) null, "Cat", "bb"), ourReportProvider.getLastTags().get(1));
IOUtils.closeQuietly(status.getEntity().getContent());
}
@ -142,9 +145,10 @@ public class UpdateTest {
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
CloseableHttpResponse status = ourClient.execute(httpPost);
assertEquals(1, ourReportProvider.getLastTags().size());
assertEquals(new Tag("Dog"), ourReportProvider.getLastTags().get(0));
IOUtils.closeQuietly(status.getEntity().getContent());
}
@ -157,9 +161,10 @@ public class UpdateTest {
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; scheme=\"http://foo\"");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
CloseableHttpResponse status = ourClient.execute(httpPost);
assertEquals(1, ourReportProvider.getLastTags().size());
assertEquals(new Tag("http://foo", "Dog", null), ourReportProvider.getLastTags().get(0));
IOUtils.closeQuietly(status.getEntity().getContent());
httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; scheme=\"http://foo\";");
@ -167,6 +172,7 @@ public class UpdateTest {
ourClient.execute(httpPost);
assertEquals(1, ourReportProvider.getLastTags().size());
assertEquals(new Tag("http://foo", "Dog", null), ourReportProvider.getLastTags().get(0));
IOUtils.closeQuietly(status.getEntity().getContent());
}
@ -179,16 +185,18 @@ public class UpdateTest {
HttpPut httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; scheme=\"http://foo\"; label=\"aaaa\"");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
CloseableHttpResponse status = ourClient.execute(httpPost);
assertEquals(1, ourReportProvider.getLastTags().size());
assertEquals(new Tag("http://foo", "Dog", "aaaa"), ourReportProvider.getLastTags().get(0));
IOUtils.closeQuietly(status.getEntity().getContent());
httpPost = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
httpPost.addHeader("Category", "Dog; scheme=\"http://foo\"; label=\"aaaa\"; ");
httpPost.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(dr), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
ourClient.execute(httpPost);
status=ourClient.execute(httpPost);
assertEquals(1, ourReportProvider.getLastTags().size());
assertEquals(new Tag("http://foo", "Dog", "aaaa"), ourReportProvider.getLastTags().get(0));
IOUtils.closeQuietly(status.getEntity().getContent());
}
@ -208,9 +216,9 @@ public class UpdateTest {
// IOUtils.toString(status.getEntity().getContent());
// ourLog.info("Response was:\n{}", responseContent);
assertEquals(204, status.getStatusLine().getStatusCode());
assertNull(status.getEntity());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("Location").getValue());
IOUtils.closeQuietly(status.getEntity().getContent());
}
@ -224,10 +232,11 @@ public class UpdateTest {
httpPut.addHeader("Content-Location", "/Patient/001/_history/002");
httpPut.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse results = ourClient.execute(httpPut);
assertEquals(400, results.getStatusLine().getStatusCode());
String responseContent = IOUtils.toString(results.getEntity().getContent());
CloseableHttpResponse status = ourClient.execute(httpPut);
assertEquals(400, status.getStatusLine().getStatusCode());
String responseContent = IOUtils.toString(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
IOUtils.closeQuietly(status.getEntity().getContent());
}

View File

@ -253,6 +253,16 @@
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
<!-- Misc -->
<dependency>

View File

@ -31,23 +31,11 @@ public class JpaConformanceProvider extends ServerConformanceProvider {
myRestfulServer = theRestfulServer;
mySystemDao = theSystemDao;
super.setCache(false);
// for (IFhirResourceDao<?> nextResourceDao : theResourceDaos) {
// nextResourceDao.registerDaoListener(new IDaoListener() {
// @Override
// public void writeCompleted() {
// myCachedValue = null;
// }
// });
// }
}
@Override
public Conformance getServerConformance() {
Conformance retVal = myCachedValue;
// if (retVal != null) {
// return retVal;
// }
Map<String, Long> counts = mySystemDao.getResourceCounts();

View File

@ -5,6 +5,10 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@ -30,6 +34,7 @@ import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.HttpEntityWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
@ -52,6 +57,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.rest.client.IClientInterceptor;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.gclient.ICreateTyped;
import ca.uhn.fhir.rest.gclient.IQuery;
@ -59,6 +65,7 @@ import ca.uhn.fhir.rest.gclient.IUntypedQuery;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.to.model.HomeRequest;
import ca.uhn.fhir.to.model.ResourceRequest;
import ca.uhn.fhir.to.model.TransactionRequest;
@ -96,7 +103,8 @@ public class Controller {
public String actionConformance(final HomeRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
ResultType returnsResource = ResultType.RESOURCE;
long start = System.currentTimeMillis();
@ -107,7 +115,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, "Loaded conformance");
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, "Loaded conformance", interceptor);
ourLog.info(logPrefix(theModel) + "Displayed conformance profile");
@ -124,7 +132,8 @@ public class Controller {
public String actionDelete(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
RuntimeResourceDefinition def;
try {
@ -150,7 +159,7 @@ public class Controller {
returnsResource = handleClientException(client, e, theModel);
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
ourLog.info(logPrefix(theModel) + "Deleted resource of type " + def.getName());
@ -161,7 +170,8 @@ public class Controller {
public String actionGetTags(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
Class<? extends IResource> resType = null;
ResultType returnsResource = ResultType.TAGLIST;
@ -202,7 +212,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
return "result";
}
@ -229,7 +239,8 @@ public class Controller {
public String actionPage(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
String url = defaultString(theReq.getParameter("page-url"));
if (!url.startsWith(theModel.get("base").toString())) {
@ -253,7 +264,7 @@ public class Controller {
String outcomeDescription = "Bundle Page";
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
return "result";
}
@ -262,7 +273,8 @@ public class Controller {
public String actionRead(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
RuntimeResourceDefinition def;
try {
@ -297,7 +309,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
return "result";
}
@ -306,7 +318,8 @@ public class Controller {
public String actionResource(final ResourceRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
Conformance conformance = addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
String resourceName = theRequest.getResource();
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theRequest.getResource());
@ -372,6 +385,72 @@ public class Controller {
return "resource";
}
public static class CaptureInterceptor implements IClientInterceptor {
private HttpRequestBase myLastRequest;
private HttpResponse myLastResponse;
private String myResponseBody;
@Override
public void interceptRequest(HttpRequestBase theRequest) {
assert myLastRequest == null;
myLastRequest = theRequest;
}
@Override
public void interceptResponse(HttpResponse theResponse) throws IOException {
assert myLastResponse == null;
myLastResponse = theResponse;
HttpEntity respEntity = theResponse.getEntity();
if (respEntity != null) {
final byte[] bytes;
try {
bytes = IOUtils.toByteArray(respEntity.getContent());
} catch (IllegalStateException e) {
throw new InternalErrorException(e);
}
myResponseBody = new String(bytes, "UTF-8");
theResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
}
}
public HttpRequestBase getLastRequest() {
return myLastRequest;
}
public HttpResponse getLastResponse() {
return myLastResponse;
}
private static class MyEntityWrapper extends HttpEntityWrapper {
private byte[] myBytes;
public MyEntityWrapper(HttpEntity theWrappedEntity, byte[] theBytes) {
super(theWrappedEntity);
myBytes = theBytes;
}
@Override
public InputStream getContent() throws IOException {
return new ByteArrayInputStream(myBytes);
}
@Override
public void writeTo(OutputStream theOutstream) throws IOException {
theOutstream.write(myBytes);
}
}
public String getLastResponseBody() {
return myResponseBody;
}
}
@RequestMapping(value = { "/search" })
public String actionSearch(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) {
addCommonParams(theRequest, theModel);
@ -382,7 +461,8 @@ public class Controller {
clientCodeJsonWriter.write("action", "search");
clientCodeJsonWriter.write("base", (String) theModel.get("base"));
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
IUntypedQuery search = client.search();
IQuery query;
@ -463,7 +543,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
clientCodeJsonWriter.writeEnd();
clientCodeJsonWriter.close();
@ -477,7 +557,8 @@ public class Controller {
public String actionTransaction(final TransactionRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
String body = preProcessMessageBody(theRequest.getTransactionBody());
@ -507,7 +588,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, "Transaction");
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, "Transaction", interceptor);
return "result";
}
@ -561,7 +642,8 @@ public class Controller {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
Class<? extends IResource> type = null; // def.getImplementingClass();
if ("history-type".equals(theMethod)) {
@ -623,7 +705,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription, interceptor);
try {
if (validate) {
@ -642,7 +724,8 @@ public class Controller {
private void doActionHistory(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel, String theMethod, String theMethodDescription) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
CaptureInterceptor interceptor = new CaptureInterceptor();
GenericClient client = theRequest.newClient(myCtx, myConfig, interceptor);
String id = null;
Class<? extends IResource> type = null; // def.getImplementingClass();
@ -675,7 +758,7 @@ public class Controller {
}
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, theMethodDescription);
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, theMethodDescription, interceptor);
}
@ -1011,14 +1094,16 @@ public class Controller {
return retVal;
}
private void processAndAddLastClientInvocation(GenericClient theClient, ResultType theResultType, ModelMap theModelMap, long theLatency, String outcomeDescription) {
private void processAndAddLastClientInvocation(GenericClient theClient, ResultType theResultType, ModelMap theModelMap, long theLatency, String outcomeDescription,
CaptureInterceptor theInterceptor) {
try {
HttpRequestBase lastRequest = theClient.getLastRequest();
HttpRequestBase lastRequest = theInterceptor.getLastRequest();
HttpResponse lastResponse = theInterceptor.getLastResponse();
String requestBody = null;
String requestUrl = lastRequest != null ? lastRequest.getURI().toASCIIString() : null;
String action = theClient.getLastRequest() != null ? theClient.getLastRequest().getMethod() : null;
String resultStatus = theClient.getLastResponse() != null ? theClient.getLastResponse().getStatusLine().toString() : null;
String resultBody = StringUtils.defaultString(theClient.getLastResponseBody());
String action = lastRequest != null ? lastRequest.getMethod() : null;
String resultStatus = lastResponse != null ? lastResponse.getStatusLine().toString() : null;
String resultBody = StringUtils.defaultString(theInterceptor.getLastResponseBody());
if (lastRequest instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) lastRequest).getEntity();
@ -1027,7 +1112,6 @@ public class Controller {
}
}
HttpResponse lastResponse = theClient.getLastResponse();
ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null;
String mimeType = ct != null ? ct.getMimeType() : null;
EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.to.model;
import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
@ -11,6 +12,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.rest.client.IClientInterceptor;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.to.Controller;
import ca.uhn.fhir.to.TesterConfig;
public class HomeRequest {
@ -80,7 +82,7 @@ public class HomeRequest {
myServerId = theServerId;
}
public GenericClient newClient(FhirContext theContext, TesterConfig theConfig) {
public GenericClient newClient(FhirContext theContext, TesterConfig theConfig, Controller.CaptureInterceptor theInterceptor) {
GenericClient retVal = (GenericClient) theContext.newRestfulGenericClient(getServerBase(theConfig));
retVal.setKeepResponses(true);
@ -96,6 +98,8 @@ public class HomeRequest {
retVal.setEncoding( EncodingEnum.JSON);
}
retVal.registerInterceptor(theInterceptor);
final String remoteAddr = org.slf4j.MDC.get("req.remoteAddr");
retVal.registerInterceptor(new IClientInterceptor() {

View File

@ -21,6 +21,7 @@
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
@ -29,6 +30,7 @@
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8" />
</bean>
</beans>

View File

@ -142,6 +142,7 @@
</configuration>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<!--
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
@ -172,6 +173,7 @@
</lifecycleMappingMetadata>
</configuration>
</plugin>
-->
</plugins>
</pluginManagement>

View File

@ -6,7 +6,7 @@
<dependent-module archiveName="hapi-fhir-base-0.6-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/hapi-fhir-base/hapi-fhir-base">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-tester-overlay?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependent-module deploy-path="/" handle="module:/overlay/prj/hapi-fhir-testpage-overlay?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">
<dependency-type>consumes</dependency-type>
</dependent-module>
<dependent-module deploy-path="/" handle="module:/overlay/slf/?includes=**/**&amp;excludes=META-INF/MANIFEST.MF">