Merge branch 'master' of https://github.com/hugosoares/hapi-fhir into hugosoares-master
This commit is contained in:
commit
9501ea0961
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -19,9 +21,42 @@ package ca.uhn.fhir.rest.gclient;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IOperation extends IBaseOn<IOperationUnnamed> {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This operation is called <b><a href="https://www.hl7.org/fhir/messaging.html">$process-message</a></b> as defined by FHIR
|
||||
* DSTU2.<br><br>
|
||||
* Usage :<br>
|
||||
* <code>
|
||||
* <pre>
|
||||
* Bundle response = client
|
||||
* .operation()
|
||||
* .onServer()
|
||||
* .processMessage()
|
||||
* .setResponseUrlParam("http://myserver/fhir")
|
||||
* .setMessageBundle(msgBundle)
|
||||
* .synchronous(Bundle.class)
|
||||
* .execute();
|
||||
*
|
||||
* //if you want to send an async message
|
||||
*
|
||||
* OperationOutcome response = client
|
||||
* .operation()
|
||||
* .onServer()
|
||||
* .processMessage()
|
||||
* .setResponseUrlParam("http://myserver/fhir")
|
||||
* .setMessageBundle(msgBundle)
|
||||
* .asynchronous(OperationOutcome.class)
|
||||
* .execute();
|
||||
*
|
||||
* </pre>
|
||||
* </code>
|
||||
*
|
||||
* @see <a href="https://www.hl7.org/fhir/messaging.html">2.4 Messaging
|
||||
* using FHIR Resources</a>
|
||||
*
|
||||
* @return An interface that defines the operation related to sending
|
||||
* Messages to a Messaging Server
|
||||
*/
|
||||
IOperationProcessMsg processMessage();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author HGS
|
||||
*/
|
||||
public interface IOperationProcessMsg{
|
||||
|
||||
/**
|
||||
* Set the Message Bundle to POST to the messaging server.<br>
|
||||
* After this call you must choose either the method synchronous or asynchronous to set the processing mode.
|
||||
*
|
||||
* @param <R>
|
||||
* @param theMsgBundle A Bundle of type message
|
||||
* @return
|
||||
*/
|
||||
<R extends IBaseResource> IOperationProcessMsgMode<R> setMessageBundle(IBaseBundle theMsgBundle);
|
||||
|
||||
/**
|
||||
* An optional query parameter indicating that responses from the receiving server should be sent to this url
|
||||
*
|
||||
* @param respondToUri The receiving endpoint to witch server response messages should be sent.
|
||||
* @return
|
||||
*/
|
||||
IOperationProcessMsg setResponseUrlParam(String respondToUri);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2017 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
public interface IOperationProcessMsgMode<T extends IBaseResource> extends IClientExecutable<IOperationProcessMsgMode<T>, T> {
|
||||
|
||||
<R extends IBaseResource> IOperationProcessMsgMode<R> asynchronous(Class<R> theResponseClass);
|
||||
|
||||
<R extends IBaseResource> IOperationProcessMsgMode<R> synchronous(Class<R> theResponseClass);
|
||||
}
|
|
@ -24,5 +24,4 @@ package ca.uhn.fhir.rest.gclient;
|
|||
public interface IOperationUnnamed {
|
||||
|
||||
IOperationUntyped named(String theName);
|
||||
|
||||
}
|
||||
|
|
|
@ -321,6 +321,23 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
myDescription = theDescription;
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createProcessMsgInvocation(FhirContext theContext, String theOperationName, IBaseBundle theInput, Map<String, List<String>> urlParams) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
if (b.length() > 0) {
|
||||
b.append('/');
|
||||
}
|
||||
if (!theOperationName.startsWith("$")) {
|
||||
b.append("$");
|
||||
}
|
||||
b.append(theOperationName);
|
||||
|
||||
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(urlParams,b, b.indexOf("?") == -1);
|
||||
|
||||
return new HttpPostClientInvocation(theContext, theInput, b.toString());
|
||||
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createOperationInvocation(FhirContext theContext, String theResourceName, String theId, String theOperationName, IBaseParameters theInput, boolean theUseHttpGet) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (theResourceName != null) {
|
||||
|
|
|
@ -146,6 +146,9 @@ public class Constants {
|
|||
public static final String PARAM_TAGS = "_tags";
|
||||
public static final String PARAM_TEXT = "_text";
|
||||
public static final String PARAM_VALIDATE = "_validate";
|
||||
public static final String PARAM_ASYNC = "async"; //Used in messaging
|
||||
public static final String PARAM_RESPONSE_URL = "response-url"; //Used in messaging
|
||||
public static final String EXTOP_PROCESS_MESSAGE = "$process-message"; //Used in messaging
|
||||
public static final String PARAMQUALIFIER_MISSING = ":missing";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
|
||||
|
|
|
@ -190,7 +190,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>${argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>-Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
||||
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.MessageHeader;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.ResponseTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MessageClientDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MessageClientDstu2Test.class);
|
||||
private FhirContext ourCtx;
|
||||
private HttpClient myHttpClient;
|
||||
|
||||
private HttpResponse myHttpResponse;
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
|
||||
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
|
||||
ourCtx.setRestfulClientFactory(new ApacheRestfulClientFactory(ourCtx));
|
||||
ourCtx.getRestfulClientFactory().setConnectionRequestTimeout(10000);
|
||||
ourCtx.getRestfulClientFactory().setConnectTimeout(10000);
|
||||
ourCtx.getRestfulClientFactory().setPoolMaxPerRoute(100);
|
||||
ourCtx.getRestfulClientFactory().setPoolMaxTotal(100);
|
||||
|
||||
ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
|
||||
|
||||
System.setProperty(BaseClient.HAPI_CLIENT_KEEPRESPONSES, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMessageAsync() throws Exception {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDiagnostics("FOOBAR");
|
||||
final String msg = ourCtx.newJsonParser().encodeResourceToString(oo);
|
||||
|
||||
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()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.getRestfulClientFactory().newGenericClient("http://192.168.4.93:83/fhirServer");
|
||||
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
|
||||
// Create the input message to pass to the server
|
||||
final Bundle msgBundle = getMessageBundle(
|
||||
"myEvent", "Test Event",
|
||||
"MySource", "http://myServer/fhir/", "MyDestination", "http://myDestinationServer/fhir/");
|
||||
|
||||
// Invoke $process-message
|
||||
OperationOutcome response = client
|
||||
.operation()
|
||||
.processMessage()
|
||||
.setResponseUrlParam("http://myserver/fhir")
|
||||
.setMessageBundle(msgBundle)
|
||||
.asynchronous(OperationOutcome.class)
|
||||
.execute();
|
||||
|
||||
//System.out.println(response);
|
||||
assertEquals("http://192.168.4.93:83/fhirServer/$process-message?async=true&response-url=http%3A%2F%2Fmyserver%2Ffhir&_format=json", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
assertEquals("POST", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
//assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", extractBody(capt, 0));
|
||||
//assertNotNull(response.getOperationOutcome());
|
||||
assertEquals("FOOBAR", ((OperationOutcome) response).getIssueFirstRep().getDiagnosticsElement().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMessage() throws Exception {
|
||||
final Bundle msgBundleResponse = getMessageBundle(
|
||||
"myEvent", "Test Event",
|
||||
"MySource", "http://myServer/fhir/", "MyDestination", "http://myDestinationServer/fhir/");
|
||||
((MessageHeader) msgBundleResponse.getEntryFirstRep().getResource()).getResponse().setCode(ResponseTypeEnum.OK);
|
||||
final String msg = ourCtx.newJsonParser().encodeResourceToString(msgBundleResponse);
|
||||
|
||||
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()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
}
|
||||
});
|
||||
|
||||
IGenericClient client = ourCtx.getRestfulClientFactory().newGenericClient("http://192.168.4.93:83/fhirServer");
|
||||
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
|
||||
// Create the input message to pass to the server
|
||||
final Bundle msgBundle = getMessageBundle(
|
||||
"myEvent", "Test Event",
|
||||
"MySource", "http://myServer/fhir/", "MyDestination", "http://myDestinationServer/fhir/");
|
||||
|
||||
// Invoke $process-message
|
||||
Bundle response = client
|
||||
.operation()
|
||||
.processMessage()
|
||||
.setMessageBundle(msgBundle)
|
||||
.synchronous(Bundle.class)
|
||||
.execute();
|
||||
|
||||
//System.out.println(response);
|
||||
assertEquals("http://192.168.4.93:83/fhirServer/$process-message?async=false&_format=json", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||
assertEquals("POST", capt.getAllValues().get(0).getRequestLine().getMethod());
|
||||
//assertEquals("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", extractBody(capt, 0));
|
||||
//assertNotNull(response.getOperationOutcome());
|
||||
assertEquals("MessageHeader", ((Bundle) response).getEntryFirstRep().getResource().getResourceName());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Criar um FHIR Message Bundle pre-preenchido com os parametros
|
||||
*
|
||||
* @param eventCode
|
||||
* @param eventDisplay
|
||||
* @param sourceName
|
||||
* @param sourceEnpoint
|
||||
* @param destinationName
|
||||
* @param destinationEndpoint
|
||||
* @return Message Bundle
|
||||
*/
|
||||
public static Bundle getMessageBundle(String eventCode, String eventDisplay, String sourceName, String sourceEnpoint, String destinationName, String destinationEndpoint) {
|
||||
/*
|
||||
Init Bundle
|
||||
*/
|
||||
Bundle msgBundle = new Bundle();
|
||||
msgBundle.getMeta().setLastUpdated(new Date());
|
||||
msgBundle.setType(BundleTypeEnum.MESSAGE); //Document Type
|
||||
msgBundle.setId(UUID.randomUUID().toString()); // Random ID
|
||||
/*
|
||||
Init MessageHeader
|
||||
*/
|
||||
MessageHeader msh = new MessageHeader();
|
||||
msh.setId(UUID.randomUUID().toString());
|
||||
msh.setTimestampWithMillisPrecision(new Date());
|
||||
msh.getEvent().setSystem("http://mybServer/fhir/events");
|
||||
msh.getEvent().setCode(eventCode);
|
||||
msh.getEvent().setDisplay(eventDisplay);
|
||||
msh.getSource().setName(sourceName);
|
||||
msh.getSource().setEndpoint(sourceEnpoint);
|
||||
msh.getDestinationFirstRep().setName(destinationName);
|
||||
msh.getDestinationFirstRep().setEndpoint(destinationEndpoint);
|
||||
Bundle.Entry entry = new Bundle.Entry();
|
||||
entry.setFullUrl("http://mybase/fhirServer/Bundle/" + msh.getId().getValue());
|
||||
entry.setResource(msh);
|
||||
msgBundle.addEntry(entry);
|
||||
return msgBundle;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue