Resolve crash in InMemory SP resolver for empty source (#2150)

* Resolve crash in InMemory SP resolver for empty source

* Add changelog
This commit is contained in:
James Agnew 2020-10-28 14:30:32 -04:00 committed by GitHub
parent 6ccb7c8312
commit 5e8ec8d6f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 10 deletions

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 2150
title: "The In Memory search matcher (used for Subscriptions) could crash if a subscription was registered using the
`_source` search parameter, and a resource was processed with no source value. This has been corrected."

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.searchparam.util;
import ca.uhn.fhir.rest.api.Constants;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.left;
/*
@ -35,19 +36,19 @@ public class SourceParam {
private final String myRequestId;
public SourceParam(String theParameterValue) {
myParameterValue = theParameterValue;
myParameterValue = defaultString(theParameterValue);
String requestId;
int lastHashValueIndex = theParameterValue.lastIndexOf('#');
int lastHashValueIndex = myParameterValue.lastIndexOf('#');
if (lastHashValueIndex == -1) {
mySourceUri = theParameterValue;
mySourceUri = myParameterValue;
requestId = null;
} else {
if (lastHashValueIndex == 0) {
mySourceUri = null;
} else {
mySourceUri = theParameterValue.substring(0, lastHashValueIndex);
mySourceUri = myParameterValue.substring(0, lastHashValueIndex);
}
requestId = theParameterValue.substring(lastHashValueIndex + 1);
requestId = myParameterValue.substring(lastHashValueIndex + 1);
}
myRequestId = left(requestId, Constants.REQUEST_ID_LENGTH);
}

View File

@ -50,6 +50,7 @@ public class InMemoryResourceMatcherR5Test {
private static final String SOURCE_URI = "urn:source:0";
private static final String REQUEST_ID = "a_request_id";
private static final String TEST_SOURCE = SOURCE_URI + "#" + REQUEST_ID;
@MockBean
ISearchParamRegistry mySearchParamRegistry;
@Autowired
@ -100,6 +101,27 @@ public class InMemoryResourceMatcherR5Test {
}
}
@Test
public void testSupportedSource_ResourceWithNoSourceValue() {
myObservation.getMeta().getSourceElement().setValue(null);
{
InMemoryMatchResult result = myInMemoryResourceMatcher.match(Constants.PARAM_SOURCE + "=" + TEST_SOURCE, myObservation, mySearchParams);
assertFalse(result.matched());
}
{
InMemoryMatchResult result = myInMemoryResourceMatcher.match(Constants.PARAM_SOURCE + "=" + SOURCE_URI, myObservation, mySearchParams);
assertFalse(result.matched());
}
{
InMemoryMatchResult result = myInMemoryResourceMatcher.match(Constants.PARAM_SOURCE + "=" + REQUEST_ID, myObservation, mySearchParams);
assertFalse(result.matched());
}
{
InMemoryMatchResult result = myInMemoryResourceMatcher.match(Constants.PARAM_SOURCE + "=#" + REQUEST_ID, myObservation, mySearchParams);
assertFalse(result.matched());
}
}
@Test
public void testUnsupportedChained() {
InMemoryMatchResult result = myInMemoryResourceMatcher.match("encounter.class=FOO", myObservation, mySearchParams);

View File

@ -4,11 +4,9 @@ import ca.uhn.fhir.jpa.subscription.channel.api.IChannelReceiver;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.SubscribableChannel;
import javax.annotation.PreDestroy;
@ -35,8 +33,8 @@ import static ca.uhn.fhir.jpa.subscription.match.matcher.subscriber.Subscription
*/
public class MatchingQueueSubscriberLoader {
protected IChannelReceiver myMatchingChannel;
private Logger ourLog = LoggerFactory.getLogger(MatchingQueueSubscriberLoader.class);
@Autowired
private SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
@Autowired
@ -46,8 +44,6 @@ public class MatchingQueueSubscriberLoader {
@Autowired
private SubscriptionActivatingSubscriber mySubscriptionActivatingSubscriber;
protected IChannelReceiver myMatchingChannel;
@EventListener(classes = {ContextRefreshedEvent.class})
public void handleContextRefreshEvent() {
if (myMatchingChannel == null) {