package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.CapabilityStatement;
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestOperationComponent;
import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.IntegerType;
import org.hl7.fhir.dstu3.model.Money;
import org.hl7.fhir.dstu3.model.OperationDefinition;
import org.hl7.fhir.dstu3.model.OperationDefinition.OperationParameterUse;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UnsignedIntType;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
public class OperationServerDstu3Test {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx;
private static IdType ourLastId;
private static String ourLastMethod;
private static StringType ourLastParam1;
private static Patient ourLastParam2;
private static List<StringType> ourLastParam3;
private static Money ourLastParamMoney1;
private static UnsignedIntType ourLastParamUnsignedInt1;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationServerDstu3Test.class);
private static int ourPort;
private static Server ourServer;
private IGenericClient myFhirClient;
@Before
public void before() {
ourLastParam1 = null;
ourLastParam2 = null;
ourLastParam3 = null;
ourLastParamUnsignedInt1 = null;
ourLastParamMoney1 = null;
ourLastId = null;
ourLastMethod = "";
myFhirClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort);
}
@Test
public void testConformance() throws Exception {
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
loggingInterceptor.setLogResponseBody(true);
myFhirClient.registerInterceptor(loggingInterceptor);
CapabilityStatement p = myFhirClient.fetchConformance().ofType(CapabilityStatement.class).prettyPrint().execute();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p));
List<CapabilityStatementRestOperationComponent> ops = p.getRest().get(0).getOperation();
assertThat(ops.size(), greaterThan(1));
List<String> opNames = toOpNames(ops);
assertThat(opNames, containsInRelativeOrder("OP_TYPE"));
// OperationDefinition def = (OperationDefinition) ops.get(opNames.indexOf("OP_TYPE")).getDefinition().getResource();
OperationDefinition def = myFhirClient.read().resource(OperationDefinition.class).withId(ops.get(opNames.indexOf("OP_TYPE")).getDefinition().getReferenceElement()).execute();
assertEquals("OP_TYPE", def.getCode());
}
/**
* See #380
*/
@Test
public void testOperationDefinition() {
OperationDefinition def = myFhirClient.read().resource(OperationDefinition.class).withId("OperationDefinition/Patient--OP_TYPE").execute();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(def));
// @OperationParam(name="PARAM1") StringType theParam1,
// @OperationParam(name="PARAM2") Patient theParam2,
// @OperationParam(name="PARAM3", min=2, max=5) List<StringType> theParam3,
// @OperationParam(name="PARAM4", min=1) List<StringType> theParam4,
assertEquals(4, def.getParameter().size());
assertEquals("PARAM1", def.getParameter().get(0).getName());
assertEquals(OperationParameterUse.IN, def.getParameter().get(0).getUse());
assertEquals(0, def.getParameter().get(0).getMin());
assertEquals("1", def.getParameter().get(0).getMax());
assertEquals("PARAM2", def.getParameter().get(1).getName());
assertEquals(OperationParameterUse.IN, def.getParameter().get(1).getUse());
assertEquals(0, def.getParameter().get(1).getMin());
assertEquals("1", def.getParameter().get(1).getMax());
assertEquals("PARAM3", def.getParameter().get(2).getName());
assertEquals(OperationParameterUse.IN, def.getParameter().get(2).getUse());
assertEquals(2, def.getParameter().get(2).getMin());
assertEquals("5", def.getParameter().get(2).getMax());
assertEquals("PARAM4", def.getParameter().get(3).getName());
assertEquals(OperationParameterUse.IN, def.getParameter().get(3).getUse());
assertEquals(1, def.getParameter().get(3).getMin());
assertEquals("*", def.getParameter().get(3).getMax());
}
private List<String> toOpNames(List<CapabilityStatementRestOperationComponent> theOps) {
ArrayList<String> retVal = new ArrayList<String>();
for (CapabilityStatementRestOperationComponent next : theOps) {
retVal.add(next.getName());
}
return retVal;
}
@Test
public void testInstanceEverythingGet() throws Exception {
// Try with a GET
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$everything");
CloseableHttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("instance $everything", ourLastMethod);
assertThat(response, startsWith("<Bundle"));
assertEquals("Patient/123", ourLastId.toUnqualifiedVersionless().getValue());
}
@Test
public void testInstanceEverythingHapiClient() throws Exception {
ourCtx.newRestfulGenericClient("http://localhost:" + ourPort).operation().onInstance(new IdType("Patient/123")).named("$everything").withParameters(new Parameters()).execute();
assertEquals("instance $everything", ourLastMethod);
assertEquals("Patient/123", ourLastId.toUnqualifiedVersionless().getValue());
}
@Test
public void testInstanceEverythingPost() throws Exception {
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(new Parameters());
// Try with a POST
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$everything");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("instance $everything", ourLastMethod);
assertThat(response, startsWith("<Bundle"));
assertEquals("Patient/123", ourLastId.toUnqualifiedVersionless().getValue());
}
@Test
public void testOperationCantUseGetIfItIsntIdempotent() throws Exception {
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$OP_INSTANCE");
HttpResponse status = ourClient.execute(httpPost);
assertEquals(Constants.STATUS_HTTP_405_METHOD_NOT_ALLOWED, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("POST", status.getFirstHeader(Constants.HEADER_ALLOW).getValue());
assertThat(response, containsString("HTTP Method GET is not allowed"));
}
@Test
public void testOperationWrongParameterType() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new IntegerType(123));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$OP_INSTANCE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse status = ourClient.execute(httpPost);
try {
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
assertThat(response, containsString("Request has parameter PARAM1 of type IntegerType but method expects type StringType"));
ourLog.info(response);
} finally {
IOUtils.closeQuietly(status);
}
}
@Test
public void testOperationOnInstance() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$OP_INSTANCE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("123", ourLastId.getIdPart());
assertEquals("$OP_INSTANCE", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
/*
* Against type should fail
*/
httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_INSTANCE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
status = ourClient.execute(httpPost);
response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info(response);
assertEquals(400, status.getStatusLine().getStatusCode());
}
@Test
public void testOperationOnInstanceAndType_Instance() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$OP_INSTANCE_OR_TYPE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("123", ourLastId.getIdPart());
assertEquals("$OP_INSTANCE_OR_TYPE", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationOnInstanceAndType_Type() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_INSTANCE_OR_TYPE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals(null, ourLastId);
assertEquals("$OP_INSTANCE_OR_TYPE", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationOnServer() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/$OP_SERVER");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("$OP_SERVER", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationOnType() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_TYPE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("$OP_TYPE", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationOnTypeReturnBundle() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new StringType("PARAM1val"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_TYPE_RET_BUNDLE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertEquals(true, ourLastParam2.getActive());
assertEquals("$OP_TYPE_RET_BUNDLE", ourLastMethod);
Bundle resp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
assertEquals("100", resp.getEntryFirstRep().getResponse().getStatus());
}
@Test
public void testOperationWithBundleProviderResponse() throws Exception {
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/$OP_INSTANCE_BUNDLE_PROVIDER?_pretty=true");
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info(response);
ourCtx.newXmlParser().parseResource(Bundle.class, response);
}
@Test
public void testOperationWithGetUsingParams() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$OP_TYPE?PARAM1=PARAM1val");
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("PARAM1val", ourLastParam1.getValue());
assertNull(ourLastParam2);
assertEquals("$OP_TYPE", ourLastMethod);
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationWithGetUsingParamsFailsWithNonPrimitive() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$OP_TYPE?PARAM1=PARAM1val&PARAM2=foo");
HttpResponse status = ourClient.execute(httpGet);
assertEquals(405, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("POST", status.getFirstHeader(Constants.HEADER_ALLOW).getValue());
assertThat(response, containsString("Can not invoke operation $OP_TYPE using HTTP GET because parameter PARAM2 is not a primitive datatype"));
}
@Test
public void testOperationWithListParam() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
p.addParameter().setName("PARAM3").setValue(new StringType("PARAM3val1"));
p.addParameter().setName("PARAM3").setValue(new StringType("PARAM3val2"));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/$OP_SERVER_LIST_PARAM");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("$OP_SERVER_LIST_PARAM", ourLastMethod);
assertEquals(true, ourLastParam2.getActive());
assertEquals(null, ourLastParam1);
assertEquals(2, ourLastParam3.size());
assertEquals("PARAM3val1", ourLastParam3.get(0).getValue());
assertEquals("PARAM3val2", ourLastParam3.get(1).getValue());
Parameters resp = ourCtx.newXmlParser().parseResource(Parameters.class, response);
assertEquals("RET1", resp.getParameter().get(0).getName());
}
@Test
public void testOperationWithProfileDatatypeParams() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new IntegerType("123"));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_PROFILE_DT");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("$OP_PROFILE_DT", ourLastMethod);
assertEquals("123", ourLastParamUnsignedInt1.getValueAsString());
}
@Test
public void testOperationWithProfileDatatypeParams2() throws Exception {
Parameters p = new Parameters();
Money money = new Money();
money.setCode("CODE");
money.setSystem("SYSTEM");
money.setValue(123L);
p.addParameter().setName("PARAM1").setValue(money);
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_PROFILE_DT2");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("$OP_PROFILE_DT2", ourLastMethod);
assertEquals("CODE", ourLastParamMoney1.getCode());
assertEquals("SYSTEM", ourLastParamMoney1.getSystem());
assertEquals("123", ourLastParamMoney1.getValue().toString());
}
@Test
public void testOperationWithProfileDatatypeUrl() throws Exception {
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient/$OP_PROFILE_DT?PARAM1=123");
HttpResponse status = ourClient.execute(httpPost);
assertEquals(200, status.getStatusLine().getStatusCode());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("$OP_PROFILE_DT", ourLastMethod);
assertEquals("123", ourLastParamUnsignedInt1.getValueAsString());
}
@Test
public void testOperationWrongParamType() throws Exception {
Parameters p = new Parameters();
p.addParameter().setName("PARAM1").setValue(new IntegerType("123"));
p.addParameter().setName("PARAM2").setResource(new Patient().setActive(true));
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$OP_TYPE");
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
assertEquals(400, status.getStatusLine().getStatusCode());
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info(status.getStatusLine().toString());
ourLog.info(response);
assertThat(response, containsString("Request has parameter PARAM1 of type IntegerType but method expects type StringType"));
}
@Test
public void testReadWithOperations() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123");
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals("read", ourLastMethod);
}
@AfterClass
public static void afterClassClearContext() throws Exception {
ourServer.stop();
TestUtil.clearAllStaticFieldsForUnitTest();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourCtx = FhirContext.forDstu3();
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
servlet.setPagingProvider(new FifoMemoryPagingProvider(10).setDefaultPageSize(2));
servlet.setFhirContext(ourCtx);
servlet.setResourceProviders(new PatientProvider());
servlet.setPlainProviders(new PlainProvider());
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
public static void main(String[] theValue) {
Parameters p = new Parameters();
p.addParameter().setName("start").setValue(new DateTimeType("2001-01-02"));
p.addParameter().setName("end").setValue(new DateTimeType("2015-07-10"));
String inParamsStr = FhirContext.forDstu2().newXmlParser().encodeResourceToString(p);
ourLog.info(inParamsStr.replace("\"", "\\\""));
}
public static class PatientProvider implements IResourceProvider {
@Override
public Class<Patient> getResourceType() {
return Patient.class;
}
//@formatter:off
@Operation(name="$OP_INSTANCE")
public Parameters opInstance(
@IdParam IdType theId,
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
) {
//@formatter:on
ourLastMethod = "$OP_INSTANCE";
ourLastId = theId;
ourLastParam1 = theParam1;
ourLastParam2 = theParam2;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off
@Operation(name="$OP_INSTANCE_OR_TYPE")
public Parameters opInstanceOrType(
@IdParam(optional=true) IdType theId,
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
) {
//@formatter:on
ourLastMethod = "$OP_INSTANCE_OR_TYPE";
ourLastId = theId;
ourLastParam1 = theParam1;
ourLastParam2 = theParam2;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off
@Operation(name="$OP_PROFILE_DT2", idempotent=true)
public Bundle opProfileType(
@OperationParam(name="PARAM1") Money theParam1
) {
//@formatter:on
ourLastMethod = "$OP_PROFILE_DT2";
ourLastParamMoney1 = theParam1;
Bundle retVal = new Bundle();
retVal.addEntry().getResponse().setStatus("100");
return retVal;
}
//@formatter:off
@Operation(name="$OP_PROFILE_DT", idempotent=true)
public Bundle opProfileType(
@OperationParam(name="PARAM1") UnsignedIntType theParam1
) {
//@formatter:on
ourLastMethod = "$OP_PROFILE_DT";
ourLastParamUnsignedInt1 = theParam1;
Bundle retVal = new Bundle();
retVal.addEntry().getResponse().setStatus("100");
return retVal;
}
//@formatter:off
@SuppressWarnings("unused")
@Operation(name="$OP_TYPE", idempotent=true)
public Parameters opType(
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2,
@OperationParam(name="PARAM3", min=2, max=5) List<StringType> theParam3,
@OperationParam(name="PARAM4", min=1) List<StringType> theParam4
) {
//@formatter:on
ourLastMethod = "$OP_TYPE";
ourLastParam1 = theParam1;
ourLastParam2 = theParam2;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off
@Operation(name="$OP_TYPE_ONLY_STRING", idempotent=true)
public Parameters opTypeOnlyString(
@OperationParam(name="PARAM1") StringType theParam1
) {
//@formatter:on
ourLastMethod = "$OP_TYPE";
ourLastParam1 = theParam1;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off
@Operation(name="$OP_TYPE_RET_BUNDLE")
public Bundle opTypeRetBundle(
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
) {
//@formatter:on
ourLastMethod = "$OP_TYPE_RET_BUNDLE";
ourLastParam1 = theParam1;
ourLastParam2 = theParam2;
Bundle retVal = new Bundle();
retVal.addEntry().getResponse().setStatus("100");
return retVal;
}
@Operation(name = "$everything", idempotent=true)
public Bundle patientEverything(@IdParam IdType thePatientId) {
ourLastMethod = "instance $everything";
ourLastId = thePatientId;
return new Bundle();
}
/**
* Just to make sure this method doesn't "steal" calls
*/
@Read
public Patient read(@IdParam IdType theId) {
ourLastMethod = "read";
Patient retVal = new Patient();
retVal.setId(theId);
return retVal;
}
}
public static class PlainProvider {
//@formatter:off
@Operation(name="$OP_INSTANCE_BUNDLE_PROVIDER", idempotent=true)
public IBundleProvider opInstanceReturnsBundleProvider() {
ourLastMethod = "$OP_INSTANCE_BUNDLE_PROVIDER";
List<IBaseResource> resources = new ArrayList<IBaseResource>();
for (int i =0; i < 100;i++) {
Patient p = new Patient();
p.setId("Patient/" + i);
p.addName().setFamily("Patient " + i);
resources.add(p);
}
return new SimpleBundleProvider(resources);
}
//@formatter:off
@Operation(name="$OP_SERVER")
public Parameters opServer(
@OperationParam(name="PARAM1") StringType theParam1,
@OperationParam(name="PARAM2") Patient theParam2
) {
//@formatter:on
ourLastMethod = "$OP_SERVER";
ourLastParam1 = theParam1;
ourLastParam2 = theParam2;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
//@formatter:off
@Operation(name="$OP_SERVER_LIST_PARAM")
public Parameters opServerListParam(
@OperationParam(name="PARAM2") Patient theParam2,
@OperationParam(name="PARAM3") List<StringType> theParam3
) {
//@formatter:on
ourLastMethod = "$OP_SERVER_LIST_PARAM";
ourLastParam2 = theParam2;
ourLastParam3 = theParam3;
Parameters retVal = new Parameters();
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
return retVal;
}
}
}