Add unit tests and documentation to the JAX-RS client implementation
This commit is contained in:
parent
f9fa6265df
commit
f49130baf8
|
@ -40,6 +40,11 @@
|
|||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
@SuppressWarnings(value= {"serial"})
|
||||
public class JaxRsClient {
|
||||
|
||||
public static void main(String[] args) {
|
||||
//START SNIPPET: createClient
|
||||
|
||||
// Create a client
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
|
||||
// Create an instance of the JAX RS client factory and
|
||||
// set it on the context
|
||||
JaxRsRestfulClientFactory clientFactory = new JaxRsRestfulClientFactory(ctx);
|
||||
ctx.setRestfulClientFactory(clientFactory);
|
||||
|
||||
// This client uses JAX-RS!
|
||||
IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2");
|
||||
|
||||
//END SNIPPET: createClient
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -570,6 +570,7 @@ public class FhirContext {
|
|||
* @param theRestfulClientFactory
|
||||
*/
|
||||
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
||||
Validate.notNull(theRestfulClientFactory, "theRestfulClientFactory must not be null");
|
||||
this.myRestfulClientFactory = theRestfulClientFactory;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ public interface IRestfulClientFactory {
|
|||
IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getServerValidationMode()} instead
|
||||
* @deprecated Use {@link #getServerValidationMode()} instead (this method is a synonym for that method, but this method is poorly named and will be removed at some point)
|
||||
*/
|
||||
@Deprecated
|
||||
ServerValidationModeEnum getServerValidationModeEnum();
|
||||
|
|
|
@ -150,10 +150,11 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
*/
|
||||
@Override
|
||||
public synchronized <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) {
|
||||
validateConfigured();
|
||||
|
||||
if (!theClientType.isInterface()) {
|
||||
throw new ConfigurationException(theClientType.getCanonicalName() + " is not an interface");
|
||||
}
|
||||
|
||||
|
||||
ClientInvocationHandlerFactory invocationHandler = myInvocationHandlers.get(theClientType);
|
||||
if (invocationHandler == null) {
|
||||
|
@ -171,8 +172,20 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
|||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called automatically before the first use of this factory to ensure that
|
||||
* the configuration is sane. Subclasses may override, but should also call
|
||||
* <code>super.validateConfigured()</code>
|
||||
*/
|
||||
protected void validateConfigured() {
|
||||
if (getFhirContext() == null) {
|
||||
throw new IllegalStateException(getClass().getSimpleName() + " does not have FhirContext defined. This must be set via " + getClass().getSimpleName() + "#setFhirContext(FhirContext)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized IGenericClient newGenericClient(String theServerBase) {
|
||||
validateConfigured();
|
||||
IHttpClient httpClient = getHttpClient(theServerBase);
|
||||
return new GenericClient(myContext, httpClient, theServerBase, this);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,17 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Unit test dependencies -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
|
|
|
@ -87,7 +87,7 @@ public class JaxRsHttpClient implements IHttpClient {
|
|||
}
|
||||
Entity<Form> entity = Entity.form(map);
|
||||
JaxRsHttpRequest retVal = createHttpRequest(entity);
|
||||
addHeadersToRequest(retVal, null, theContext);
|
||||
addHeadersToRequest(retVal, theEncoding, theContext);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ public class JaxRsHttpResponse implements IHttpResponse {
|
|||
@Override
|
||||
public String getMimeType() {
|
||||
MediaType mediaType = myResponse.getMediaType();
|
||||
if (mediaType == null) {
|
||||
return null;
|
||||
}
|
||||
//Keep only type and subtype and do not include the parameters such as charset
|
||||
return new MediaType(mediaType.getType(), mediaType.getSubtype()).toString();
|
||||
}
|
||||
|
|
|
@ -41,14 +41,17 @@ public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
|||
private Client myNativeClient;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor. Note that you must set the {@link FhirContext} manually using {@link #setFhirContext(FhirContext)} if this constructor is used!
|
||||
*/
|
||||
public JaxRsRestfulClientFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param theFhirContext The context
|
||||
*
|
||||
* @param theFhirContext
|
||||
* The context
|
||||
*/
|
||||
public JaxRsRestfulClientFactory(FhirContext theFhirContext) {
|
||||
super(theFhirContext);
|
||||
|
@ -64,10 +67,9 @@ public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> theIfNoneExistParams,
|
||||
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
return new JaxRsHttpClient(getNativeClientClient(), url, theIfNoneExistParams, theIfNoneExistString, theRequestType,
|
||||
theHeaders);
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
Client client = getNativeClientClient();
|
||||
return new JaxRsHttpClient(client, url, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,6 +79,7 @@ public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
|||
|
||||
/**
|
||||
* Only accept clients of type javax.ws.rs.client.Client
|
||||
*
|
||||
* @param theHttpClient
|
||||
*/
|
||||
@Override
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,69 @@
|
|||
<Bundle xmlns="http://hl7.org/fhir">
|
||||
<id value="487d3669-0e1c-4867-b124-400d1849548d"></id>
|
||||
<type value="searchset"></type>
|
||||
<base value="http://localhost:19080/fhir/dstu1"></base>
|
||||
<link>
|
||||
<relation value="just trying add link"></relation>
|
||||
<url value="blarion"></url>
|
||||
</link>
|
||||
<link>
|
||||
<relation value="self"></relation>
|
||||
<url value="http://localhost:19080/fhir/dstu1/Observation?subject.identifier=puppet|CLONE-AA102"></url>
|
||||
</link>
|
||||
<entry>
|
||||
<link>
|
||||
<relation value="orionhealth.edit"></relation>
|
||||
<url value="Observation"></url>
|
||||
</link>
|
||||
<resource>
|
||||
<Observation xmlns="http://hl7.org/fhir">
|
||||
<id value="0d87f02c-da2c-4551-9ead-2956f0165a4f"></id>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
|
||||
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
|
||||
</extension>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org"></system>
|
||||
<code value="8867-4"></code>
|
||||
</coding>
|
||||
</code>
|
||||
<valueString value="observationValue"></valueString>
|
||||
<status value="final"></status>
|
||||
<reliability value="ok"></reliability>
|
||||
<subject>
|
||||
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
|
||||
</subject>
|
||||
</Observation>
|
||||
</resource>
|
||||
</entry>
|
||||
<entry>
|
||||
<link>
|
||||
<relation value="orionhealth.edit"></relation>
|
||||
<url value="Observation"></url>
|
||||
</link>
|
||||
<resource>
|
||||
<Observation xmlns="http://hl7.org/fhir">
|
||||
<id value="c54ac0cc-a99f-40aa-9541-c5aa853a2e88"></id>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
|
||||
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
|
||||
</extension>
|
||||
<code>
|
||||
<coding>
|
||||
<system value="http://loinc.org"></system>
|
||||
<code value="3141-9"></code>
|
||||
</coding>
|
||||
</code>
|
||||
<valueString value="observationValue"></valueString>
|
||||
<status value="final"></status>
|
||||
<reliability value="ok"></reliability>
|
||||
<subject>
|
||||
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
|
||||
</subject>
|
||||
</Observation>
|
||||
</resource>
|
||||
</entry>
|
||||
</Bundle>
|
|
@ -68,6 +68,7 @@ import ca.uhn.fhir.parser.XmlParserDstu2Test;
|
|||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
|
@ -88,6 +89,7 @@ public class GenericClientDstu2Test {
|
|||
@Before
|
||||
public void before() {
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.setRestfulClientFactory(new ApacheRestfulClientFactory(ourCtx));
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
|
@ -99,6 +101,7 @@ public class GenericClientDstu2Test {
|
|||
return body;
|
||||
}
|
||||
|
||||
|
||||
private String getPatientFeedWithOneResult() {
|
||||
//@formatter:off
|
||||
String msg = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
|
@ -1079,13 +1082,8 @@ public class GenericClientDstu2Test {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFormatComment() {
|
||||
return false;
|
||||
public List<String> getFormatCommentsPost() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1094,8 +1092,13 @@ public class GenericClientDstu2Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFormatCommentsPost() {
|
||||
return null;
|
||||
public boolean hasFormatComment() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1109,60 +1112,6 @@ public class GenericClientDstu2Test {
|
|||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithProfiledDatatypeParam() throws IOException, Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Parameters outParams = new Parameters();
|
||||
outParams.addParameter().setValue(new StringDt("STRINGVALOUT1"));
|
||||
outParams.addParameter().setValue(new StringDt("STRINGVALOUT2"));
|
||||
final String respString = p.encodeResourceToString(outParams);
|
||||
|
||||
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()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
client
|
||||
.operation()
|
||||
.onInstance(new IdDt("http://foo/Patient/1"))
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
||||
.andParameter("system", new UriDt("http://loinc.org"))
|
||||
.useHttpGet()
|
||||
.execute();
|
||||
//@formatter:off
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/1/$validate-code?code=8495-4&system=http%3A%2F%2Floinc.org", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
|
||||
//@formatter:off
|
||||
idx++;
|
||||
client
|
||||
.operation()
|
||||
.onInstance(new IdDt("http://foo/Patient/1"))
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
||||
.andParameter("system", new UriDt("http://loinc.org"))
|
||||
.execute();
|
||||
//@formatter:off
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/1/$validate-code", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
ourLog.info(extractBody(capt, idx));
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"code\"/><valueCode value=\"8495-4\"/></parameter><parameter><name value=\"system\"/><valueUri value=\"http://loinc.org\"/></parameter></Parameters>",extractBody(capt, idx));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithListOfParameterResponse() throws Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
@ -1327,6 +1276,60 @@ public class GenericClientDstu2Test {
|
|||
idx++;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationWithProfiledDatatypeParam() throws IOException, Exception {
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
|
||||
Parameters outParams = new Parameters();
|
||||
outParams.addParameter().setValue(new StringDt("STRINGVALOUT1"));
|
||||
outParams.addParameter().setValue(new StringDt("STRINGVALOUT2"));
|
||||
final String respString = p.encodeResourceToString(outParams);
|
||||
|
||||
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()).thenAnswer(new Answer<ReaderInputStream>() {
|
||||
@Override
|
||||
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
//@formatter:off
|
||||
client
|
||||
.operation()
|
||||
.onInstance(new IdDt("http://foo/Patient/1"))
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
||||
.andParameter("system", new UriDt("http://loinc.org"))
|
||||
.useHttpGet()
|
||||
.execute();
|
||||
//@formatter:off
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/1/$validate-code?code=8495-4&system=http%3A%2F%2Floinc.org", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
|
||||
//@formatter:off
|
||||
idx++;
|
||||
client
|
||||
.operation()
|
||||
.onInstance(new IdDt("http://foo/Patient/1"))
|
||||
.named("validate-code")
|
||||
.withParameter(Parameters.class, "code", new CodeDt("8495-4"))
|
||||
.andParameter("system", new UriDt("http://loinc.org"))
|
||||
.execute();
|
||||
//@formatter:off
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/1/$validate-code", capt.getAllValues().get(idx).getURI().toASCIIString());
|
||||
ourLog.info(extractBody(capt, idx));
|
||||
assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"code\"/><valueCode value=\"8495-4\"/></parameter><parameter><name value=\"system\"/><valueUri value=\"http://loinc.org\"/></parameter></Parameters>",extractBody(capt, idx));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPageNext() throws Exception {
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
|
@ -1424,6 +1427,21 @@ public class GenericClientDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderWhereWeForgotToSetTheContext() throws Exception {
|
||||
ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory(); // no ctx
|
||||
clientFactory.setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
|
||||
ourCtx.setRestfulClientFactory(clientFactory);
|
||||
|
||||
try {
|
||||
ourCtx.newRestfulGenericClient("http://localhost:8080/fhir");
|
||||
fail();
|
||||
} catch (IllegalStateException e) {
|
||||
assertEquals("ApacheRestfulClientFactory does not have FhirContext defined. This must be set via ApacheRestfulClientFactory#setFhirContext(FhirContext)", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadByUri() throws Exception {
|
||||
|
||||
|
@ -1605,6 +1623,88 @@ public class GenericClientDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPost() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/_search?_elements=identifier%2Cname", capt.getValue().getURI().toString());
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
assertThat(capt.getValue().getFirstHeader("user-agent").getValue(), not(emptyString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPostUseJson() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.encodedJson()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient/_search?"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_elements=identifier%2Cname"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_format=json"));
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.CT_FHIR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByString() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
@ -1765,88 +1865,6 @@ public class GenericClientDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPost() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertEquals("http://example.com/fhir/Patient/_search?_elements=identifier%2Cname", capt.getValue().getURI().toString());
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
assertThat(capt.getValue().getFirstHeader("user-agent").getValue(), not(emptyString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchByPostUseJson() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
||||
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_JSON + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
//@formatter:off
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.matches().value("james"))
|
||||
.elementsSubset("name", "identifier")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.encodedJson()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient/_search?"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_elements=identifier%2Cname"));
|
||||
assertThat(capt.getValue().getURI().toString(), containsString("_format=json"));
|
||||
|
||||
// assertThat(capt.getValue().getURI().toString(),
|
||||
// either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname")));
|
||||
|
||||
assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass());
|
||||
|
||||
ourLog.info(Arrays.asList(capt.getValue().getAllHeaders()).toString());
|
||||
ourLog.info(capt.getValue().toString());
|
||||
|
||||
HttpEntityEnclosingRequestBase v = (HttpEntityEnclosingRequestBase) capt.getValue();
|
||||
String req = IOUtils.toString(v.getEntity().getContent(), "UTF-8");
|
||||
assertEquals("name=james", req);
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase());
|
||||
assertEquals(Constants.CT_FHIR_JSON, capt.getValue().getFirstHeader("accept").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithLastUpdated() throws Exception {
|
||||
String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
|
||||
|
|
|
@ -304,7 +304,7 @@
|
|||
as well as a Maven plugin, and to use external
|
||||
sources. Thanks to Bill Denton for the pull
|
||||
request!
|
||||
</actiom>
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server now allows searching by token
|
||||
parameter using a system only and no code,
|
||||
|
@ -314,6 +314,19 @@
|
|||
was not clear in the spec and HAPI had different
|
||||
behaviour from the other reference servers.
|
||||
</action>
|
||||
<action type="add">
|
||||
Introduce a JAX-RS client provider which can be used instead of the
|
||||
default Apache HTTP Client provider to provide low level HTTP
|
||||
services to HAPI's REST client. See
|
||||
<![CDATA[<a href="./doc_rest_client_alternate_provider.html">JAX-RS & Alternate HTTP Client Providers</a>]]>
|
||||
for more information.
|
||||
<![CDATA[<br/><br/>]]>
|
||||
This is useful in cases where you have other non-FHIR REST clients
|
||||
using a JAX-RS provider and want to take advantage of the
|
||||
rest of the framework.
|
||||
<![CDATA[<br/><br/>]]>
|
||||
Thanks to Peter Van Houte from Agfa for the amazing work!
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.4" date="2016-02-04">
|
||||
<action type="add">
|
||||
|
@ -362,7 +375,7 @@
|
|||
<action type="add" issue="251">
|
||||
Introduce a JAX-RS version of the REST server, which can be used
|
||||
to deploy the same resource provider implementations which work
|
||||
on the existing REST server into a JAX-RS (Jersey) environment.
|
||||
on the existing REST server into a JAX-RS (e.g. Jersey) environment.
|
||||
Thanks to Peter Van Houte from Agfa for the amazing work!
|
||||
</action>
|
||||
<action type="add">
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<item name="Interceptors (client)" href="./doc_rest_client_interceptor.html"/>
|
||||
<item name="Client HTTP Configuration" href="./doc_rest_client_http_config.html"/>
|
||||
<item name="Client Examples" href="./doc_rest_client_examples.html"/>
|
||||
<item name="JAX-RS Client & Alternate HTTP Providers" href="./doc_rest_client_alternate_provider.html"/>
|
||||
</item>
|
||||
<item name="RESTful Server" href="./doc_rest_server.html" >
|
||||
<item name="Using RESTful Server" href="./doc_rest_server.html" />
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
|
||||
<properties>
|
||||
<title>JAX-RS & Alternate HTTP Client Providers</title>
|
||||
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
|
||||
<section name="JAX-RS & Alternate HTTP Client Providers">
|
||||
|
||||
<p>
|
||||
By default, the HAPI FHIR client uses the
|
||||
<a href="http://hc.apache.org/httpcomponents-client-ga/">Apache HTTP Client (HC)</a>
|
||||
as it's underlying HTTP provider. HC is a very powerful and efficient provider,
|
||||
so it is generally a good choice.
|
||||
</p>
|
||||
<p>
|
||||
It can be replaced however by providing an alternate implementation of
|
||||
<code><a href="./apidocs/ca/uhn/fhir/rest/client/IRestfulClientFactory.html">IRestfulClientFactory</a></code>
|
||||
to the <code>FhirContext</code>.
|
||||
</p>
|
||||
|
||||
<subsection name="JAX-RS">
|
||||
|
||||
<p>
|
||||
If you are using HAPI FHIR's client in an environment where other
|
||||
JAX-RS clients are being used, you may want to use the JAX-RS provider
|
||||
instead of the Apache HC provider.
|
||||
</p>
|
||||
<p>
|
||||
Using this provider is as simple as creating an instance and providing it
|
||||
to the context:
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="createClient"/>
|
||||
<param name="file" value="examples/src/main/java/example/JaxRsClient.java"/>
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Note that this provider is defined in the JAX-RS Server module, so you need
|
||||
to add the following dependency to your project in order for this to work:
|
||||
</p>
|
||||
<pre><![CDATA[<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>[version]</version>
|
||||
</dependency>]]></pre>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</document>
|
|
@ -22,16 +22,15 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
In many cases, the default configuration should suffice. However,
|
||||
if you require anything
|
||||
more sophisticated (username/password, HTTP
|
||||
proxy settings, etc.) you will need
|
||||
to configure the underlying
|
||||
client.
|
||||
In many cases, the default configuration should suffice. HAPI FHIR
|
||||
also encapsulates some of the more common configuration settings you
|
||||
might want to use (socket timesouts, proxy settings, etc.) so that these
|
||||
can be configured through HAPI's API without needing to understand the
|
||||
underlying HTTP Client library.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The underlying client configuration is provided by accessing the
|
||||
This configuration is provided by accessing the
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/client/IRestfulClientFactory.html">IRestfulClientFactory</a>
|
||||
class from the FhirContext.
|
||||
</p>
|
||||
|
@ -39,8 +38,10 @@
|
|||
<p>
|
||||
Note that individual requests and responses
|
||||
can be tweaked using
|
||||
<a href="./doc_rest_client_interceptor.html">Client Interceptors</a>
|
||||
.
|
||||
<a href="./doc_rest_client_interceptor.html">Client Interceptors.</a>
|
||||
This approach is generally useful for configuration involving
|
||||
tweaking the HTTP request/response, such as adding authorization headers
|
||||
or logging.
|
||||
</p>
|
||||
|
||||
<subsection name="Setting Socket Timeouts">
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<li><a href="./doc_rest_client_interceptor.html">Interceptors (client)</a></li>
|
||||
<li><a href="./doc_rest_client_http_config.html">Client HTTP Configuration</a></li>
|
||||
<li><a href="./doc_rest_client_examples.html">Client Examples</a></li>
|
||||
<li><a href="./doc_rest_client_alternate_provider.html">JAX-RS Client & Alternate HTTP Providers</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>RESTful Server</h4>
|
||||
|
|
Loading…
Reference in New Issue