Merge branch 'master' into cr-6.9.6-snapshot

This commit is contained in:
Justin McKelvy
2023-11-27 08:40:31 -07:00
committed by GitHub
10 changed files with 163 additions and 6 deletions

View File

@@ -20,10 +20,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 17
distribution: zulu
- name: Build with Maven
run: mvn -B package --file pom.xml verify

View File

@@ -21,11 +21,12 @@ jobs:
steps:
- name: Checkout project
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 17
distribution: zulu
- name: Build with Maven
run: mvn -B package --file pom.xml -Dmaven.test.skip=true
- name: Docker Pull HTTP client

View File

@@ -515,6 +515,32 @@ To add a custom operation, refer to the documentation in the core hapi-fhir libr
Within `hapi-fhir-jpaserver-starter`, create a generic class (that does not extend or implement any classes or interfaces), add the `@Operation` as a method within the generic class, and then register the class as a provider using `RestfulServer.registerProvider()`.
## Runtime package install
It's possible to install a FHIR Implementation Guide package (`package.tgz`) either from a published package or from a local package with the `$install` operation, without having to restart the server. This is available for R4 and R5.
This feature must be enabled in the application.yaml (or docker command line):
```yaml
hapi:
fhir:
ig_runtime_upload_enabled: true
```
The `$install` operation is triggered with a POST to `[server]/ImplementationGuide/$install`, with the payload below:
```json
{
"resourceType": "Parameters",
"parameter": [
{
"name": "npmContent",
"valueBase64Binary": "[BASE64_ENCODED_NPM_PACKAGE_DATA]"
}
]
}
```
## Enable OpenTelemetry auto-instrumentation
The container image includes the [OpenTelemetry Java auto-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation)

View File

@@ -76,6 +76,18 @@ public class AppProperties {
private Boolean reload_existing_implementationguides = false;
private Map<String, PackageInstallationSpec> implementationGuides = null;
private Boolean cr_enabled = false;
private Boolean ig_runtime_upload_enabled = false;
private Validation validation = new Validation();
private Map<String, Tester> tester = null;
private Logger logger = new Logger();
private Subscription subscription = new Subscription();
private Cors cors = null;
private Partitioning partitioning = null;
private Boolean install_transitive_ig_dependencies = true;
private Map<String, PackageInstallationSpec> implementationGuides = null;
private String staticLocation = null;
private String staticLocationPrefix = "/static";
private Boolean lastn_enabled = false;
@@ -579,6 +591,14 @@ public class AppProperties {
return local_base_urls;
}
public Boolean getIg_runtime_upload_enabled() {
return ig_runtime_upload_enabled;
}
public void setIg_runtime_upload_enabled(Boolean ig_runtime_upload_enabled) {
this.ig_runtime_upload_enabled = ig_runtime_upload_enabled;
}
public static class Cors {
private Boolean allow_Credentials = true;
private List<String> allowed_origin = List.of("*");

View File

@@ -44,6 +44,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent;
import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent;
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
@@ -241,7 +242,7 @@ public class StarterJpaConfig {
}
@Bean
public RestfulServer restfulServer(IFhirSystemDao<?, ?> fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional<MdmProviderLoader> mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional<TerminologyUploaderProvider> terminologyUploaderProvider, Optional<SubscriptionTriggeringProvider> subscriptionTriggeringProvider, Optional<CorsInterceptor> corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional<BinaryAccessProvider> binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional<GraphQLProvider> graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional<RepositoryValidatingInterceptor> repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional<IpsOperationProvider> theIpsOperationProvider) {
public RestfulServer restfulServer(IFhirSystemDao<?, ?> fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional<MdmProviderLoader> mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional<TerminologyUploaderProvider> terminologyUploaderProvider, Optional<SubscriptionTriggeringProvider> subscriptionTriggeringProvider, Optional<CorsInterceptor> corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional<BinaryAccessProvider> binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional<GraphQLProvider> graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional<RepositoryValidatingInterceptor> repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
@@ -304,6 +305,8 @@ public class StarterJpaConfig {
fhirServer.registerInterceptor(loggingInterceptor);
implementationGuideOperationProvider.ifPresent(fhirServer::registerProvider);
/*
* If you are hosting this server at a specific DNS name, the server will try to
* figure out the FHIR base URL based on what the web container tells it, but

View File

@@ -0,0 +1,18 @@
package ca.uhn.fhir.jpa.starter.ig;
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
import org.hl7.fhir.utilities.npm.NpmPackage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public interface IImplementationGuideOperationProvider {
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
return new PackageInstallationSpec().setName(npmPackage.name()).setPackageContents(npmPackageAsByteArray).setVersion(npmPackage.version()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(false);
}
//The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
//@Operation(name = "$install", typeName = "ImplementationGuide")
//Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
}

View File

@@ -0,0 +1,14 @@
package ca.uhn.fhir.jpa.starter.ig;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class IgConfigCondition implements Condition {
@Override
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.ig_runtime_upload_enabled");
return Boolean.parseBoolean(property);
}
}

View File

@@ -0,0 +1,35 @@
package ca.uhn.fhir.jpa.starter.ig;
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import org.hl7.fhir.r4.model.Base64BinaryType;
import org.hl7.fhir.r4.model.Parameters;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Conditional({OnR4Condition.class, IgConfigCondition.class})
@Service
public class ImplementationGuideR4OperationProvider implements IImplementationGuideOperationProvider {
IPackageInstallerSvc packageInstallerSvc;
public ImplementationGuideR4OperationProvider(IPackageInstallerSvc packageInstallerSvc) {
this.packageInstallerSvc = packageInstallerSvc;
}
@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}
}

View File

@@ -0,0 +1,36 @@
package ca.uhn.fhir.jpa.starter.ig;
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import org.hl7.fhir.r5.model.Base64BinaryType;
import org.hl7.fhir.r5.model.Parameters;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Conditional({OnR5Condition.class, IgConfigCondition.class})
@Service
public class ImplementationGuideR5OperationProvider {
IPackageInstallerSvc packageInstallerSvc;
public ImplementationGuideR5OperationProvider(IPackageInstallerSvc packageInstallerSvc) {
this.packageInstallerSvc = packageInstallerSvc;
}
@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}
}

View File

@@ -56,7 +56,7 @@ hapi:
### 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.
cr:
enabled: true
enabled: false
cdshooks:
enabled: true
@@ -66,6 +66,9 @@ hapi:
openapi_enabled: true
### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5
fhir_version: R4
### Flag is false by default. This flag enables runtime installation of IG's.
ig_runtime_upload_enabled: false
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers
### to determine the FHIR server address