Skip to content

Commit

Permalink
Merge eb2d21a into fe37c87
Browse files Browse the repository at this point in the history
  • Loading branch information
javajeff committed Dec 23, 2017
2 parents fe37c87 + eb2d21a commit a6c0d9a
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 29 deletions.
Expand Up @@ -2105,14 +2105,14 @@ public IUpdateExecutable prefer(PreferReturnEnum theReturn) {

@Override
public IUpdateTyped resource(IBaseResource theResource) {
Validate.notNull(theResource, "Resource can not be null");
//Validate.notNull(theResource, "Resource can not be null");
myResource = theResource;
return this;
}

@Override
public IUpdateTyped resource(String theResourceBody) {
Validate.notBlank(theResourceBody, "Body can not be null or blank");
//Validate.notBlank(theResourceBody, "Body can not be null or blank");
myResourceBody = theResourceBody;
return this;
}
Expand Down
Expand Up @@ -98,11 +98,7 @@ protected void validateChannelEndpoint(Subscription theResource) {
}

protected void validateChannelPayload(Subscription theResource) {
if (isBlank(theResource.getChannel().getPayload())) {
throw new UnprocessableEntityException("Subscription.channel.payload must be populated for rest-hook subscriptions");
}

if (EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
if (!isBlank(theResource.getChannel().getPayload()) && EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getChannel().getPayload());
}
}
Expand Down
Expand Up @@ -99,11 +99,7 @@ protected void validateChannelEndpoint(Subscription theResource) {
}

protected void validateChannelPayload(Subscription theResource) {
if (isBlank(theResource.getChannel().getPayload())) {
throw new UnprocessableEntityException("Subscription.channel.payload must be populated for rest-hook subscriptions");
}

if (EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
if (!isBlank(theResource.getChannel().getPayload()) && EncodingEnum.forContentType(theResource.getChannel().getPayload()) == null) {
throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getChannel().getPayload());
}
}
Expand Down
Expand Up @@ -20,24 +20,26 @@
* #L%
*/

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.subscription.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.gclient.IClientExecutable;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

Expand All @@ -54,10 +56,38 @@ protected void deliverPayload(ResourceDeliveryMessage theMsg, CanonicalSubscript
IClientExecutable<?, ?> operation;
switch (theMsg.getOperationType()) {
case CREATE:
operation = theClient.update().resource(payloadResource);
if (payloadResource == null || payloadResource.isEmpty()) {
if (thePayloadType != null ) {
operation = theClient.create().resource(payloadResource);
} else {
sendNotification(theMsg);
return;
}
} else {
if (thePayloadType != null ) {
operation = theClient.update().resource(payloadResource);
} else {
sendNotification(theMsg);
return;
}
}
break;
case UPDATE:
operation = theClient.update().resource(payloadResource);
if (payloadResource == null || payloadResource.isEmpty()) {
if (thePayloadType != null ) {
operation = theClient.create().resource(payloadResource);
} else {
sendNotification(theMsg);
return;
}
} else {
if (thePayloadType != null ) {
operation = theClient.update().resource(payloadResource);
} else {
sendNotification(theMsg);
return;
}
}
break;
case DELETE:
operation = theClient.delete().resourceById(theMsg.getPayloadId(getContext()));
Expand All @@ -67,11 +97,19 @@ protected void deliverPayload(ResourceDeliveryMessage theMsg, CanonicalSubscript
return;
}

operation.encoded(thePayloadType);
if (thePayloadType != null) {
operation.encoded(thePayloadType);
}

ourLog.info("Delivering {} rest-hook payload {} for {}", theMsg.getOperationType(), payloadResource.getIdElement().toUnqualified().getValue(), theSubscription.getIdElement(getContext()).toUnqualifiedVersionless().getValue());

operation.execute();
try {
operation.execute();
} catch (ResourceNotFoundException e) {
ourLog.error("Cannot reach "+ theMsg.getSubscription().getEndpointUrl());
e.printStackTrace();
throw e;
}
}

@Override
Expand All @@ -83,13 +121,14 @@ public void handleMessage(ResourceDeliveryMessage theMessage) throws MessagingEx

// Grab the payload type (encoding mimetype) from the subscription
String payloadString = subscription.getPayloadString();
payloadString = StringUtils.defaultString(payloadString, Constants.CT_FHIR_XML_NEW);
if (payloadString.contains(";")) {
payloadString = payloadString.substring(0, payloadString.indexOf(';'));
EncodingEnum payloadType = null;
if(payloadString != null) {
if (payloadString.contains(";")) {
payloadString = payloadString.substring(0, payloadString.indexOf(';'));
}
payloadString = payloadString.trim();
payloadType = EncodingEnum.forContentType(payloadString);
}
payloadString = payloadString.trim();
EncodingEnum payloadType = EncodingEnum.forContentType(payloadString);
payloadType = ObjectUtils.defaultIfNull(payloadType, EncodingEnum.XML);

// Create the client request
getContext().getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
Expand All @@ -109,4 +148,23 @@ public void handleMessage(ResourceDeliveryMessage theMessage) throws MessagingEx
deliverPayload(theMessage, subscription, payloadType, client);
}

/**
* Sends a POST notification without a payload
* @param theMsg
*/
protected void sendNotification(ResourceDeliveryMessage theMsg) {
FhirContext context= getContext();
Map<String, List<String>> params = new HashMap();
List<Header> headers = new ArrayList<>();
StringBuilder url = new StringBuilder(theMsg.getSubscription().getEndpointUrl());
IHttpClient client = context.getRestfulClientFactory().getHttpClient(url, params, "", RequestTypeEnum.POST, headers);
IHttpRequest request = client.createParamRequest(context, params, null);
try {
IHttpResponse response = request.execute();
} catch (IOException e) {
ourLog.error("Error trying to reach "+ theMsg.getSubscription().getEndpointUrl());
e.printStackTrace();
throw new ResourceNotFoundException(e.getMessage());
}
}
}
Expand Up @@ -34,7 +34,7 @@
*/
public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {

private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu2Test.class);
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestHookTestDstu3Test.class);
private static List<Observation> ourCreatedObservations = Lists.newArrayList();
private static int ourListenerPort;
private static RestfulServer ourListenerRestServer;
Expand Down Expand Up @@ -311,6 +311,25 @@ public void testRestHookSubscriptionApplicationXmlJson() throws Exception {
assertEquals(Constants.CT_FHIR_XML_NEW, ourContentTypes.get(0));
}

@Test
public void testRestHookSubscriptionWithoutPayload() throws Exception {
String payload = "";

String code = "1000000050";
String criteria1 = "Observation?code=SNOMED-CT|" + code;
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111";

Subscription subscription1 = createSubscription(criteria1, payload, ourListenerServerBase);
Subscription subscription2 = createSubscription(criteria2, payload, ourListenerServerBase);

Observation observation1 = sendObservation(code, "SNOMED-CT");

// Should see 1 subscription notification, but no payload
waitForQueueToDrain();
waitForSize(0, ourCreatedObservations);
waitForSize(0, ourUpdatedObservations);
}

// TODO: Reenable this
@Test
@Ignore
Expand Down

0 comments on commit a6c0d9a

Please sign in to comment.