Feature/cds config (#857)
* Added MCP support using SSE on http://localhost:8080/sse * Reverted change that IntelliJ complains about * Pre-rework * Cleaned up the code a fair bit * Renamed * Renamed * Running spotless * Reuse FhirContext in result serialization to make MCP server work with R5 * Added support for transactions * PoC tool for CDS Hooks * some cleanup * Upgrade of model protocol * Added comments * Removed field injection ... CDS to be changed to AutoConfig eventually * Adjusted to new builder pattern * Update src/main/java/ca/uhn/fhir/rest/server/MCPBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * A bit of restructuring * More rework * Removing (suspected unnecessary) formatting * Add more example doc * Added a smoke- / passthrough-test * Applied spotless * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/RequestBuilder.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/RequestBuilder.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/ToolFactory.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/rest/server/McpCdsBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/rest/server/McpCdsBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Formatting * Added some documentation * spotless cares about MD? * Reverting back to default values * minor refinements * Fixed CDS hooks configuration * Fixed some wirings * Readded missing elements * getting closer to get test running again ... * applying review * Readded exclude * Bumped spring-ai deps * added agents file * Updated according to review --------- Co-authored-by: Ádám Z. Kövér <adamzkover@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d29b9f80af
commit
d76662c9e9
38
AGENTS.md
Normal file
38
AGENTS.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Repository Guidelines
|
||||||
|
|
||||||
|
## Project Structure & Module Organization
|
||||||
|
- `src/main/java`: Spring Boot entry point `ca.uhn.fhir.jpa.starter.Application`, resource providers, config.
|
||||||
|
- `src/main/resources`: Application YAML, search parameter bundles, capability statements packaged with the WAR.
|
||||||
|
- `src/main/webapp`: HAPI Testpage overlay shipped for the default UI.
|
||||||
|
- `src/test/java` & `src/test/resources`: JUnit 5 suites (interceptors, MCP, MDM) plus matching fixtures grouped by FHIR version.
|
||||||
|
- `charts/`, `docker-compose.yml`, `configs/`: Deployment templates for Helm, Docker, and Tomcat/server overrides.
|
||||||
|
- `Dockerfile`, `build-docker-image.sh`: Reference container build scripts used by CI/CD.
|
||||||
|
|
||||||
|
## Build, Test, and Development Commands
|
||||||
|
- `mvn clean install`: Compile, run Surefire + Failsafe, and emit `target/ROOT.war`.
|
||||||
|
- `mvn spring-boot:run -Pboot`: Start the server on port 8080 with hot reload-friendly Boot profile.
|
||||||
|
- `mvn clean package spring-boot:repackage -Pboot && java -jar target/ROOT.war`: Build and exercise the bootable WAR.
|
||||||
|
- `docker-compose up -d --build`: Launch JPAServer + PostgreSQL using the local Dockerfile.
|
||||||
|
- `docker run -p 8080:8080 hapiproject/hapi:latest`: Compare against the upstream binary distribution.
|
||||||
|
|
||||||
|
## Coding Style & Naming Conventions
|
||||||
|
- Target Java 17, four-space indents, alphabetized imports, no wildcards.
|
||||||
|
- Keep code under `ca.uhn.fhir.jpa.starter` and mirror packages in tests.
|
||||||
|
- Prefer descriptive class suffixes (`*Provider`, `*Service`, `*Config`) and constructor injection with `final` collaborators.
|
||||||
|
- YAML keys stay kebab-case; JSON fixtures use lower_snake_case filenames.
|
||||||
|
|
||||||
|
## Testing Guidelines
|
||||||
|
- `mvn test`: Runs JUnit Jupiter unit suites such as `CustomBeanTest` and `ParallelUpdatesVersionConflictTest`.
|
||||||
|
- `mvn verify`: Adds integration coverage through Failsafe with the default H2 datasource; if you pivot to PostgreSQL, run `mvn install -DskipTests` until fixtures are updated.
|
||||||
|
- Store integration suites as `*IT.java` so Failsafe detects them and colocate datasets in `src/test/resources`.
|
||||||
|
- Leverage Testcontainers and HAPI FHIR test utilities already declared in `pom.xml`.
|
||||||
|
|
||||||
|
## Commit & Pull Request Guidelines
|
||||||
|
- Follow repository precedent: imperative summary, optional scope (`Feature/mcp`), and linked issue `(#123)` when applicable.
|
||||||
|
- Keep commits narrowly scoped and include config or fixture updates with the code they support.
|
||||||
|
- PRs should describe runtime impact (profiles, ports, env vars), reference issues, and include UI screenshots when behaviour changes.
|
||||||
|
- Run `mvn verify` or the relevant Docker workflow before review; note any skipped checks and how to reproduce the result.
|
||||||
|
|
||||||
|
## Security & Configuration Tips
|
||||||
|
- Do not commit secrets; stash overrides under `configs/` and explain required env vars in the PR.
|
||||||
|
- When enabling external services, update `src/main/resources/application.yaml` plus sample overrides and mention connection expectations for reviewers.
|
||||||
10
pom.xml
10
pom.xml
@@ -391,20 +391,14 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp</artifactId>
|
<artifactId>spring-ai-mcp</artifactId>
|
||||||
<version>1.1.0-M1</version>
|
<version>1.1.0-M2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--implementation("org.springframework.ai:spring-ai-starter-mcp-server-webmvc:1.1.0-M1")-->
|
<!--implementation("org.springframework.ai:spring-ai-starter-mcp-server-webmvc:1.1.0-M1")-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-mcp-server</artifactId>
|
<artifactId>spring-ai-starter-mcp-server</artifactId>
|
||||||
<version>1.1.0-M1</version>
|
<version>1.1.0-M2</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
|
||||||
<artifactId>mcp</artifactId>
|
|
||||||
<version>0.12.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "hapi.fhir.cdshooks")
|
@ConfigurationProperties(prefix = "hapi.fhir.cdshooks")
|
||||||
public class CdsHooksProperties {
|
public class CdsHooksProperties {
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.starter.cdshooks;
|
|||||||
|
|
||||||
import ca.uhn.fhir.jpa.starter.AppProperties;
|
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||||
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
|
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
@@ -43,9 +42,6 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
@Autowired
|
@Autowired
|
||||||
ICdsServiceRegistry cdsServiceRegistry;
|
ICdsServiceRegistry cdsServiceRegistry;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
RestfulServer restfulServer;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
|
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
|
||||||
ObjectMapper objectMapper;
|
ObjectMapper objectMapper;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
import ca.uhn.fhir.jpa.starter.cr.CqlRuntimeProperties;
|
||||||
|
|
||||||
public class ProviderConfiguration {
|
public class ProviderConfiguration {
|
||||||
private final String clientIdHeaderName;
|
private final String clientIdHeaderName;
|
||||||
@@ -11,8 +11,8 @@ public class ProviderConfiguration {
|
|||||||
this.clientIdHeaderName = clientIdHeaderName;
|
this.clientIdHeaderName = clientIdHeaderName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProviderConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
|
public ProviderConfiguration(CdsHooksProperties cdsProperties, CqlRuntimeProperties cqlRuntimeProperties) {
|
||||||
this(crProperties.getCql().getRuntime().isDebugLoggingEnabled(), cdsProperties.getClientIdHeaderName());
|
this(cqlRuntimeProperties.isDebugLoggingEnabled(), cdsProperties.getClientIdHeaderName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClientIdHeaderName() {
|
public String getClientIdHeaderName() {
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.jpa.starter.cr.*;
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrCommonConfig;
|
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrConfigCondition;
|
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsHooksDaoAuthorizationSvc;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsHooksDaoAuthorizationSvc;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.CdsHooksContextBooter;
|
import ca.uhn.hapi.fhir.cdshooks.svc.CdsHooksContextBooter;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrServiceRegistry;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrSettings;
|
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrSettings;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.ICdsCrServiceRegistry;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.CdsCrDiscoveryServiceRegistry;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.ICdsCrDiscoveryServiceRegistry;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.config.test.TestCdsHooksConfig;
|
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -24,30 +17,9 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional({CdsHooksConfigCondition.class, CrConfigCondition.class})
|
@Conditional({CdsHooksConfigCondition.class, CrConfigCondition.class})
|
||||||
@Import({RepositoryConfig.class, TestCdsHooksConfig.class, CrCdsHooksConfig.class, CrCommonConfig.class})
|
@Import({RepositoryConfig.class, CrCdsHooksConfig.class, CrCommonConfig.class, CdsHooksConfig.class})
|
||||||
public class StarterCdsHooksConfig {
|
public class StarterCdsHooksConfig {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ICdsCrDiscoveryServiceRegistry cdsCrDiscoveryServiceRegistry() {
|
|
||||||
CdsCrDiscoveryServiceRegistry registry = new CdsCrDiscoveryServiceRegistry();
|
|
||||||
registry.unregister(FhirVersionEnum.R4);
|
|
||||||
registry.register(FhirVersionEnum.R4, UpdatedCrDiscoveryService.class);
|
|
||||||
return registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ICdsCrServiceRegistry cdsCrServiceRegistry() {
|
|
||||||
CdsCrServiceRegistry registry = new CdsCrServiceRegistry();
|
|
||||||
registry.unregister(FhirVersionEnum.R4);
|
|
||||||
registry.register(FhirVersionEnum.R4, UpdatedCdsCrService.class);
|
|
||||||
return registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public CdsHooksProperties cdsHooksProperties() {
|
|
||||||
return new CdsHooksProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CdsCrSettings cdsCrSettings(CdsHooksProperties cdsHooksProperties) {
|
public CdsCrSettings cdsCrSettings(CdsHooksProperties cdsHooksProperties) {
|
||||||
CdsCrSettings settings = CdsCrSettings.getDefault();
|
CdsCrSettings settings = CdsCrSettings.getDefault();
|
||||||
@@ -67,8 +39,9 @@ public class StarterCdsHooksConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ProviderConfiguration providerConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
|
public ProviderConfiguration providerConfiguration(
|
||||||
return new ProviderConfiguration(cdsProperties, crProperties);
|
CdsHooksProperties cdsProperties, CqlProperties cqlProperties, CqlRuntimeProperties cqlRuntimeProperties) {
|
||||||
|
return new ProviderConfiguration(cdsProperties, cqlRuntimeProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
|
||||||
import ca.uhn.fhir.repository.IRepository;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrService;
|
|
||||||
import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory;
|
|
||||||
|
|
||||||
import static org.opencds.cqf.fhir.utility.Constants.APPLY_PARAMETER_DATA;
|
|
||||||
|
|
||||||
public class UpdatedCdsCrService extends CdsCrService {
|
|
||||||
private final IAdapterFactory adapterFactory;
|
|
||||||
|
|
||||||
public UpdatedCdsCrService(RequestDetails theRequestDetails, IRepository theRepository) {
|
|
||||||
super(theRequestDetails, theRepository);
|
|
||||||
adapterFactory = IAdapterFactory.forFhirContext(theRepository.fhirContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBaseParameters encodeParams(CdsServiceRequestJson theJson) {
|
|
||||||
var parameters = adapterFactory.createParameters(super.encodeParams(theJson));
|
|
||||||
if (parameters.hasParameter(APPLY_PARAMETER_DATA)) {
|
|
||||||
parameters.addParameter(
|
|
||||||
"useServerData",
|
|
||||||
booleanTypeForVersion(parameters.fhirContext().getVersion().getVersion(), false));
|
|
||||||
}
|
|
||||||
return (IBaseParameters) parameters.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IPrimitiveType<Boolean> booleanTypeForVersion(FhirVersionEnum fhirVersion, boolean value) {
|
|
||||||
return switch (fhirVersion) {
|
|
||||||
case DSTU2 -> new org.hl7.fhir.dstu2.model.BooleanType(value);
|
|
||||||
case DSTU3 -> new org.hl7.fhir.dstu3.model.BooleanType(value);
|
|
||||||
case R4 -> new org.hl7.fhir.r4.model.BooleanType(value);
|
|
||||||
case R5 -> new org.hl7.fhir.r5.model.BooleanType(value);
|
|
||||||
default -> throw new IllegalArgumentException("unknown or unsupported FHIR version");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.repository.IRepository;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.CrDiscoveryService;
|
|
||||||
|
|
||||||
public class UpdatedCrDiscoveryService extends CrDiscoveryService {
|
|
||||||
public UpdatedCrDiscoveryService(IIdType thePlanDefinitionId, IRepository theRepository) {
|
|
||||||
super(thePlanDefinitionId, theRepository);
|
|
||||||
maxUriLength = 6000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cr;
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.caregaps")
|
||||||
public class CareGapsProperties {
|
public class CareGapsProperties {
|
||||||
private String reporter = "default";
|
private String reporter = "default";
|
||||||
private String section_author = "default";
|
private String section_author = "default";
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ package ca.uhn.fhir.jpa.starter.cr;
|
|||||||
import org.cqframework.cql.cql2elm.CqlCompilerException;
|
import org.cqframework.cql.cql2elm.CqlCompilerException;
|
||||||
import org.cqframework.cql.cql2elm.CqlTranslator;
|
import org.cqframework.cql.cql2elm.CqlTranslator;
|
||||||
import org.cqframework.cql.cql2elm.LibraryBuilder;
|
import org.cqframework.cql.cql2elm.LibraryBuilder;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.compiler")
|
||||||
public class CqlCompilerProperties {
|
public class CqlCompilerProperties {
|
||||||
private Boolean validate_units = true;
|
private Boolean validate_units = true;
|
||||||
private Boolean verify_only = false;
|
private Boolean verify_only = false;
|
||||||
|
|||||||
46
src/main/java/ca/uhn/fhir/jpa/starter/cr/CqlData.java
Normal file
46
src/main/java/ca/uhn/fhir/jpa/starter/cr/CqlData.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
|
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.data")
|
||||||
|
public class CqlData {
|
||||||
|
private RetrieveSettings.SEARCH_FILTER_MODE searchParameterMode = RetrieveSettings.SEARCH_FILTER_MODE.AUTO;
|
||||||
|
private RetrieveSettings.PROFILE_MODE profileMode = RetrieveSettings.PROFILE_MODE.OFF;
|
||||||
|
private RetrieveSettings.TERMINOLOGY_FILTER_MODE terminologyParameterMode =
|
||||||
|
RetrieveSettings.TERMINOLOGY_FILTER_MODE.AUTO;
|
||||||
|
|
||||||
|
public RetrieveSettings.SEARCH_FILTER_MODE getSearchParameterMode() {
|
||||||
|
return searchParameterMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchParameterMode(RetrieveSettings.SEARCH_FILTER_MODE searchParameterMode) {
|
||||||
|
this.searchParameterMode = searchParameterMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveSettings.PROFILE_MODE getProfileMode() {
|
||||||
|
return profileMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProfileMode(RetrieveSettings.PROFILE_MODE profileMode) {
|
||||||
|
this.profileMode = profileMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveSettings.TERMINOLOGY_FILTER_MODE getTerminologyParameterMode() {
|
||||||
|
return terminologyParameterMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTerminologyParameterMode(RetrieveSettings.TERMINOLOGY_FILTER_MODE terminologyParameterMode) {
|
||||||
|
this.terminologyParameterMode = terminologyParameterMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetrieveSettings getRetrieveSettings() {
|
||||||
|
var retrieveSettings = new RetrieveSettings();
|
||||||
|
retrieveSettings.setSearchParameterMode(searchParameterMode);
|
||||||
|
retrieveSettings.setProfileMode(profileMode);
|
||||||
|
retrieveSettings.setTerminologyParameterMode(terminologyParameterMode);
|
||||||
|
return retrieveSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,14 +2,18 @@ package ca.uhn.fhir.jpa.starter.cr;
|
|||||||
|
|
||||||
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
|
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
|
||||||
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
|
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql")
|
||||||
public class CqlProperties {
|
public class CqlProperties {
|
||||||
|
|
||||||
private Boolean use_embedded_libraries = true;
|
private Boolean use_embedded_libraries = true;
|
||||||
private CqlCompilerProperties compiler = new CqlCompilerProperties();
|
private CqlCompilerProperties compiler = new CqlCompilerProperties();
|
||||||
private CqlRuntimeProperties runtime = new CqlRuntimeProperties();
|
private CqlRuntimeProperties runtime = new CqlRuntimeProperties();
|
||||||
private TerminologySettings terminology = new TerminologySettings();
|
private TerminologySettings terminology = new TerminologySettings();
|
||||||
private RetrieveSettings data = new RetrieveSettings();
|
private CqlData data = new CqlData();
|
||||||
|
|
||||||
public Boolean getUse_embedded_libraries() {
|
public Boolean getUse_embedded_libraries() {
|
||||||
return use_embedded_libraries;
|
return use_embedded_libraries;
|
||||||
@@ -43,11 +47,15 @@ public class CqlProperties {
|
|||||||
this.terminology = terminology;
|
this.terminology = terminology;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RetrieveSettings getData() {
|
public CqlData getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(RetrieveSettings data) {
|
public void setData(CqlData data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RetrieveSettings getRetrieveSettings() {
|
||||||
|
return data.getRetrieveSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cr;
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.runtime")
|
||||||
public class CqlRuntimeProperties {
|
public class CqlRuntimeProperties {
|
||||||
|
|
||||||
private Boolean debug_logging_enabled = false;
|
private Boolean debug_logging_enabled = false;
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
|
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.terminology")
|
||||||
|
@Configuration
|
||||||
|
public class CqlTerminologyProperties {
|
||||||
|
|
||||||
|
private TerminologySettings.VALUESET_EXPANSION_MODE valuesetExpansionMode =
|
||||||
|
TerminologySettings.VALUESET_EXPANSION_MODE.AUTO;
|
||||||
|
private TerminologySettings.VALUESET_MEMBERSHIP_MODE valuesetMembershipMode =
|
||||||
|
TerminologySettings.VALUESET_MEMBERSHIP_MODE.AUTO;
|
||||||
|
private TerminologySettings.CODE_LOOKUP_MODE codeLookupMode = TerminologySettings.CODE_LOOKUP_MODE.AUTO;
|
||||||
|
private TerminologySettings.VALUESET_PRE_EXPANSION_MODE valueSetPreExpansionMode =
|
||||||
|
TerminologySettings.VALUESET_PRE_EXPANSION_MODE.USE_IF_PRESENT;
|
||||||
|
|
||||||
|
public void setValuesetExpansionMode(TerminologySettings.VALUESET_EXPANSION_MODE valuesetExpansionMode) {
|
||||||
|
this.valuesetExpansionMode = valuesetExpansionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValuesetMembershipMode(TerminologySettings.VALUESET_MEMBERSHIP_MODE valuesetMembershipMode) {
|
||||||
|
this.valuesetMembershipMode = valuesetMembershipMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCodeLookupMode(TerminologySettings.CODE_LOOKUP_MODE codeLookupMode) {
|
||||||
|
this.codeLookupMode = codeLookupMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueSetPreExpansionMode(TerminologySettings.VALUESET_PRE_EXPANSION_MODE valueSetPreExpansionMode) {
|
||||||
|
this.valueSetPreExpansionMode = valueSetPreExpansionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminologySettings getTerminologySettings() {
|
||||||
|
TerminologySettings settings = new TerminologySettings();
|
||||||
|
settings.setValuesetExpansionMode(valuesetExpansionMode);
|
||||||
|
settings.setValuesetMembershipMode(valuesetMembershipMode);
|
||||||
|
settings.setCodeLookupMode(codeLookupMode);
|
||||||
|
settings.setValuesetPreExpansionMode(valueSetPreExpansionMode);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,6 @@ import org.opencds.cqf.fhir.cr.measure.CareGapsProperties;
|
|||||||
import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions;
|
import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions;
|
||||||
import org.opencds.cqf.fhir.utility.ValidationProfile;
|
import org.opencds.cqf.fhir.utility.ValidationProfile;
|
||||||
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -43,19 +42,13 @@ import java.util.concurrent.Executors;
|
|||||||
public class CrCommonConfig {
|
public class CrCommonConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
RetrieveSettings retrieveSettings(CqlData cqlData) {
|
||||||
CrProperties crProperties() {
|
return cqlData.getRetrieveSettings();
|
||||||
return new CrProperties();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
RetrieveSettings retrieveSettings(CrProperties theCrProperties) {
|
TerminologySettings terminologySettings(CqlTerminologyProperties theCqlTerminologyProperties) {
|
||||||
return theCrProperties.getCql().getData();
|
return theCqlTerminologyProperties.getTerminologySettings();
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
TerminologySettings terminologySettings(CrProperties theCrProperties) {
|
|
||||||
return theCrProperties.getCql().getTerminology();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -65,7 +58,8 @@ public class CrCommonConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public EvaluationSettings evaluationSettings(
|
public EvaluationSettings evaluationSettings(
|
||||||
CrProperties theCrProperties,
|
CqlRuntimeProperties cqlRuntimeProperties,
|
||||||
|
CqlCompilerProperties cqlCompilerProperties,
|
||||||
RetrieveSettings theRetrieveSettings,
|
RetrieveSettings theRetrieveSettings,
|
||||||
TerminologySettings theTerminologySettings,
|
TerminologySettings theTerminologySettings,
|
||||||
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
||||||
@@ -76,7 +70,7 @@ public class CrCommonConfig {
|
|||||||
|
|
||||||
var cqlEngineOptions = cqlOptions.getCqlEngineOptions();
|
var cqlEngineOptions = cqlOptions.getCqlEngineOptions();
|
||||||
Set<CqlEngine.Options> options = EnumSet.noneOf(CqlEngine.Options.class);
|
Set<CqlEngine.Options> options = EnumSet.noneOf(CqlEngine.Options.class);
|
||||||
var cqlRuntimeProperties = theCrProperties.getCql().getRuntime();
|
|
||||||
if (cqlRuntimeProperties.isEnableExpressionCaching()) {
|
if (cqlRuntimeProperties.isEnableExpressionCaching()) {
|
||||||
options.add(CqlEngine.Options.EnableExpressionCaching);
|
options.add(CqlEngine.Options.EnableExpressionCaching);
|
||||||
}
|
}
|
||||||
@@ -91,8 +85,6 @@ public class CrCommonConfig {
|
|||||||
|
|
||||||
var cqlCompilerOptions = new CqlCompilerOptions();
|
var cqlCompilerOptions = new CqlCompilerOptions();
|
||||||
|
|
||||||
var cqlCompilerProperties = theCrProperties.getCql().getCompiler();
|
|
||||||
|
|
||||||
if (cqlCompilerProperties.isEnableDateRangeOptimization()) {
|
if (cqlCompilerProperties.isEnableDateRangeOptimization()) {
|
||||||
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableDateRangeOptimization);
|
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableDateRangeOptimization);
|
||||||
}
|
}
|
||||||
@@ -159,8 +151,8 @@ public class CrCommonConfig {
|
|||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean(name = "measure.CareGapsProperties")
|
||||||
CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
org.opencds.cqf.fhir.cr.measure.CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
||||||
var careGapsProperties = new CareGapsProperties();
|
var careGapsProperties = new CareGapsProperties();
|
||||||
// This check for the resource type really should be happening down in CR where the setting is actually used but
|
// This check for the resource type really should be happening down in CR where the setting is actually used but
|
||||||
// that will have to wait for a future CR release
|
// that will have to wait for a future CR release
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cr;
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
||||||
public class CrProperties {
|
public class CrProperties {
|
||||||
private Boolean enabled;
|
private Boolean enabled;
|
||||||
|
|
||||||
private CareGapsProperties careGaps = new CareGapsProperties();
|
private CareGapsProperties careGaps = new CareGapsProperties();
|
||||||
private CqlProperties cql = new CqlProperties();
|
private CqlProperties cql = new CqlProperties();
|
||||||
|
|
||||||
private TerminologyServerClientSettings terminologyServerClientSettings = new TerminologyServerClientSettings();
|
private TerminologyServerClientSettings terminologyServerClientSettings = new TerminologyServerClientSettings();
|
||||||
|
|
||||||
public Boolean getEnabled() {
|
public Boolean getEnabled() {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.module.CdsHooksObjectMapperFactory;
|
import ca.uhn.hapi.fhir.cdshooks.module.CdsHooksObjectMapperFactory;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
|
||||||
import io.modelcontextprotocol.server.McpServerFeatures;
|
import io.modelcontextprotocol.server.McpServerFeatures;
|
||||||
import io.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider;
|
import io.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider;
|
||||||
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerStreamableHttpProperties;
|
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerStreamableHttpProperties;
|
||||||
@@ -66,7 +67,7 @@ public class McpServerConfig {
|
|||||||
return HttpServletStreamableServerTransportProvider.builder()
|
return HttpServletStreamableServerTransportProvider.builder()
|
||||||
.disallowDelete(false)
|
.disallowDelete(false)
|
||||||
.mcpEndpoint(properties.getMcpEndpoint())
|
.mcpEndpoint(properties.getMcpEndpoint())
|
||||||
.objectMapper(new ObjectMapper())
|
.jsonMapper(new JacksonMcpJsonMapper(new ObjectMapper()))
|
||||||
// .contextExtractor((serverRequest, context) -> context)
|
// .contextExtractor((serverRequest, context) -> context)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
#Uncomment the "servlet" and "context-path" lines below to make the fhir endpoint available at /example/path/fhir instead of the default value of /fhir
|
# -------------------------------------------------------------------------------------
|
||||||
|
# Server & Spring Boot
|
||||||
|
# -------------------------------------------------------------------------------------
|
||||||
server:
|
server:
|
||||||
|
# Uncomment to serve FHIR under a non-default context path (e.g., /example/path/fhir)
|
||||||
# servlet:
|
# servlet:
|
||||||
# context-path: /example/path
|
# context-path: /example/path
|
||||||
port: 8080
|
port: 8080
|
||||||
tomcat:
|
tomcat:
|
||||||
# allow | as a separator in the URL
|
# allow | as a separator in URLs
|
||||||
relaxed-query-chars: "|"
|
relaxed-query-chars: "|"
|
||||||
#Adds the option to go to e.g. http://localhost:8080/actuator/health for seeing the running configuration
|
|
||||||
#see https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints
|
|
||||||
management:
|
management:
|
||||||
health:
|
# Actuator endpoints: only /actuator/health exposed by default
|
||||||
elasticsearch:
|
|
||||||
enabled: false
|
|
||||||
#The following configuration will enable the actuator endpoints at /actuator/health, /actuator/info, /actuator/prometheus, /actuator/metrics. For security purposes, only /actuator/health is enabled by default.
|
|
||||||
endpoints:
|
endpoints:
|
||||||
enabled-by-default: false
|
enabled-by-default: false
|
||||||
web:
|
web:
|
||||||
exposure:
|
exposure:
|
||||||
# expose only health (default) — change to [health,info,prometheus,metrics] if you want them reachable
|
include: "health" # or "info,health,prometheus,metrics" or "*" for all
|
||||||
include: health
|
|
||||||
endpoint:
|
endpoint:
|
||||||
info:
|
info:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -30,25 +28,27 @@ management:
|
|||||||
enabled: true
|
enabled: true
|
||||||
group:
|
group:
|
||||||
liveness:
|
liveness:
|
||||||
include:
|
include: [ "livenessState", "readinessState" ]
|
||||||
- livenessState
|
|
||||||
- readinessState
|
|
||||||
prometheus:
|
prometheus:
|
||||||
enabled: true
|
enabled: true
|
||||||
prometheus:
|
prometheus:
|
||||||
metrics:
|
metrics:
|
||||||
export:
|
export:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# A. Spring AI — Model Context Protocol (MCP)
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
ai:
|
ai:
|
||||||
# Run e.g. `npx @modelcontextprotocol/inspector` and connect to http://localhost:8080/mcp/message using Streamable HTTP
|
# Run e.g. `npx @modelcontextprotocol/inspector` and connect to http://localhost:8080/mcp/messages using Streamable HTTP
|
||||||
|
|
||||||
# Add the following to the MCP server settings file in e.g. cursor or claude (Desktop applications) for local debugging:
|
# Add the following to the MCP server settings file in e.g. cursor or claude (Desktop applications) for local debugging:
|
||||||
# cursor:
|
# cursor:
|
||||||
# {
|
# {
|
||||||
# "mcpServers": {
|
# "mcpServers": {
|
||||||
# "hapi": {
|
# "hapi": {
|
||||||
# "url": "http://localhost:8080/mcp/message"
|
# "url": "http://localhost:8080/mcp/messages"
|
||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
@@ -59,7 +59,7 @@ spring:
|
|||||||
# "command": "npx",
|
# "command": "npx",
|
||||||
# "args": [
|
# "args": [
|
||||||
# "mcp-remote@latest",
|
# "mcp-remote@latest",
|
||||||
# "http://localhost:8080/mcp/message"
|
# "http://localhost:8080/mcp/messages"
|
||||||
# ]
|
# ]
|
||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
@@ -75,48 +75,43 @@ spring:
|
|||||||
mcp-endpoint: /mcp/messages
|
mcp-endpoint: /mcp/messages
|
||||||
|
|
||||||
|
|
||||||
#schema:
|
# -------------------------------------------------------------------------------
|
||||||
# fhir-enabled: true
|
# B. Core Spring
|
||||||
# fhir:
|
# -------------------------------------------------------------------------------
|
||||||
# base-url: http://localhost:8080/fhir
|
main:
|
||||||
|
allow-bean-definition-overriding: false
|
||||||
#query:
|
allow-circular-references: true
|
||||||
# prompt:
|
|
||||||
# template: |
|
|
||||||
# You are a FHIR assistant. Translate the following question into a valid FHIR RESTful API query:
|
|
||||||
# "{{query}}"
|
|
||||||
# Use the provided FHIR schema:
|
|
||||||
# {{schema}}
|
|
||||||
#base-url: /api/v1
|
|
||||||
|
|
||||||
|
|
||||||
autoconfigure:
|
autoconfigure:
|
||||||
# This exclude is only needed for setups not using Elasticsearch where the elasticsearch sniff is not needed.
|
# This exclude is only needed for setups not using Elasticsearch where the elasticsearch sniff is not needed.
|
||||||
exclude: org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
|
exclude: org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
|
||||||
main:
|
|
||||||
allow-bean-definition-overriding: false
|
|
||||||
allow-circular-references: true
|
|
||||||
flyway:
|
flyway:
|
||||||
enabled: false
|
enabled: false
|
||||||
baseline-on-migrate: true
|
baseline-on-migrate: true
|
||||||
fail-on-missing-locations: false
|
fail-on-missing-locations: false
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
#url: 'jdbc:h2:file:./target/database/h2'
|
# url: "jdbc:h2:file:./target/database/h2"
|
||||||
url: jdbc:h2:mem:test_mem
|
url: jdbc:h2:mem:test_mem
|
||||||
username: sa
|
username: sa
|
||||||
password: null
|
password: null
|
||||||
driver-class-name: org.h2.Driver
|
driver-class-name: org.h2.Driver
|
||||||
|
# max-active: 15 # (ignored with HikariCP; use hikari.maximum-pool-size)
|
||||||
# database connection pool size
|
|
||||||
hikari:
|
hikari:
|
||||||
maximum-pool-size: 10
|
maximum-pool-size: 10
|
||||||
# elasticsearch:
|
|
||||||
# uris: http://localhost:9200
|
|
||||||
# username: elastic
|
|
||||||
# password: changeme
|
|
||||||
jpa:
|
jpa:
|
||||||
properties:
|
properties:
|
||||||
hibernate:
|
hibernate:
|
||||||
|
format_sql: false
|
||||||
|
show_sql: false
|
||||||
|
# Hibernate dialect is auto-detected except for H2/Postgres.
|
||||||
|
# If using H2: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||||
|
# If using Postgres: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||||
|
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||||
|
|
||||||
|
# --- Optional Hibernate DDL & tuning (commented out from source) ---
|
||||||
hbm2ddl:
|
hbm2ddl:
|
||||||
auto: update
|
auto: update
|
||||||
jdbc:
|
jdbc:
|
||||||
@@ -126,43 +121,73 @@ spring:
|
|||||||
use_second_level_cache: false
|
use_second_level_cache: false
|
||||||
use_structured_entries: false
|
use_structured_entries: false
|
||||||
use_minimal_puts: false
|
use_minimal_puts: false
|
||||||
format_sql: false
|
|
||||||
show_sql: false
|
|
||||||
#If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
|
||||||
#If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
|
||||||
#dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
|
||||||
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
|
||||||
search:
|
|
||||||
enabled: true
|
|
||||||
schema_management:
|
|
||||||
strategy: create
|
|
||||||
### lucene parameters
|
|
||||||
backend:
|
|
||||||
type: lucene
|
|
||||||
directory:
|
|
||||||
type: local-filesystem
|
|
||||||
root: target/lucenefiles
|
|
||||||
analysis:
|
|
||||||
configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
|
||||||
|
|
||||||
### elastic parameters ===> see also elasticsearch section below <===
|
# --- Hibernate Search (Lucene/Elasticsearch) ---
|
||||||
|
search:
|
||||||
|
enabled: false
|
||||||
|
# Lucene backend (default example)
|
||||||
|
# backend:
|
||||||
|
# type: lucene
|
||||||
|
# analysis:
|
||||||
|
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||||
|
# directory:
|
||||||
|
# type: local-filesystem
|
||||||
|
# root: target/lucenefiles
|
||||||
|
# lucene_version: lucene_current
|
||||||
|
# Elasticsearch backend (alternative) — see also hapi.fhir.elasticsearch section in docs
|
||||||
# backend:
|
# backend:
|
||||||
# type: elasticsearch
|
# type: elasticsearch
|
||||||
# discovery: true
|
|
||||||
# analysis:
|
# analysis:
|
||||||
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
||||||
# hosts: localhost:9200
|
|
||||||
# protocol: http
|
|
||||||
# username: elastic
|
|
||||||
# password: changeme
|
|
||||||
# refresh_after_write: true
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------------
|
||||||
|
# HAPI FHIR — grouped by domain
|
||||||
|
# -------------------------------------------------------------------------------------
|
||||||
hapi:
|
hapi:
|
||||||
fhir:
|
fhir:
|
||||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
|
||||||
### Flag is false by default, can be passed as command line argument to override.
|
# -------------------------------------------------------------------------------
|
||||||
|
# A. Core Server & API
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
openapi_enabled: true # Swagger UI at /fhir/swagger-ui/index.html; API docs at /fhir/api-docs
|
||||||
|
fhir_version: R4 # DSTU2 | DSTU3 | R4 | R5
|
||||||
|
# use_apache_address_strategy: false
|
||||||
|
# use_apache_address_strategy_https: false
|
||||||
|
# custom_content_path: ./custom # folder name must be 'custom'
|
||||||
|
# app_content_path: ./configs/app # served under /web/app
|
||||||
|
# server_address: http://hapi.fhir.org/baseR4
|
||||||
|
# defer_indexing_for_codesystems_of_size: 101
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# B. Implementation Guides (IG) & Package Install
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
ig_runtime_upload_enabled: false
|
||||||
|
# validate_resource_status_for_package_upload: false # default true
|
||||||
|
# install_transitive_ig_dependencies: true
|
||||||
|
# implementationguides:
|
||||||
|
# swiss:
|
||||||
|
# name: swiss.mednet.fhir
|
||||||
|
# version: 0.8.0
|
||||||
|
# reloadExisting: false
|
||||||
|
# installMode: STORE_AND_INSTALL
|
||||||
|
# ips_1_0_0:
|
||||||
|
# packageUrl: https://costateixeira.github.io/smart-ips-pilgrimage-fulltest/package.tgz
|
||||||
|
# name: smart.who.int.ips-pilgrimage-test
|
||||||
|
# version: 0.1.0
|
||||||
|
# installMode: STORE_AND_INSTALL
|
||||||
|
# additionalResourceFolders:
|
||||||
|
# - example
|
||||||
|
# - example2
|
||||||
|
# supported_resource_types:
|
||||||
|
# - Patient
|
||||||
|
# - Observation
|
||||||
|
# allowed_bundle_types: COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# C. Clinical Reasoning / CQL / Care Gaps / CDS Hooks
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
cr:
|
cr:
|
||||||
enabled: false
|
enabled: false # exposes Clinical Reasoning operation endpoints
|
||||||
caregaps:
|
caregaps:
|
||||||
reporter: "default"
|
reporter: "default"
|
||||||
section_author: "default"
|
section_author: "default"
|
||||||
@@ -174,8 +199,7 @@ hapi:
|
|||||||
cql:
|
cql:
|
||||||
use_embedded_libraries: true
|
use_embedded_libraries: true
|
||||||
compiler:
|
compiler:
|
||||||
### These are low-level compiler options.
|
# low-level compiler options (typically not needed)
|
||||||
### They are not typically needed by most users.
|
|
||||||
# validate_units: true
|
# validate_units: true
|
||||||
# verify_only: false
|
# verify_only: false
|
||||||
# compatibility_level: "1.5"
|
# compatibility_level: "1.5"
|
||||||
@@ -201,68 +225,42 @@ hapi:
|
|||||||
# enable_validation: false
|
# enable_validation: false
|
||||||
# enable_expression_caching: true
|
# enable_expression_caching: true
|
||||||
terminology:
|
terminology:
|
||||||
valueset_preexpansion_mode: REQUIRE # USE_IF_PRESENT, REQUIRE, IGNORE
|
valueset_preexpansion_mode: REQUIRE # USE_IF_PRESENT | REQUIRE | IGNORE
|
||||||
valueset_expansion_mode: PERFORM_NAIVE_EXPANSION # AUTO, USE_EXPANSION_OPERATION, PERFORM_NAIVE_EXPANSION
|
valueset_expansion_mode: PERFORM_NAIVE_EXPANSION # AUTO | USE_EXPANSION_OPERATION | PERFORM_NAIVE_EXPANSION
|
||||||
valueset_membership_mode: USE_EXPANSION # AUTO, USE_VALIDATE_CODE_OPERATION, USE_EXPANSION
|
valueset_membership_mode: USE_EXPANSION # AUTO | USE_VALIDATE_CODE_OPERATION | USE_EXPANSION
|
||||||
code_lookup_mode: USE_VALIDATE_CODE_OPERATION # AUTO, USE_VALIDATE_CODE_OPERATION, USE_CODESYSTEM_URL
|
code_lookup_mode: USE_VALIDATE_CODE_OPERATION # AUTO | USE_VALIDATE_CODE_OPERATION | USE_CODESYSTEM_URL
|
||||||
data:
|
data:
|
||||||
search_parameter_mode: USE_SEARCH_PARAMETERS # AUTO, USE_SEARCH_PARAMETERS, FILTER_IN_MEMORY
|
search_parameter_mode: USE_SEARCH_PARAMETERS # AUTO | USE_SEARCH_PARAMETERS | FILTER_IN_MEMORY
|
||||||
terminology_parameter_mode: FILTER_IN_MEMORY # AUTO, USE_VALUE_SET_URL, USE_INLINE_CODES, FILTER_IN_MEMORY
|
terminology_parameter_mode: FILTER_IN_MEMORY # AUTO | USE_VALUE_SET_URL | USE_INLINE_CODES | FILTER_IN_MEMORY
|
||||||
profile_mode: DECLARED # ENFORCED, DECLARED, OPTIONAL, TRUST, OFF
|
profile_mode: DECLARED # ENFORCED | DECLARED | OPTIONAL | TRUST | OFF
|
||||||
|
|
||||||
cdshooks:
|
cdshooks:
|
||||||
enabled: false
|
enabled: false
|
||||||
clientIdHeaderName: client_id
|
clientIdHeaderName: client_id
|
||||||
|
|
||||||
### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html)
|
# -------------------------------------------------------------------------------
|
||||||
openapi_enabled: true
|
# D. Search & Indexing
|
||||||
### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5
|
# -------------------------------------------------------------------------------
|
||||||
fhir_version: R4
|
# NOTE: Extended Lucene/Elasticsearch indexing is experimental.
|
||||||
### Flag is false by default. This flag enables runtime installation of IG's.
|
# See https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html
|
||||||
ig_runtime_upload_enabled: false
|
advanced_lucene_indexing: false
|
||||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
search_index_full_text_enabled: false
|
||||||
|
# language_search_parameter_enabled: true
|
||||||
|
# upliftedRefchains_enabled: true
|
||||||
|
# index_storage_optimized: false
|
||||||
|
# enable_index_missing_fields: false
|
||||||
|
# enable_index_of_type: true
|
||||||
|
# enable_index_contained_resource: false
|
||||||
|
# store_resource_in_lucene_index_enabled: true
|
||||||
|
|
||||||
### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers
|
# -------------------------------------------------------------------------------
|
||||||
### to determine the FHIR server address
|
# E. Bulk Operations
|
||||||
# use_apache_address_strategy: false
|
# -------------------------------------------------------------------------------
|
||||||
### forces the use of the https:// protocol for the returned server address.
|
bulk_export_enabled: false
|
||||||
### alternatively, it may be set using the X-Forwarded-Proto header.
|
bulk_import_enabled: false
|
||||||
# use_apache_address_strategy_https: false
|
|
||||||
### enables the server to overwrite defaults on HTML, css, etc. under the url pattern of eg. /content/custom **
|
# -------------------------------------------------------------------------------
|
||||||
### Folder with custom content MUST be named custom. If omitted then default content applies
|
# F. Write / Delete / Integrity
|
||||||
#custom_content_path: ./custom
|
# -------------------------------------------------------------------------------
|
||||||
### enables the server host custom content. If e.g. the value ./configs/app is supplied then the content
|
|
||||||
### will be served under /web/app
|
|
||||||
#app_content_path: ./configs/app
|
|
||||||
### enable to set the Server URL
|
|
||||||
# server_address: http://hapi.fhir.org/baseR4
|
|
||||||
# defer_indexing_for_codesystems_of_size: 101
|
|
||||||
### Flag is true by default. This flag filters resources during package installation, allowing only those resources with a valid status (e.g. active) to be installed.
|
|
||||||
# validate_resource_status_for_package_upload: false
|
|
||||||
# install_transitive_ig_dependencies: true
|
|
||||||
#implementationguides:
|
|
||||||
### example from registry (packages.fhir.org)
|
|
||||||
# swiss:
|
|
||||||
# name: swiss.mednet.fhir
|
|
||||||
# version: 0.8.0
|
|
||||||
# reloadExisting: false
|
|
||||||
# installMode: STORE_AND_INSTALL
|
|
||||||
# example not from registry
|
|
||||||
# ips_1_0_0:
|
|
||||||
# packageUrl: https://costateixeira.github.io/smart-ips-pilgrimage-fulltest/package.tgz
|
|
||||||
# name: smart.who.int.ips-pilgrimage-test
|
|
||||||
# version: 0.1.0
|
|
||||||
# installMode: STORE_AND_INSTALL
|
|
||||||
# additionalResourceFolders:
|
|
||||||
# - example
|
|
||||||
# - example2
|
|
||||||
# supported_resource_types:
|
|
||||||
# - Patient
|
|
||||||
# - Observation
|
|
||||||
##################################################
|
|
||||||
# Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE)
|
|
||||||
##################################################
|
|
||||||
# allowed_bundle_types: COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET
|
|
||||||
# allow_cascading_deletes: true
|
# allow_cascading_deletes: true
|
||||||
# allow_contains_searches: true
|
# allow_contains_searches: true
|
||||||
# allow_external_references: true
|
# allow_external_references: true
|
||||||
@@ -270,54 +268,40 @@ hapi:
|
|||||||
# allow_override_default_search_params: true
|
# allow_override_default_search_params: true
|
||||||
# auto_create_placeholder_reference_targets: false
|
# auto_create_placeholder_reference_targets: false
|
||||||
# mass_ingestion_mode_enabled: false
|
# mass_ingestion_mode_enabled: false
|
||||||
### tells the server to automatically append the current version of the target resource to references at these paths
|
|
||||||
# auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject
|
# auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject
|
||||||
# ips_enabled: false
|
# client_id_strategy: ALPHANUMERIC
|
||||||
# default_encoding: JSON
|
# server_id_strategy: SEQUENTIAL_NUMERIC
|
||||||
# default_pretty_print: true
|
|
||||||
# default_page_size: 20
|
|
||||||
# delete_enabled: true
|
|
||||||
# delete_expunge_enabled: true
|
|
||||||
# match_url_cache_enabled: false
|
|
||||||
# enable_repository_validating_interceptor: true
|
|
||||||
### Reduce the size used by search indexes by not tagging every row with the resource type and parameter name (this setting makes manual inspection of the database more difficult, but does not impact HAPI FHIR functionality in any way)
|
|
||||||
# index_storage_optimized: false
|
|
||||||
# enable_index_missing_fields: false
|
|
||||||
# enable_index_of_type: true
|
|
||||||
# enable_index_contained_resource: false
|
|
||||||
# upliftedRefchains_enabled: true
|
|
||||||
# resource_dbhistory_enabled: false
|
|
||||||
### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!!
|
|
||||||
### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html
|
|
||||||
advanced_lucene_indexing: false
|
|
||||||
search_index_full_text_enabled: false
|
|
||||||
bulk_export_enabled: false
|
|
||||||
bulk_import_enabled: false
|
|
||||||
# language_search_parameter_enabled: true
|
|
||||||
# enforce_referential_integrity_on_delete: false
|
|
||||||
# This is an experimental feature, and does not fully support _total and other FHIR features.
|
|
||||||
# enforce_referential_integrity_on_delete: false
|
# enforce_referential_integrity_on_delete: false
|
||||||
# enforce_referential_integrity_on_write: false
|
# enforce_referential_integrity_on_write: false
|
||||||
# etag_support_enabled: true
|
# etag_support_enabled: true
|
||||||
# expunge_enabled: true
|
# expunge_enabled: true
|
||||||
# client_id_strategy: ALPHANUMERIC
|
|
||||||
# server_id_strategy: SEQUENTIAL_NUMERIC
|
|
||||||
# fhirpath_interceptor_enabled: false
|
# fhirpath_interceptor_enabled: false
|
||||||
# filter_search_enabled: true
|
# filter_search_enabled: true
|
||||||
# graphql_enabled: true
|
# graphql_enabled: true
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# G. Narrative & Validation
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
narrative_enabled: false
|
narrative_enabled: false
|
||||||
|
# validation:
|
||||||
|
# requests_enabled: true
|
||||||
|
# responses_enabled: true
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# H. MDM (Master Data Management)
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
mdm_enabled: false
|
mdm_enabled: false
|
||||||
mdm_rules_json_location: "mdm-rules.json"
|
mdm_rules_json_location: "mdm-rules.json"
|
||||||
## see: https://hapifhir.io/hapi-fhir/docs/interceptors/built_in_server_interceptors.html#jpa-server-retry-on-version-conflicts
|
|
||||||
# userRequestRetryVersionConflictsInterceptorEnabled: false
|
# userRequestRetryVersionConflictsInterceptorEnabled: false
|
||||||
# local_base_urls:
|
|
||||||
# - https://hapi.fhir.org/baseR4
|
# -------------------------------------------------------------------------------
|
||||||
|
# I. Terminology / ValueSet Expansion
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# pre_expand_value_sets: true
|
# pre_expand_value_sets: true
|
||||||
# enable_task_pre_expand_value_sets: true
|
# enable_task_pre_expand_value_sets: true
|
||||||
# pre_expand_value_sets_default_count: 1000
|
# pre_expand_value_sets_default_count: 1000
|
||||||
# pre_expand_value_sets_max_count: 1000
|
# pre_expand_value_sets_max_count: 1000
|
||||||
# maximum_expansion_size: 1000
|
# maximum_expansion_size: 1000
|
||||||
|
|
||||||
logical_urls:
|
logical_urls:
|
||||||
- http://terminology.hl7.org/*
|
- http://terminology.hl7.org/*
|
||||||
- https://terminology.hl7.org/*
|
- https://terminology.hl7.org/*
|
||||||
@@ -328,38 +312,32 @@ hapi:
|
|||||||
- http://loinc.org/*
|
- http://loinc.org/*
|
||||||
- https://loinc.org/*
|
- https://loinc.org/*
|
||||||
|
|
||||||
### Uncomment the following section, and any sub-properties you need in order to enable
|
# -------------------------------------------------------------------------------
|
||||||
### partitioning support on this server.
|
# J. Partitioning & Multitenancy
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# partitioning:
|
# partitioning:
|
||||||
# allow_references_across_partitions: false
|
# allow_references_across_partitions: false
|
||||||
# partitioning_include_in_search_hashes: false
|
# partitioning_include_in_search_hashes: false
|
||||||
# default_partition_id: 0
|
# default_partition_id: 0
|
||||||
### Enable the following setting to enable Database Partitioning Mode
|
|
||||||
### See: https://hapifhir.io/hapi-fhir/docs/server_jpa_partitioning/db_partition_mode.html
|
|
||||||
# database_partition_mode_enabled: true
|
# database_partition_mode_enabled: true
|
||||||
### Partition Style: Partitioning requires a partition interceptor which helps the server
|
|
||||||
### select which partition(s) should be accessed for a given request. You can supply your
|
|
||||||
### own interceptor (see https://hapifhir.io/hapi-fhir/docs/server_jpa_partitioning/partitioning.html#partition-interceptors )
|
|
||||||
### but the following setting can also be used to use a built-in form.
|
|
||||||
### Patient ID Partitioning Mode uses the patient/subject ID to determine the partition
|
|
||||||
# patient_id_partitioning_mode: true
|
# patient_id_partitioning_mode: true
|
||||||
### Request tenant mode can be used for a multi-tenancy setup where the request path is
|
|
||||||
### expected to have an additional path element, e.g. GET http://example.com/fhir/TENANT-ID/Patient/A
|
|
||||||
# request_tenant_partitioning_mode: false
|
# request_tenant_partitioning_mode: false
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# K. CORS
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
cors:
|
cors:
|
||||||
allow_Credentials: true
|
allow_Credentials: true
|
||||||
# These are allowed_origin patterns, see: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/cors/CorsConfiguration.html#setAllowedOriginPatterns-java.util.List-
|
|
||||||
allowed_origin:
|
allowed_origin:
|
||||||
- '*'
|
- "*"
|
||||||
|
|
||||||
# Search coordinator thread pool sizes
|
# -------------------------------------------------------------------------------
|
||||||
|
# L. Search Orchestration
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
search-coord-core-pool-size: 20
|
search-coord-core-pool-size: 20
|
||||||
search-coord-max-pool-size: 100
|
search-coord-max-pool-size: 100
|
||||||
search-coord-queue-capacity: 200
|
search-coord-queue-capacity: 200
|
||||||
|
|
||||||
# Search Prefetch Thresholds.
|
# Search Prefetch Thresholds.
|
||||||
|
|
||||||
# This setting sets the number of search results to prefetch. For example, if this list
|
# This setting sets the number of search results to prefetch. For example, if this list
|
||||||
# is set to [100, 1000, -1] then the server will initially load 100 results and not
|
# is set to [100, 1000, -1] then the server will initially load 100 results and not
|
||||||
# attempt to load more. If the user requests subsequent page(s) of results and goes
|
# attempt to load more. If the user requests subsequent page(s) of results and goes
|
||||||
@@ -367,28 +345,27 @@ hapi:
|
|||||||
# The system will progressively work through these thresholds.
|
# The system will progressively work through these thresholds.
|
||||||
# A threshold of -1 means to load all results. Note that if the final threshold is a
|
# A threshold of -1 means to load all results. Note that if the final threshold is a
|
||||||
# number other than -1, the system will never prefetch more than the given number.
|
# number other than -1, the system will never prefetch more than the given number.
|
||||||
|
# CSV list; -1 as final value means "all"
|
||||||
search_prefetch_thresholds: 13,503,2003,-1
|
search_prefetch_thresholds: 13,503,2003,-1
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# M. Extensibility (custom beans / interceptors / providers)
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# comma-separated package names, will be @ComponentScan'ed by Spring to allow for creating custom Spring beans
|
# comma-separated package names, will be @ComponentScan'ed by Spring to allow for creating custom Spring beans
|
||||||
#custom-bean-packages:
|
|
||||||
|
|
||||||
# comma-separated list of fully qualified interceptor classes.
|
|
||||||
# classes listed here will be fetched from the Spring context when combined with 'custom-bean-packages',
|
|
||||||
# or will be instantiated via reflection using a no-arg constructor; then registered with the server
|
|
||||||
#custom-interceptor-classes:
|
|
||||||
|
|
||||||
# comma-separated list of fully qualified provider classes.
|
|
||||||
# classes listed here will be fetched from the Spring context when combined with 'custom-bean-packages',
|
|
||||||
# or will be instantiated via reflection using a no-arg constructor; then registered with the server
|
|
||||||
# custom-provider-classes:
|
# custom-provider-classes:
|
||||||
# specify what should be stored in meta.source based on StoreMetaSourceInformationEnum defaults to NONE
|
# custom-interceptor-classes:
|
||||||
|
# custom-provider-classes:
|
||||||
|
|
||||||
# store_meta_source_information: NONE
|
# store_meta_source_information: NONE
|
||||||
# Threadpool size for BATCH'ed GETs in a bundle.
|
|
||||||
# bundle_batch_pool_size: 10
|
# bundle_batch_pool_size: 10
|
||||||
# bundle_batch_pool_max_size: 50
|
# bundle_batch_pool_max_size: 50
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# N. Logging
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# logger:
|
# logger:
|
||||||
# error_format: 'ERROR - ${requestVerb} ${requestUrl}'
|
# error_format: "ERROR - ${requestVerb} ${requestUrl}"
|
||||||
# format: >-
|
# format: >-
|
||||||
# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
|
# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
|
||||||
# Operation[${operationType} ${operationName} ${idOrResourceName}]
|
# Operation[${operationType} ${operationName} ${idOrResourceName}]
|
||||||
@@ -396,39 +373,33 @@ hapi:
|
|||||||
# ResponseEncoding[${responseEncodingNoDefault}]
|
# ResponseEncoding[${responseEncodingNoDefault}]
|
||||||
# log_exceptions: true
|
# log_exceptions: true
|
||||||
# name: fhirtest.access
|
# name: fhirtest.access
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# O. Storage / Pagination / Caching
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# max_binary_size: 104857600
|
# max_binary_size: 104857600
|
||||||
# max_page_size: 200
|
# max_page_size: 200
|
||||||
# retain_cached_searches_mins: 60
|
# retain_cached_searches_mins: 60
|
||||||
# reuse_cached_search_results_millis: 60000
|
# reuse_cached_search_results_millis: 60000
|
||||||
# The remote_terminology_service block is commented out by default because it requires external terminology service endpoints.
|
inline_resource_storage_below_size: 4000
|
||||||
# Uncomment and configure the block below if you need to enable remote terminology validation or mapping.
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# P. Remote Terminology Service (disabled by default)
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# remote_terminology_service:
|
# remote_terminology_service:
|
||||||
# all:
|
# all:
|
||||||
# system: '*'
|
# system: "*"
|
||||||
# url: 'https://tx.fhir.org/r4/'
|
# url: "https://tx.fhir.org/r4/"
|
||||||
# snomed:
|
# snomed:
|
||||||
# system: 'http://snomed.info/sct'
|
# system: "http://snomed.info/sct"
|
||||||
# url: 'https://tx.fhir.org/r4/'
|
# url: "https://tx.fhir.org/r4/"
|
||||||
# loinc:
|
# loinc:
|
||||||
# system: 'http://loinc.org'
|
# system: "http://loinc.org"
|
||||||
# url: 'https://hapi.fhir.org/baseR4/'
|
# url: "https://hapi.fhir.org/baseR4/"
|
||||||
tester:
|
|
||||||
home:
|
# -------------------------------------------------------------------------------
|
||||||
name: Local Tester
|
# Q. Subscriptions (disabled by default)
|
||||||
server_address: 'http://localhost:8080/fhir'
|
# -------------------------------------------------------------------------------
|
||||||
refuse_to_fetch_third_party_urls: false
|
|
||||||
fhir_version: R4
|
|
||||||
global:
|
|
||||||
name: Global Tester
|
|
||||||
server_address: "http://hapi.fhir.org/baseR4"
|
|
||||||
refuse_to_fetch_third_party_urls: false
|
|
||||||
fhir_version: R4
|
|
||||||
# validation:
|
|
||||||
# requests_enabled: true
|
|
||||||
# responses_enabled: true
|
|
||||||
# binary_storage_enabled: true
|
|
||||||
inline_resource_storage_below_size: 4000
|
|
||||||
# bulk_export_enabled: true
|
|
||||||
# subscription:
|
# subscription:
|
||||||
# resthook_enabled: true
|
# resthook_enabled: true
|
||||||
# websocket_enabled: false
|
# websocket_enabled: false
|
||||||
@@ -444,10 +415,8 @@ hapi:
|
|||||||
# startTlsEnable:
|
# startTlsEnable:
|
||||||
# startTlsRequired:
|
# startTlsRequired:
|
||||||
# quitWait:
|
# quitWait:
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
# R. LastN (analytics)
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
# lastn_enabled: true
|
# lastn_enabled: true
|
||||||
# store_resource_in_lucene_index_enabled: true
|
|
||||||
### This is configuration for normalized quantity search level default is 0
|
|
||||||
### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default
|
|
||||||
### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED
|
|
||||||
### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED
|
|
||||||
# normalized_quantity_search_level: 2
|
|
||||||
|
|||||||
@@ -53,13 +53,14 @@ spring:
|
|||||||
maximum-pool-size: 10
|
maximum-pool-size: 10
|
||||||
jpa:
|
jpa:
|
||||||
properties:
|
properties:
|
||||||
hibernate.format_sql: false
|
hibernate:
|
||||||
hibernate.show_sql: false
|
format_sql: false
|
||||||
|
show_sql: false
|
||||||
|
|
||||||
#Hibernate dialect is automatically detected except Postgres and H2.
|
#Hibernate dialect is automatically detected except Postgres and H2.
|
||||||
#If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
#If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||||
#If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect
|
#If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect
|
||||||
hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||||
# hibernate.hbm2ddl.auto: update
|
# hibernate.hbm2ddl.auto: update
|
||||||
# hibernate.jdbc.batch_size: 20
|
# hibernate.jdbc.batch_size: 20
|
||||||
# hibernate.cache.use_query_cache: false
|
# hibernate.cache.use_query_cache: false
|
||||||
@@ -68,7 +69,9 @@ spring:
|
|||||||
# hibernate.cache.use_minimal_puts: false
|
# hibernate.cache.use_minimal_puts: false
|
||||||
|
|
||||||
### These settings will enable fulltext search with lucene or elastic
|
### These settings will enable fulltext search with lucene or elastic
|
||||||
hibernate.search.enabled: true
|
|
||||||
|
search:
|
||||||
|
enabled: true
|
||||||
### lucene parameters
|
### lucene parameters
|
||||||
# hibernate.search.backend.type: lucene
|
# hibernate.search.backend.type: lucene
|
||||||
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||||
@@ -78,6 +81,10 @@ spring:
|
|||||||
### elastic parameters ===> see also elasticsearch section below <===
|
### elastic parameters ===> see also elasticsearch section below <===
|
||||||
# hibernate.search.backend.type: elasticsearch
|
# hibernate.search.backend.type: elasticsearch
|
||||||
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
||||||
|
autoconfigure:
|
||||||
|
# This exclude is only needed for setups not using Elasticsearch where the elasticsearch sniff is not needed.
|
||||||
|
exclude: org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
|
||||||
|
|
||||||
hapi:
|
hapi:
|
||||||
fhir:
|
fhir:
|
||||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
|||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
||||||
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
||||||
@@ -35,15 +36,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, NicknameServiceConfig.class, RepositoryConfig.class, TestCdsHooksConfig.class, CrCdsHooksConfig.class, StarterCdsHooksConfig.class},
|
||||||
classes = {
|
properties = {
|
||||||
Application.class,
|
|
||||||
NicknameServiceConfig.class,
|
|
||||||
RepositoryConfig.class,
|
|
||||||
TestCdsHooksConfig.class,
|
|
||||||
CrCdsHooksConfig.class,
|
|
||||||
StarterCdsHooksConfig.class
|
|
||||||
}, properties = {
|
|
||||||
"spring.profiles.include=storageSettingsTest",
|
"spring.profiles.include=storageSettingsTest",
|
||||||
"spring.datasource.url=jdbc:h2:mem:dbr4",
|
"spring.datasource.url=jdbc:h2:mem:dbr4",
|
||||||
"spring.jpa.properties.hibernate.search.backend.directory.type=local-heap",
|
"spring.jpa.properties.hibernate.search.backend.directory.type=local-heap",
|
||||||
@@ -53,7 +47,8 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||||||
"hapi.fhir.cr.caregaps.section_author=Organization/alphora-author",
|
"hapi.fhir.cr.caregaps.section_author=Organization/alphora-author",
|
||||||
"hapi.fhir.cr.caregaps.reporter=Organization/alphora",
|
"hapi.fhir.cr.caregaps.reporter=Organization/alphora",
|
||||||
"hapi.fhir.cdshooks.enabled=true",
|
"hapi.fhir.cdshooks.enabled=true",
|
||||||
"spring.main.allow-bean-definition-overriding=true"})
|
"spring.main.allow-bean-definition-overriding=true",
|
||||||
|
"server.max-http-request-header-size=16KB"})
|
||||||
class CdsHooksServletIT implements IServerSupport {
|
class CdsHooksServletIT implements IServerSupport {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CdsHooksServletIT.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CdsHooksServletIT.class);
|
||||||
private final FhirContext ourCtx = FhirContext.forR4Cached();
|
private final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
@@ -162,77 +157,81 @@ class CdsHooksServletIT implements IServerSupport {
|
|||||||
loadBundle("r4/opioidcds-10-order-sign-bundle.json", ourCtx, ourClient);
|
loadBundle("r4/opioidcds-10-order-sign-bundle.json", ourCtx, ourClient);
|
||||||
await().atMost(20000, TimeUnit.MILLISECONDS).until(this::hasCdsServices);
|
await().atMost(20000, TimeUnit.MILLISECONDS).until(this::hasCdsServices);
|
||||||
var fhirServer = " \"fhirServer\": " + "\"" + ourServerBase + "\"" + ",\n";
|
var fhirServer = " \"fhirServer\": " + "\"" + ourServerBase + "\"" + ",\n";
|
||||||
var cdsRequest = "{\n" +
|
var cdsRequest = """
|
||||||
" \"hookInstance\": \"055b009c-4a7d-4db4-a35e-0e5198918ed1\",\n" +
|
{
|
||||||
" \"hook\": \"order-sign\",\n" +
|
"hookInstance": "055b009c-4a7d-4db4-a35e-0e5198918ed1",
|
||||||
fhirServer +
|
"hook": "order-sign",
|
||||||
" \"context\": {\n" +
|
""" + fhirServer + """
|
||||||
" \"patientId\": \"example-rec-10-order-sign-illicit-POS-Cocaine-drugs\",\n" +
|
"context": {
|
||||||
" \"userId\": \"COREPRACTITIONER1\",\n" +
|
"patientId": "example-rec-10-order-sign-illicit-POS-Cocaine-drugs",
|
||||||
" \"draftOrders\": {\n" +
|
"userId": "COREPRACTITIONER1",
|
||||||
" \"resourceType\": \"Bundle\",\n" +
|
"draftOrders": {
|
||||||
" \"entry\": [\n" +
|
"resourceType": "Bundle",
|
||||||
" {\n" +
|
"entry": [
|
||||||
" \"resource\": {\n" +
|
{
|
||||||
" \"resourceType\": \"MedicationRequest\",\n" +
|
"resource": {
|
||||||
" \"id\": \"request-123\",\n" +
|
"resourceType": "MedicationRequest",
|
||||||
" \"status\": \"draft\",\n" +
|
"id": "request-123",
|
||||||
" \"subject\": {\n" +
|
"status": "draft",
|
||||||
" \"reference\": \"Patient/example-rec-10-order-sign-illicit-POS-Cocaine-drugs\"\n" +
|
"subject": {
|
||||||
" },\n" +
|
"reference": "Patient/example-rec-10-order-sign-illicit-POS-Cocaine-drugs"
|
||||||
" \"authoredOn\": \"2024-03-27\",\n" +
|
},
|
||||||
" \"dosageInstruction\": [\n" +
|
"authoredOn": "2024-03-27",
|
||||||
" {\n" +
|
"dosageInstruction": [
|
||||||
" \"timing\": {\n" +
|
{
|
||||||
" \"repeat\": {\n" +
|
"timing": {
|
||||||
" \"frequency\": 1,\n" +
|
"repeat": {
|
||||||
" \"period\": 1,\n" +
|
"frequency": 1,
|
||||||
" \"periodUnit\": \"d\"\n" +
|
"period": 1,
|
||||||
" }\n" +
|
"periodUnit": "d"
|
||||||
" },\n" +
|
}
|
||||||
" \"doseAndRate\": [\n" +
|
},
|
||||||
" {\n" +
|
"doseAndRate": [
|
||||||
" \"doseQuantity\": {\n" +
|
{
|
||||||
" \"value\": 1,\n" +
|
"doseQuantity": {
|
||||||
" \"system\": \"http://unitsofmeasure.org\",\n" +
|
"value": 1,
|
||||||
" \"code\": \"{pill}\"\n" +
|
"system": "http://unitsofmeasure.org",
|
||||||
" }\n" +
|
"code": "{pill}"
|
||||||
" }\n" +
|
}
|
||||||
" ]\n" +
|
}
|
||||||
" }\n" +
|
]
|
||||||
" ],\n" +
|
}
|
||||||
" \"dispenseRequest\": {\n" +
|
],
|
||||||
" \"expectedSupplyDuration\": {\n" +
|
"dispenseRequest": {
|
||||||
" \"value\": 90,\n" +
|
"expectedSupplyDuration": {
|
||||||
" \"unit\": \"days\",\n" +
|
"value": 90,
|
||||||
" \"system\": \"http://unitsofmeasure.org\",\n" +
|
"unit": "days",
|
||||||
" \"code\": \"d\"\n" +
|
"system": "http://unitsofmeasure.org",
|
||||||
" }\n" +
|
"code": "d"
|
||||||
" },\n" +
|
}
|
||||||
" \"intent\": \"order\",\n" +
|
},
|
||||||
" \"category\": {\n" +
|
"intent": "order",
|
||||||
" \"coding\": [\n" +
|
"category": [
|
||||||
" {\n" +
|
{
|
||||||
" \"system\": \"http://terminology.hl7.org/CodeSystem/medicationrequest-category\",\n" +
|
"coding": [
|
||||||
" \"code\": \"community\"\n" +
|
{
|
||||||
" }\n" +
|
"system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category",
|
||||||
" ]\n" +
|
"code": "community"
|
||||||
" },\n" +
|
}
|
||||||
" \"medicationCodeableConcept\": {\n" +
|
]
|
||||||
" \"coding\": [\n" +
|
}
|
||||||
" {\n" +
|
],
|
||||||
" \"system\": \"http://www.nlm.nih.gov/research/umls/rxnorm\",\n" +
|
"medicationCodeableConcept": {
|
||||||
" \"code\": \"1049502\",\n" +
|
"coding": [
|
||||||
" \"display\": \"12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet\"\n" +
|
{
|
||||||
" }\n" +
|
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
" ]\n" +
|
"code": "1049502",
|
||||||
" }\n" +
|
"display": "12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet"
|
||||||
" }\n" +
|
}
|
||||||
" }\n" +
|
]
|
||||||
" ]\n" +
|
}
|
||||||
" }\n" +
|
}
|
||||||
" }\n" +
|
}
|
||||||
"}";
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||||
HttpPost request = new HttpPost(ourCdsBase + "/opioidcds-10-order-sign");
|
HttpPost request = new HttpPost(ourCdsBase + "/opioidcds-10-order-sign");
|
||||||
request.setEntity(new StringEntity(cdsRequest));
|
request.setEntity(new StringEntity(cdsRequest));
|
||||||
|
|||||||
Reference in New Issue
Block a user