Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jp cds hooks carveout #6772

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions hapi-fhir-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,6 @@
<artifactId>hapi-fhir-storage-batch2-jobs</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hapi-fhir-storage-cr</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hapi-fhir-storage-mdm</artifactId>
Expand Down
5 changes: 0 additions & 5 deletions hapi-fhir-jacoco/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,6 @@
<artifactId>hapi-fhir-storage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-storage-cr</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
</profiles>
Expand Down
6 changes: 3 additions & 3 deletions hapi-fhir-server-cds-hooks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-storage-cr</artifactId>
<version>${project.version}</version>
<groupId>org.opencds.cqf.fhir</groupId>
<artifactId>cqf-fhir-storage-cr</artifactId>
<version>${clinical-reasoning.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ public interface ICdsServiceRegistry {
*/
CdsServiceFeedbackJson callFeedback(String theServiceId, CdsServiceFeedbackJson theCdsServiceFeedbackJson);

// TODO: LD: javadoc?
void registerService(
String theServiceId,
CdsServiceJson theCdsServiceJson,
boolean theAllowAutoFhirClientPrefetch,
String theModuleId);

/**
* Register a new CDS Service with the endpoint.
*
Expand All @@ -72,14 +79,6 @@ void registerService(
boolean theAllowAutoFhirClientPrefetch,
String theModuleId);

/**
* Register a new Clinical Reasoning CDS Service with the endpoint.
*
* @param theServiceId the id of the service PlanDefinition
* @return the service was registered
*/
boolean registerCrService(String theServiceId);

/**
* Remove registered CDS service with the service ID, only removes dynamically registered service
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,13 @@ public ICdsServiceRegistry cdsServiceRegistry(
CdsHooksContextBooter theCdsHooksContextBooter,
CdsPrefetchSvc theCdsPrefetchSvc,
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY) ObjectMapper theObjectMapper,
ICdsCrServiceFactory theCdsCrServiceFactory,
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory,
FhirContext theFhirContext) {
final CdsServiceRequestJsonDeserializer cdsServiceRequestJsonDeserializer =
new CdsServiceRequestJsonDeserializer(theFhirContext, theObjectMapper);
return new CdsServiceRegistryImpl(
theCdsHooksContextBooter,
theCdsPrefetchSvc,
theObjectMapper,
theCdsCrServiceFactory,
theCrDiscoveryServiceFactory,
cdsServiceRequestJsonDeserializer);
}

Expand Down Expand Up @@ -187,11 +183,17 @@ public ICrDiscoveryServiceFactory crDiscoveryServiceFactory(
}

@Bean
public CdsServiceInterceptor cdsServiceInterceptor() {
public CdsServiceInterceptor cdsServiceInterceptor(
CdsServiceRegistryImpl theCdsServiceRegistry,
ICrDiscoveryServiceFactory theDiscoveryServiceFactory) {
if (myResourceChangeListenerRegistry == null) {
return null;
}
CdsServiceInterceptor listener = new CdsServiceInterceptor();
// TODO: LD: how do we get the module ID here?
final String fakeModuleId = "cdsHooks";
// TODO: LD: how do we determine if this is true or false?
final boolean isAllowFhirClientPrefetch = false;
final CdsServiceInterceptor listener = new CdsServiceInterceptor(theCdsServiceRegistry, fakeModuleId, isAllowFhirClientPrefetch, theDiscoveryServiceFactory);
myResourceChangeListenerRegistry.registerResourceResourceChangeListener(
PLAN_DEFINITION_RESOURCE_NAME, SearchParameterMap.newSynchronous(), listener, 1000);
return listener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -35,8 +33,6 @@
import java.util.Map;
import java.util.function.Function;

import static ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrConstants.CDS_CR_MODULE_ID;

public class CdsServiceCache {
static final Logger ourLog = LoggerFactory.getLogger(CdsServiceCache.class);
final Map<String, ICdsMethod> myServiceMap = new LinkedHashMap<>();
Expand All @@ -61,32 +57,25 @@ public void registerDynamicService(
CdsServiceJson theCdsServiceJson,
boolean theAllowAutoFhirClientPrefetch,
String theModuleId) {
if (!isCdsServiceAlreadyRegistered(theServiceId, theModuleId)) {
final CdsDynamicPrefetchableServiceMethod cdsDynamicPrefetchableServiceMethod =
new CdsDynamicPrefetchableServiceMethod(
theCdsServiceJson, theMethod, theAllowAutoFhirClientPrefetch);
myServiceMap.put(theServiceId, cdsDynamicPrefetchableServiceMethod);
myCdsServiceJson.addService(theCdsServiceJson);
}
final CdsDynamicPrefetchableServiceMethod cdsDynamicPrefetchableServiceMethod =
new CdsDynamicPrefetchableServiceMethod(
theCdsServiceJson, theMethod, theAllowAutoFhirClientPrefetch);
registerDynamicService(theServiceId, cdsDynamicPrefetchableServiceMethod, theCdsServiceJson, theModuleId);
}

public void registerCrService(
public void registerDynamicService(
String theServiceId,
ICrDiscoveryServiceFactory theDiscoveryServiceFactory,
ICdsCrServiceFactory theCrServiceFactory) {
if (!isCdsServiceAlreadyRegistered(theServiceId, CDS_CR_MODULE_ID)) {
CdsServiceJson cdsServiceJson =
theDiscoveryServiceFactory.create(theServiceId).resolveService();
if (cdsServiceJson != null) {
final CdsCrServiceMethod cdsCrServiceMethod =
new CdsCrServiceMethod(cdsServiceJson, theCrServiceFactory);
myServiceMap.put(theServiceId, cdsCrServiceMethod);
myCdsServiceJson.addService(cdsServiceJson);
ourLog.info("Created service for {}", theServiceId);
}
ICdsMethod theMethod,
CdsServiceJson theCdsServiceJson,
String theModuleId) {
if (!isCdsServiceAlreadyRegistered(theServiceId, theModuleId)) {
myServiceMap.put(theServiceId, theMethod);
myCdsServiceJson.addService(theCdsServiceJson);
ourLog.info("Created service for {}", theServiceId);
}
}


public void registerFeedback(String theServiceId, Object theServiceBean, Method theMethod) {
final CdsFeedbackMethod cdsFeedbackMethod = new CdsFeedbackMethod(theServiceBean, theMethod);
myFeedbackMap.put(theServiceId, cdsFeedbackMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,36 @@
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
import ca.uhn.hapi.fhir.cdshooks.serializer.CdsServiceRequestJsonDeserializer;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.ICdsCrServiceFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
import ca.uhn.hapi.fhir.cdshooks.svc.prefetch.CdsPrefetchSvc;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Nonnull;
import jakarta.annotation.PostConstruct;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.function.Function;

public class CdsServiceRegistryImpl implements ICdsServiceRegistry {
private static final Logger ourLog = LoggerFactory.getLogger(CdsServiceRegistryImpl.class);
private final CdsServiceRequestJsonDeserializer myCdsServiceRequestJsonDeserializer;
private CdsServiceCache myServiceCache;

private final CdsServiceRequestJsonDeserializer myCdsServiceRequestJsonDeserializer;
private final CdsHooksContextBooter myCdsHooksContextBooter;
private final CdsPrefetchSvc myCdsPrefetchSvc;
private final ObjectMapper myObjectMapper;
private final ICdsCrServiceFactory myCdsCrServiceFactory;
private final ICrDiscoveryServiceFactory myCrDiscoveryServiceFactory;

private CdsServiceCache myServiceCache;

public CdsServiceRegistryImpl(
CdsHooksContextBooter theCdsHooksContextBooter,
CdsPrefetchSvc theCdsPrefetchSvc,
ObjectMapper theObjectMapper,
ICdsCrServiceFactory theCdsCrServiceFactory,
ICrDiscoveryServiceFactory theCrDiscoveryServiceFactory,
CdsServiceRequestJsonDeserializer theCdsServiceRequestJsonDeserializer) {
myCdsHooksContextBooter = theCdsHooksContextBooter;
myCdsPrefetchSvc = theCdsPrefetchSvc;
myObjectMapper = theObjectMapper;
myCdsCrServiceFactory = theCdsCrServiceFactory;
myCrDiscoveryServiceFactory = theCrDiscoveryServiceFactory;
myCdsServiceRequestJsonDeserializer = theCdsServiceRequestJsonDeserializer;
}

Expand All @@ -87,10 +80,7 @@ public CdsServiceResponseJson callService(String theServiceId, Object theCdsServ
final CdsServiceJson cdsServiceJson = getCdsServiceJson(theServiceId);
final CdsServiceRequestJson deserializedRequest =
myCdsServiceRequestJsonDeserializer.deserialize(cdsServiceJson, theCdsServiceRequestJson);
ICdsServiceMethod serviceMethod = (ICdsServiceMethod) getCdsServiceMethodOrThrowException(theServiceId);
myCdsPrefetchSvc.augmentRequest(deserializedRequest, serviceMethod);
Object response = serviceMethod.invoke(myObjectMapper, deserializedRequest, theServiceId);
return encodeServiceResponse(theServiceId, response);
return callService(theServiceId, deserializedRequest);
}

@Override
Expand All @@ -100,6 +90,20 @@ public CdsServiceFeedbackJson callFeedback(String theServiceId, CdsServiceFeedba
return encodeFeedbackResponse(theServiceId, response);
}

@Override
public void registerService(
String theServiceId,
CdsServiceJson theCdsServiceJson,
boolean theAllowAutoFhirClientPrefetch,
String theModuleId) {
registerService(
theServiceId,
buildRequestToResponseFunction(theServiceId),
theCdsServiceJson,
theAllowAutoFhirClientPrefetch,
theModuleId);
}

@Override
public void registerService(
String theServiceId,
Expand All @@ -114,20 +118,9 @@ public void registerService(
theServiceId, theServiceFunction, theCdsServiceJson, theAllowAutoFhirClientPrefetch, theModuleId);
}

@Override
public boolean registerCrService(String theServiceId) {
try {
myServiceCache.registerCrService(theServiceId, myCrDiscoveryServiceFactory, myCdsCrServiceFactory);
} catch (Exception e) {
ourLog.error("Error received during CR CDS Service registration: {}", e.getMessage());
return false;
}
return true;
}

@Override
public void unregisterService(String theServiceId, String theModuleId) {
Validate.notNull(theServiceId);
Objects.requireNonNull(theServiceId);

ICdsMethod activeService = myServiceCache.unregisterServiceMethod(theServiceId, theModuleId);
if (activeService != null) {
Expand Down Expand Up @@ -182,6 +175,18 @@ CdsServiceFeedbackJson encodeFeedbackResponse(String theServiceId, Object theRes
}
}

private Function<CdsServiceRequestJson, CdsServiceResponseJson> buildRequestToResponseFunction(String theServiceId) {
return cdsServiceRequestJson -> callService(theServiceId, cdsServiceRequestJson);
}

@Nonnull
private CdsServiceResponseJson callService(String theServiceId, CdsServiceRequestJson deserializedRequest) {
ICdsServiceMethod serviceMethod = (ICdsServiceMethod) getCdsServiceMethodOrThrowException(theServiceId);
myCdsPrefetchSvc.augmentRequest(deserializedRequest, serviceMethod);
Object response = serviceMethod.invoke(myObjectMapper, deserializedRequest, theServiceId);
return encodeServiceResponse(theServiceId, response);
}

private CdsServiceResponseJson buildResponseFromImplementation(String theServiceId, Object theResult) {
try {
return (CdsServiceResponseJson) theResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
import ca.uhn.fhir.jpa.cache.IResourceChangeListener;
import ca.uhn.fhir.jpa.cache.ResourceChangeEvent;
import ca.uhn.hapi.fhir.cdshooks.svc.CdsServiceRegistryImpl;
import ca.uhn.hapi.fhir.cdshooks.svc.cr.discovery.ICrDiscoveryServiceFactory;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -38,10 +38,21 @@
public class CdsServiceInterceptor implements IResourceChangeListener {
static final Logger ourLog = LoggerFactory.getLogger(CdsServiceInterceptor.class);

@Autowired
CdsServiceRegistryImpl myCdsServiceRegistry;
private final CdsServiceRegistryImpl myCdsServiceRegistry;
private final String myModuleId;
private final boolean myAllowFhirClientPrefetch;
private final ICrDiscoveryServiceFactory myDiscoveryServiceFactory;

public CdsServiceInterceptor() {}
public CdsServiceInterceptor(
CdsServiceRegistryImpl theCdsServiceRegistry,
String theModuleId,
boolean theAllowFhirClientPrefetch,
ICrDiscoveryServiceFactory theDiscoveryServiceFactory) {
myCdsServiceRegistry = theCdsServiceRegistry;
myModuleId = theModuleId;
myAllowFhirClientPrefetch = theAllowFhirClientPrefetch;
myDiscoveryServiceFactory = theDiscoveryServiceFactory;
}

@Override
public void handleInit(Collection<IIdType> theResourceIds) {
Expand Down Expand Up @@ -69,7 +80,12 @@ public void handleChange(IResourceChangeEvent theResourceChangeEvent) {
private void insert(List<IIdType> theCreatedIds) {
for (IIdType id : theCreatedIds) {
try {
myCdsServiceRegistry.registerCrService(id.getIdPart());
final String serviceId = id.getIdPart();
myCdsServiceRegistry.registerService(
serviceId,
myDiscoveryServiceFactory.create(serviceId).resolveService(),
myAllowFhirClientPrefetch,
myModuleId);
} catch (Exception e) {
ourLog.info(String.format("Failed to create service for %s", id.getIdPart()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ class CdsServiceRegistryImplTest {
@Mock
private CdsPrefetchSvc myCdsPrefetchSvc;
@Mock
private ICdsCrServiceFactory myCdsCrServiceFactory;
@Mock
private ICrDiscoveryServiceFactory myCrDiscoveryServiceFactory;
@Mock
private CdsServiceCache myCdsServiceCache;
@Mock
private CdsServiceRequestJsonDeserializer myCdsServiceRequestJsonDeserializer;
Expand All @@ -40,7 +36,7 @@ class CdsServiceRegistryImplTest {

@BeforeEach()
void setup() {
myFixture = new CdsServiceRegistryImpl(myCdsHooksContextBooter, myCdsPrefetchSvc, myObjectMapper, myCdsCrServiceFactory, myCrDiscoveryServiceFactory, myCdsServiceRequestJsonDeserializer);
myFixture = new CdsServiceRegistryImpl(myCdsHooksContextBooter, myCdsPrefetchSvc, myObjectMapper, myCdsServiceRequestJsonDeserializer);
}

@Test
Expand Down
Loading
Loading