Correctly handle extended operation in annotation based client where the

response is a raw resource and not a Parameters resource
This commit is contained in:
James Agnew 2016-03-12 15:10:02 -05:00
parent 452316aed7
commit 6ddf91d9e2
6 changed files with 62 additions and 10 deletions

View File

@ -229,8 +229,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
case BUNDLE_PROVIDER:
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients");
case BUNDLE_RESOURCE:
// TODO: we should support this
throw new IllegalStateException("Return type of " + IBundleProvider.class.getSimpleName() + " is not yet supported in clients");
return resource;
case METHOD_OUTCOME:
MethodOutcome retVal = new MethodOutcome();
retVal.setOperationOutcome((BaseOperationOutcome) resource);
@ -246,10 +245,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
@Override
public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
// byte[] requestContents = loadRequestContents(theRequest);
byte[] requestContents = null;
final ResourceOrDstu1Bundle responseObject = invokeServer(theServer, theRequest, requestContents);
final ResourceOrDstu1Bundle responseObject = doInvokeServer(theServer, theRequest);
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequest);
if (responseObject.getResource() != null) {
@ -288,7 +284,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
}
}
public ResourceOrDstu1Bundle invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest, byte[] requestContents) {
public ResourceOrDstu1Bundle doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
// Method params
Object[] params = new Object[getParameters().size()];
for (int i = 0; i < getParameters().size(); i++) {

View File

@ -78,7 +78,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
}
@Override
public ResourceOrDstu1Bundle invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest, byte[] requestContents) {
public ResourceOrDstu1Bundle doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
IBase bundle = handlePagingRequest(theServer, theRequest, null, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]);
if (bundle instanceof Bundle) {
return new ResourceOrDstu1Bundle((Bundle) bundle);

View File

@ -556,7 +556,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
if (method instanceof BaseResourceReturningMethodBinding) {
try {
ResourceOrDstu1Bundle responseData = ((BaseResourceReturningMethodBinding) method).invokeServer(theRequestDetails.getServer(), requestDetails, new byte[0]);
ResourceOrDstu1Bundle responseData = ((BaseResourceReturningMethodBinding) method).doInvokeServer(theRequestDetails.getServer(), requestDetails);
IBaseResource resource = responseData.getResource();
if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) {
resource = filterNestedBundle(requestDetails, resource);

View File

@ -566,7 +566,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
if (method instanceof BaseResourceReturningMethodBinding) {
try {
ResourceOrDstu1Bundle responseData = ((BaseResourceReturningMethodBinding) method).invokeServer(theRequestDetails.getServer(), requestDetails, new byte[0]);
ResourceOrDstu1Bundle responseData = ((BaseResourceReturningMethodBinding) method).doInvokeServer(theRequestDetails.getServer(), requestDetails);
IBaseResource resource = responseData.getResource();
if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) {
resource = filterNestedBundle(requestDetails, resource);

View File

@ -28,6 +28,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
@ -94,6 +95,46 @@ public class OperationClientDstu2Test {
idx++;
}
@Test
public void testOpInstanceWithBundleReturn() throws Exception {
Bundle retResource = new Bundle();
retResource.setTotal(100);
// Parameters outParams = new Parameters();
// outParams.addParameter().setName("return").setResource(retResource);
final String retVal = ourCtx.newXmlParser().encodeResourceToString(retResource);
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse);
when(ourHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(ourHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(ourHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(retVal), Charset.forName("UTF-8"));
}
});
IOpClient client = ourCtx.newRestfulClient(IOpClient.class, "http://foo");
int idx = 0;
Bundle response = client.opInstanceWithBundleReturn(new IdDt("222"), new StringDt("PARAM1str"), new Patient().setActive(true));
assertEquals(100, response.getTotal().intValue());
HttpPost value = (HttpPost) capt.getAllValues().get(idx);
String requestBody = IOUtils.toString(((HttpPost) value).getEntity().getContent());
IOUtils.closeQuietly(((HttpPost) value).getEntity().getContent());
ourLog.info(requestBody);
Parameters request = ourCtx.newXmlParser().parseResource(Parameters.class, requestBody);
assertEquals("http://foo/Patient/222/$OP_INSTANCE_WITH_BUNDLE_RETURN", value.getURI().toASCIIString());
assertEquals(2, request.getParameter().size());
assertEquals("PARAM1", request.getParameter().get(0).getName());
assertEquals("PARAM1str", ((StringDt) request.getParameter().get(0).getValue()).getValue());
assertEquals("PARAM2", request.getParameter().get(1).getName());
assertEquals(Boolean.TRUE, ((Patient) request.getParameter().get(1).getResource()).getActive());
idx++;
}
@Test
public void testOpServer() throws Exception {
Parameters outParams = new Parameters();
@ -269,6 +310,7 @@ public class OperationClientDstu2Test {
}
public interface IOpClient extends IBasicClient {
//@formatter:off
@Operation(name="$OP_INSTANCE", type=Patient.class)
public Parameters opInstance(
@ -278,6 +320,15 @@ public class OperationClientDstu2Test {
);
//@formatter:on
//@formatter:off
@Operation(name="$OP_INSTANCE_WITH_BUNDLE_RETURN", type=Patient.class)
public Bundle opInstanceWithBundleReturn(
@IdParam IdDt theId,
@OperationParam(name="PARAM1") StringDt theParam1,
@OperationParam(name="PARAM2") Patient theParam2
);
//@formatter:on
//@formatter:off
@Operation(name="$OP_SERVER")
public Parameters opServer(

View File

@ -230,6 +230,11 @@
Conformance statement. This is incorrect, as only
a request for <![CDATA[<code>OPTIONS [base url]</code>]]> should be treated as such. Thanks to Michael Lawley for reporting!
</action>
<action type="fix">
REST annotation style client was not able to handle extended operations
($foo) where the response from the server was a raw resource instead
of a Parameters resource. Thanks to Andrew Michael Martin for reporting!
</action>
</release>
<release version="1.4" date="2016-02-04">
<action type="add">