diff --git a/pom.xml b/pom.xml
index 661ee01..94d87c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,12 @@
hapi-fhir-jpaserver-starter
+
+ 11
+ ${java.version}
+ ${java.version}
+
+
3.6.0
@@ -293,8 +299,6 @@
-
-
org.springframework.boot
@@ -374,6 +378,9 @@
src/main/webapp/WEB-INF/web.xml
+
+ false
+
diff --git a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java
index b1f74a2..d54dfea 100644
--- a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java
+++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java
@@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.empi;
import ca.uhn.fhir.empi.api.IEmpiSettings;
import ca.uhn.fhir.empi.rules.config.EmpiRuleValidator;
import ca.uhn.fhir.empi.rules.config.EmpiSettings;
+import ca.uhn.fhir.jpa.starter.AppProperties;
import ca.uhn.fhir.jpa.starter.HapiProperties;
import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
@@ -21,11 +22,11 @@ import java.io.IOException;
public class EmpiConfig {
@Bean
- IEmpiSettings empiSettings(EmpiRuleValidator theEmpiRuleValidator) throws IOException {
+ IEmpiSettings empiSettings(EmpiRuleValidator theEmpiRuleValidator, AppProperties appProperties) throws IOException {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("empi-rules.json");
String json = IOUtils.toString(resource.getInputStream(), Charsets.UTF_8);
- return new EmpiSettings(theEmpiRuleValidator).setEnabled(HapiProperties.getEmpiEnabled()).setScriptText(json);
+ return new EmpiSettings(theEmpiRuleValidator).setEnabled(appProperties.getEmpi_enabled()).setScriptText(json);
}
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
index a3cd5d2..b8613b4 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
@@ -4,8 +4,11 @@ package ca.uhn.fhir.jpa.starter;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.api.config.DaoConfig.ClientIdStrategyEnum;
import ca.uhn.fhir.rest.api.EncodingEnum;
+
import java.util.ArrayList;
import java.util.List;
+
+import org.hl7.fhir.r4.model.Bundle;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@@ -16,7 +19,7 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties
public class AppProperties {
-
+ private Boolean empi_enabled = false;
private Boolean allow_cascading_deletes = false;
private Boolean allow_contains_searches = true;
private Boolean allow_external_references = false;
@@ -24,7 +27,6 @@ public class AppProperties {
private Boolean allow_override_default_search_params = true;
private Boolean allow_placeholder_references = true;
private Boolean auto_create_placeholder_reference_targets = true;
- private Integer default_page_size = 20;
private Boolean enable_index_missing_fields = false;
private Boolean enforce_referential_integrity_on_delete = true;
private Boolean enforce_referential_integrity_on_write = true;
@@ -35,23 +37,79 @@ public class AppProperties {
private Boolean graphql_enabled = true;
private Boolean binary_storage_enabled = true;
private Boolean bulk_export_enabled = true;
- private Integer max_binary_size = 104857600;
+ private Boolean default_pretty_print = true;
+ private Integer default_page_size = 20;
+ private Integer max_binary_size = null;
private Integer max_page_size = Integer.MAX_VALUE;
- private Integer retain_cached_searches_mins = 60;
+ private Long retain_cached_searches_mins = 60L;
private Long reuse_cached_search_results_millis = 60000L;
+ private String server_address = null;
private EncodingEnum default_encoding = EncodingEnum.JSON;
private FhirVersionEnum fhir_version = FhirVersionEnum.R4;
private ClientIdStrategyEnum client_id_strategy = ClientIdStrategyEnum.ALPHANUMERIC;
+ private List supported_resource_types = new ArrayList<>();
+ private List allowed_bundle_types = null;
private Validation validation = new Validation();
private List tester = new ArrayList<>();
private Logger logger = new Logger();
private Subscription subscription = new Subscription();
+ private Cors cors = null;
+ private Partitioning partitioning = null;
+
+ public Partitioning getPartitioning() {
+ return partitioning;
+ }
+
+ public void setPartitioning(Partitioning partitioning) {
+ this.partitioning = partitioning;
+ }
+
+ public Boolean getEmpi_enabled() {
+ return empi_enabled;
+ }
+
+ public void setEmpi_enabled(Boolean empi_enabled) {
+ this.empi_enabled = empi_enabled;
+ }
+
+
+ public Cors getCors() {
+ return cors;
+ }
+
+ public void setCors(Cors cors) {
+ this.cors = cors;
+ }
+
+ public List getAllowed_bundle_types() {
+ return allowed_bundle_types;
+ }
+
+ public void setAllowed_bundle_types(List allowed_bundle_types) {
+ this.allowed_bundle_types = allowed_bundle_types;
+ }
+
+ public String getServer_address() {
+ return server_address;
+ }
+
+ public void setServer_address(String server_address) {
+ this.server_address = server_address;
+ }
public Subscription getSubscription() {
return subscription;
}
+ public Boolean getDefault_pretty_print() {
+ return default_pretty_print;
+ }
+
+ public void setDefault_pretty_print(Boolean default_pretty_print) {
+ this.default_pretty_print = default_pretty_print;
+ }
+
public void setSubscription(Subscription subscription) {
this.subscription = subscription;
}
@@ -64,6 +122,13 @@ public class AppProperties {
this.validation = validation;
}
+ public List getSupported_resource_types() {
+ return supported_resource_types;
+ }
+
+ public void setSupported_resource_types(List supported_resource_types) {
+ this.supported_resource_types = supported_resource_types;
+ }
public Logger getLogger() {
return logger;
@@ -262,11 +327,11 @@ public class AppProperties {
this.max_page_size = max_page_size;
}
- public Integer getRetain_cached_searches_mins() {
+ public Long getRetain_cached_searches_mins() {
return retain_cached_searches_mins;
}
- public void setRetain_cached_searches_mins(Integer retain_cached_searches_mins) {
+ public void setRetain_cached_searches_mins(Long retain_cached_searches_mins) {
this.retain_cached_searches_mins = retain_cached_searches_mins;
}
@@ -286,6 +351,29 @@ public class AppProperties {
this.tester = tester;
}
+ public static class Cors {
+ private Boolean allow_Credentials = true;
+ private List allowed_origin = new ArrayList<>();//List.of("*");
+
+ public List getAllowed_origin() {
+ return allowed_origin;
+ }
+
+ public void setAllowed_origin(List allowed_origin) {
+ this.allowed_origin = allowed_origin;
+ }
+
+ public Boolean getAllow_Credentials() {
+ return allow_Credentials;
+ }
+
+ public void setAllow_Credentials(Boolean allow_Credentials) {
+ this.allow_Credentials = allow_Credentials;
+ }
+
+
+ }
+
public static class Logger {
private String name = "fhirtest.access";
@@ -398,16 +486,22 @@ public class AppProperties {
}
}
+ public static class Partitioning {
+
+ private Boolean partitioning_include_in_search_hashes = false;
+
+
+ public Boolean getPartitioning_include_in_search_hashes() {
+ return partitioning_include_in_search_hashes;
+ }
+
+ public void setPartitioning_include_in_search_hashes(Boolean partitioning_include_in_search_hashes) {
+ this.partitioning_include_in_search_hashes = partitioning_include_in_search_hashes;
+ }
+ }
+
public static class Subscription {
- public Boolean getEmail_enabled() {
- return email_enabled;
- }
-
- public void setEmail_enabled(Boolean email_enabled) {
- this.email_enabled = email_enabled;
- }
-
public Boolean getResthook_enabled() {
return resthook_enabled;
}
@@ -424,8 +518,101 @@ public class AppProperties {
this.websocket_enabled = websocket_enabled;
}
- private Boolean email_enabled = false;
private Boolean resthook_enabled = false;
private Boolean websocket_enabled = false;
+ private Email email = null;
+
+ public Email getEmail() {
+ return email;
+ }
+
+ public void setEmail(Email email) {
+ this.email = email;
+ }
+
+
+ public static class Email {
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Boolean getAuth() {
+ return auth;
+ }
+
+ public void setAuth(Boolean auth) {
+ this.auth = auth;
+ }
+
+ public Boolean getStartTlsEnable() {
+ return startTlsEnable;
+ }
+
+ public void setStartTlsEnable(Boolean startTlsEnable) {
+ this.startTlsEnable = startTlsEnable;
+ }
+
+ public Boolean getStartTlsRequired() {
+ return startTlsRequired;
+ }
+
+ public void setStartTlsRequired(Boolean startTlsRequired) {
+ this.startTlsRequired = startTlsRequired;
+ }
+
+ public Boolean getQuitWait() {
+ return quitWait;
+ }
+
+ public void setQuitWait(Boolean quitWait) {
+ this.quitWait = quitWait;
+ }
+
+ private String from;
+ private String host;
+ private Integer port = 25;
+ private String username;
+ private String password;
+ private Boolean auth = false;
+ private Boolean startTlsEnable = false;
+ private Boolean startTlsRequired = false;
+ private Boolean quitWait = false;
+ }
}
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
index be03b5f..e09c995 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
@@ -34,7 +34,7 @@ public class Application {
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setServlet(dispatcherServlet);
- registrationBean.addUrlMappings("/*");
+ registrationBean.addUrlMappings("/hapi-fhir-jpaserver/*", "/*");
registrationBean.setLoadOnStartup(1);
return registrationBean;
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java
index e359e3d..168a06b 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java
@@ -4,7 +4,6 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
-import ca.uhn.fhir.jpa.api.IDaoRegistry;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
@@ -12,56 +11,36 @@ import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor;
import ca.uhn.fhir.jpa.bulk.provider.BulkDataExportProvider;
import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor;
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
-import ca.uhn.fhir.jpa.provider.GraphQLProvider;
-import ca.uhn.fhir.jpa.provider.IJpaSystemProvider;
-import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
-import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
-import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
-import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
+import ca.uhn.fhir.jpa.provider.*;
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
-import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
-import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5;
-import ca.uhn.fhir.jpa.provider.r5.JpaSystemProviderR5;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
-import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
+import ca.uhn.fhir.rest.server.ETagSupportEnum;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.RestfulServer;
-import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.FhirPathFilterInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
+import ca.uhn.fhir.rest.server.interceptor.*;
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ResultSeverityEnum;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.servlet.ServletException;
-import org.hl7.fhir.dstu3.model.Bundle;
-import org.hl7.fhir.dstu3.model.Meta;
+import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Bundle.BundleType;
-import org.springframework.aop.framework.Advised;
-import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsConfiguration;
+import javax.servlet.ServletException;
+import java.util.*;
+import java.util.stream.Collectors;
+
public class BaseJpaRestfulServer extends RestfulServer {
- AppProperties hapiProperties;
@Autowired
DaoRegistry daoRegistry;
@@ -81,8 +60,35 @@ public class BaseJpaRestfulServer extends RestfulServer {
@Autowired
IJpaSystemProvider jpaSystemProvider;
- public BaseJpaRestfulServer(AppProperties appProperties) {
- this.hapiProperties = appProperties;
+ @Autowired
+ IInterceptorBroadcaster interceptorBroadcaster;
+
+ @Autowired
+ DatabaseBackedPagingProvider databaseBackedPagingProvider;
+
+ @Autowired
+ IInterceptorService interceptorService;
+
+ @Autowired
+ IValidatorModule validatorModule;
+
+ @Autowired
+ Optional graphQLProvider;
+
+ @Autowired
+ BulkDataExportProvider bulkDataExportProvider;
+
+ @Autowired
+ PartitionManagementProvider partitionManagementProvider;
+
+ @Autowired
+ BinaryStorageInterceptor binaryStorageInterceptor;
+
+ @Autowired
+ AppProperties appProperties;
+
+ public BaseJpaRestfulServer() {
+
}
private static final long serialVersionUID = 1L;
@@ -92,26 +98,18 @@ public class BaseJpaRestfulServer extends RestfulServer {
protected void initialize() throws ServletException {
super.initialize();
- ApplicationContext appCtx = (ApplicationContext) getServletContext()
- .getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
-
/*
* Create a FhirContext object that uses the version of FHIR
* specified in the properties file.
*/
// Customize supported resource types
- Set supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
+ List supportedResourceTypes = appProperties.getSupported_resource_types();
if (!supportedResourceTypes.isEmpty() && !supportedResourceTypes.contains("SearchParameter")) {
supportedResourceTypes.add("SearchParameter");
- }
-
- if (!supportedResourceTypes.isEmpty()) {
daoRegistry.setSupportedResourceTypes(supportedResourceTypes);
}
-
-
setFhirContext(fhirSystemDao.getContext());
registerProviders(resourceProviders.createProviders());
registerProvider(jpaSystemProvider);
@@ -160,7 +158,10 @@ public class BaseJpaRestfulServer extends RestfulServer {
/*
* ETag Support
*/
- setETagSupport(HapiProperties.getEtagSupport());
+
+ if(appProperties.getEtag_support_enabled() == false)
+ setETagSupport(ETagSupportEnum.DISABLED);
+
/*
* This server tries to dynamically generate narratives
@@ -171,12 +172,12 @@ public class BaseJpaRestfulServer extends RestfulServer {
/*
* Default to JSON and pretty printing
*/
- setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
+ setDefaultPrettyPrint(appProperties.getDefault_pretty_print());
/*
* Default encoding
*/
- setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
+ setDefaultResponseEncoding(appProperties.getDefault_encoding());
/*
* This configures the server to page search results to and from
@@ -185,7 +186,7 @@ public class BaseJpaRestfulServer extends RestfulServer {
* but makes the server much more scalable.
*/
- setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
+ setPagingProvider(databaseBackedPagingProvider);
/*
* This interceptor formats the output using nice colourful
@@ -195,7 +196,7 @@ public class BaseJpaRestfulServer extends RestfulServer {
ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
this.registerInterceptor(responseHighlighterInterceptor);
- if (HapiProperties.isFhirPathFilterInterceptorEnabled()) {
+ if (appProperties.getFhirpath_interceptor_enabled()) {
registerInterceptor(new FhirPathFilterInterceptor());
}
@@ -203,10 +204,10 @@ public class BaseJpaRestfulServer extends RestfulServer {
* Add some logging for each request
*/
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
- loggingInterceptor.setLoggerName(HapiProperties.getLoggerName());
- loggingInterceptor.setMessageFormat(HapiProperties.getLoggerFormat());
- loggingInterceptor.setErrorMessageFormat(HapiProperties.getLoggerErrorFormat());
- loggingInterceptor.setLogExceptions(HapiProperties.getLoggerLogExceptions());
+ loggingInterceptor.setLoggerName(appProperties.getLogger().getName());
+ loggingInterceptor.setMessageFormat(appProperties.getLogger().getFormat());
+ loggingInterceptor.setErrorMessageFormat(appProperties.getLogger().getError_format());
+ loggingInterceptor.setLogExceptions(appProperties.getLogger().getLog_exceptions());
this.registerInterceptor(loggingInterceptor);
/*
@@ -215,8 +216,8 @@ public class BaseJpaRestfulServer extends RestfulServer {
* this doesn't always work. If you are setting links in your search bundles that
* just refer to "localhost", you might want to use a server address strategy:
*/
- String serverAddress = HapiProperties.getServerAddress();
- if (serverAddress != null && serverAddress.length() > 0) {
+ String serverAddress = appProperties.getServer_address();
+ if (!Strings.isNullOrEmpty(serverAddress)) {
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
}
@@ -228,21 +229,21 @@ public class BaseJpaRestfulServer extends RestfulServer {
* with this feature.
*/
if (false) { // <-- DISABLED RIGHT NOW
- registerProvider(appCtx.getBean(TerminologyUploaderProvider.class));
+ //registerProvider(appCtx.getBean(TerminologyUploaderProvider.class));
}
// If you want to enable the $trigger-subscription operation to allow
// manual triggering of a subscription delivery, enable this provider
if (false) { // <-- DISABLED RIGHT NOW
- SubscriptionTriggeringProvider retriggeringProvider = appCtx
+ /* SubscriptionTriggeringProvider retriggeringProvider = appCtx
.getBean(SubscriptionTriggeringProvider.class);
- registerProvider(retriggeringProvider);
+ registerProvider(retriggeringProvider);*/
}
// Define your CORS configuration. This is an example
// showing a typical setup. You should customize this
// to your specific needs
- if (HapiProperties.getCorsEnabled()) {
+ if (appProperties.getCors() != null) {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedHeader(HttpHeaders.ORIGIN);
config.addAllowedHeader(HttpHeaders.ACCEPT);
@@ -252,17 +253,15 @@ public class BaseJpaRestfulServer extends RestfulServer {
config.addAllowedHeader("x-fhir-starter");
config.addAllowedHeader("X-Requested-With");
config.addAllowedHeader("Prefer");
- String allAllowedCORSOrigins = HapiProperties.getCorsAllowedOrigin();
- Arrays.stream(allAllowedCORSOrigins.split(",")).forEach(o -> {
- config.addAllowedOrigin(o);
- });
- config.addAllowedOrigin(HapiProperties.getCorsAllowedOrigin());
+ List allAllowedCORSOrigins = appProperties.getCors().getAllowed_origin();
+ allAllowedCORSOrigins.forEach(config::addAllowedOrigin);
+
config.addExposedHeader("Location");
config.addExposedHeader("Content-Location");
config.setAllowedMethods(
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
- config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
+ config.setAllowCredentials(appProperties.getCors().getAllow_Credentials());
// Create the interceptor and register it
CorsInterceptor interceptor = new CorsInterceptor(config);
@@ -271,40 +270,35 @@ public class BaseJpaRestfulServer extends RestfulServer {
// If subscriptions are enabled, we want to register the interceptor that
// will activate them and match results against them
- if (HapiProperties.getSubscriptionWebsocketEnabled() ||
- HapiProperties.getSubscriptionEmailEnabled() ||
- HapiProperties.getSubscriptionRestHookEnabled()) {
+ if (appProperties.getSubscription() != null) {
// Subscription debug logging
- IInterceptorService interceptorService = appCtx.getBean(IInterceptorService.class);
interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor());
}
// Cascading deletes
- DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
- IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
- if (HapiProperties.getAllowCascadingDeletes()) {
+
+
+ if (appProperties.getAllow_cascading_deletes()) {
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(ctx,
daoRegistry, interceptorBroadcaster);
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
}
// Binary Storage
- if (HapiProperties.isBinaryStorageEnabled()) {
- BinaryStorageInterceptor binaryStorageInterceptor = appCtx
- .getBean(BinaryStorageInterceptor.class);
+ if (appProperties.getBinary_storage_enabled()) {
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
}
// Validation
- IValidatorModule validatorModule = appCtx.getBean(IValidatorModule.class);
+
if (validatorModule != null) {
- if (HapiProperties.getValidateRequestsEnabled()) {
+ if (appProperties.getValidation().getRequests_enabled()) {
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
registerInterceptor(interceptor);
}
- if (HapiProperties.getValidateResponsesEnabled()) {
+ if (appProperties.getValidation().getResponses_enabled()) {
ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
@@ -313,52 +307,33 @@ public class BaseJpaRestfulServer extends RestfulServer {
}
// GraphQL
- if (HapiProperties.getGraphqlEnabled()) {
+ if (appProperties.getGraphql_enabled()) {
if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
- registerProvider(appCtx.getBean(GraphQLProvider.class));
+ registerProvider(graphQLProvider.get());
}
}
- if (!HapiProperties.getAllowedBundleTypes().isEmpty()) {
- String allowedBundleTypesString = HapiProperties.getAllowedBundleTypes();
- Set allowedBundleTypes = new HashSet<>();
- Arrays.stream(allowedBundleTypesString.split(",")).forEach(o -> {
- BundleType type = BundleType.valueOf(o);
- allowedBundleTypes.add(type.toCode());
- });
- DaoConfig config = daoConfig;
- config.setBundleTypesAllowedForStorage(
- Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
+ if (appProperties.getAllowed_bundle_types() != null) {
+ daoConfig.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet()));
}
// Bulk Export
- if (HapiProperties.getBulkExportEnabled()) {
- registerProvider(appCtx.getBean(BulkDataExportProvider.class));
+ if (appProperties.getBulk_export_enabled()) {
+ registerProvider(bulkDataExportProvider);
}
// Partitioning
- if (HapiProperties.getPartitioningMultitenancyEnabled()) {
+ if (appProperties.getPartitioning() != null) {
registerInterceptor(new RequestTenantPartitionInterceptor());
setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy());
- registerProviders(appCtx.getBean(PartitionManagementProvider.class));
+ registerProviders(partitionManagementProvider);
}
- if (HapiProperties.getClientIdStrategy() == DaoConfig.ClientIdStrategyEnum.ANY) {
+ if (appProperties.getClient_id_strategy() == DaoConfig.ClientIdStrategyEnum.ANY) {
daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID);
- daoConfig.setResourceClientIdStrategy(HapiProperties.getClientIdStrategy());
+ daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy());
}
}
- protected T getBeanWithoutProxy(Object bean) {
-
- if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
- try {
- return (T) ((Advised) bean).getTargetSource().getTarget();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- return (T)bean;
- }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java
index d81361b..28aab92 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java
@@ -8,6 +8,7 @@ import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender;
import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender;
+import com.google.common.base.Strings;
import org.apache.commons.dbcp2.BasicDataSource;
import org.hl7.fhir.dstu2.model.Subscription;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,6 +21,7 @@ import org.thymeleaf.util.Validate;
import java.lang.reflect.InvocationTargetException;
import java.sql.Driver;
+import java.util.Optional;
/**
* This is the primary configuration file for the example server
@@ -30,23 +32,6 @@ public class FhirServerConfigCommon {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class);
-
-
- private Boolean subscriptionRestHookEnabled = HapiProperties.getSubscriptionRestHookEnabled();
- private Boolean subscriptionEmailEnabled = HapiProperties.getSubscriptionEmailEnabled();
-
- private String emailFrom = HapiProperties.getEmailFrom();
- private Boolean emailEnabled = HapiProperties.getEmailEnabled();
- private String emailHost = HapiProperties.getEmailHost();
- private Integer emailPort = HapiProperties.getEmailPort();
- private String emailUsername = HapiProperties.getEmailUsername();
- private String emailPassword = HapiProperties.getEmailPassword();
- private Boolean emailAuth = HapiProperties.getEmailAuth();
- private Boolean emailStartTlsEnable = HapiProperties.getEmailStartTlsEnable();
- private Boolean emailStartTlsRequired = HapiProperties.getEmailStartTlsRequired();
- private Boolean emailQuitWait = HapiProperties.getEmailQuitWait();
-
-
@Autowired
private ApplicationContext appContext;
@@ -58,24 +43,25 @@ public class FhirServerConfigCommon {
ourLog.info("Server configured to " + (appProperties.getAllow_placeholder_references() ? "allow" : "deny") + " placeholder references");
ourLog.info("Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny") + " overriding default search params");
- if (this.emailEnabled) {
- ourLog.info("Server is configured to enable email with host '" + this.emailHost + "' and port " + this.emailPort.toString());
- ourLog.info("Server will use '" + this.emailFrom + "' as the from email address");
+ if (appProperties.getSubscription().getEmail() != null) {
+ AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
+ ourLog.info("Server is configured to enable email with host '" + email.getHost() + "' and port " + email.getPort());
+ ourLog.info("Server will use '" + email.getFrom() + "' as the from email address");
- if (this.emailUsername != null && this.emailUsername.length() > 0) {
- ourLog.info("Server is configured to use username '" + this.emailUsername + "' for email");
+ if (!Strings.isNullOrEmpty(email.getUsername())) {
+ ourLog.info("Server is configured to use username '" + email.getUsername() + "' for email");
}
- if (this.emailPassword != null && this.emailPassword.length() > 0) {
+ if (!Strings.isNullOrEmpty(email.getPassword())) {
ourLog.info("Server is configured to use a password for email");
}
}
- if (this.subscriptionRestHookEnabled) {
+ if (appProperties.getSubscription().getResthook_enabled()) {
ourLog.info("REST-hook subscriptions enabled");
}
- if (this.subscriptionEmailEnabled) {
+ if (appProperties.getSubscription().getEmail() != null) {
ourLog.info("Email subscriptions enabled");
}
}
@@ -96,7 +82,8 @@ public class FhirServerConfigCommon {
retVal.setAllowExternalReferences(appProperties.getAllow_external_references());
retVal.setExpungeEnabled(appProperties.getExpunge_enabled());
retVal.setAutoCreatePlaceholderReferenceTargets(appProperties.getAllow_placeholder_references());
- retVal.setEmailFromAddress(this.emailFrom);
+ if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
+ retVal.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());
Integer maxFetchSize = appProperties.getMax_page_size();
retVal.setFetchSizeDefaultMaximum(maxFetchSize);
@@ -106,21 +93,24 @@ public class FhirServerConfigCommon {
retVal.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis);
- Long retainCachedSearchesMinutes = HapiProperties.getExpireSearchResultsAfterMins();
+
+ Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins();
retVal.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000);
- // Subscriptions are enabled by channel type
- if (appProperties.getSubscription().getResthook_enabled()) {
- ourLog.info("Enabling REST-hook subscriptions");
- retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
- }
- if (appProperties.getSubscription().getEmail_enabled()) {
- ourLog.info("Enabling email subscriptions");
- retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
- }
- if (appProperties.getSubscription().getWebsocket_enabled()) {
- ourLog.info("Enabling websocket subscriptions");
- retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
+ if(appProperties.getSubscription() != null) {
+ // Subscriptions are enabled by channel type
+ if (appProperties.getSubscription().getResthook_enabled()) {
+ ourLog.info("Enabling REST-hook subscriptions");
+ retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
+ }
+ if (appProperties.getSubscription().getEmail() != null) {
+ ourLog.info("Enabling email subscriptions");
+ retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
+ }
+ if (appProperties.getSubscription().getWebsocket_enabled()) {
+ ourLog.info("Enabling websocket subscriptions");
+ retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
+ }
}
retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
@@ -133,7 +123,7 @@ public class FhirServerConfigCommon {
PartitionSettings retVal = new PartitionSettings();
// Partitioning
- if (HapiProperties.getPartitioningMultitenancyEnabled()) {
+ if (appProperties.getPartitioning() != null) {
retVal.setPartitioningEnabled(true);
}
@@ -147,14 +137,15 @@ public class FhirServerConfigCommon {
modelConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches());
modelConfig.setAllowExternalReferences(appProperties.getAllow_external_references());
modelConfig.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params());
- modelConfig.setEmailFromAddress(this.emailFrom);
+ if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
+ modelConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());
// You can enable these if you want to support Subscriptions from your server
- if (this.subscriptionRestHookEnabled) {
+ if (appProperties.getSubscription() != null && appProperties.getSubscription().getResthook_enabled() != null) {
modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.RESTHOOK);
}
- if (this.subscriptionEmailEnabled) {
+ if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.EMAIL);
}
@@ -181,34 +172,33 @@ public class FhirServerConfigCommon {
@Lazy
@Bean
- public IBinaryStorageSvc binaryStorageSvc() {
+ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();
- if (HapiProperties.getMaxBinarySize() != null) {
- binaryStorageSvc.setMaximumBinarySize(HapiProperties.getMaxBinarySize());
+ if (appProperties.getMax_binary_size() != null) {
+ binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
}
return binaryStorageSvc;
}
@Bean()
- public IEmailSender emailSender() {
- if (this.emailEnabled) {
+ public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) {
+ if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
JavaMailEmailSender retVal = new JavaMailEmailSender();
- retVal.setSmtpServerHostname(this.emailHost);
- retVal.setSmtpServerPort(this.emailPort);
- retVal.setSmtpServerUsername(this.emailUsername);
- retVal.setSmtpServerPassword(this.emailPassword);
- retVal.setAuth(this.emailAuth);
- retVal.setStartTlsEnable(this.emailStartTlsEnable);
- retVal.setStartTlsRequired(this.emailStartTlsRequired);
- retVal.setQuitWait(this.emailQuitWait);
-
- SubscriptionDeliveryHandlerFactory subscriptionDeliveryHandlerFactory = appContext.getBean(SubscriptionDeliveryHandlerFactory.class);
- Validate.notNull(subscriptionDeliveryHandlerFactory, "No subscription delivery handler");
- subscriptionDeliveryHandlerFactory.setEmailSender(retVal);
+ AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
+ retVal.setSmtpServerHostname(email.getHost());
+ retVal.setSmtpServerPort(email.getPort());
+ retVal.setSmtpServerUsername(email.getUsername());
+ retVal.setSmtpServerPassword(email.getPassword());
+ retVal.setAuth(email.getAuth());
+ retVal.setStartTlsEnable(email.getStartTlsEnable());
+ retVal.setStartTlsRequired(email.getStartTlsRequired());
+ retVal.setQuitWait(email.getQuitWait());
+ if(subscriptionDeliveryHandlerFactory.isPresent())
+ subscriptionDeliveryHandlerFactory.get().setEmailSender(retVal);
return retVal;
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java
index 491aae3..8669fc8 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java
@@ -2,16 +2,21 @@ package ca.uhn.fhir.jpa.starter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
+
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
-@WebServlet(urlPatterns = {"/fhir/*"})
+@WebServlet(urlPatterns = {"/hapi-fhir-jpaserver/fhir/*"})
@Import(AppProperties.class)
public class JpaRestfulServer extends BaseJpaRestfulServer {
+ @Autowired
+ AppProperties appProperties;
+
private static final long serialVersionUID = 1L;
- public JpaRestfulServer(AppProperties appProperties) {
- super(appProperties);
+ public JpaRestfulServer() {
+ super();
}
@Override
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index 13ec39d..f43409e 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -1,6 +1,6 @@
spring:
datasource:
- url: 'jdbc:h2:file:./target/database/h2dflkjglkj'
+ url: 'jdbc:h2:file:./target/database/h2'
username: sa
password: null
driverClassName: org.h2.Driver
@@ -10,42 +10,57 @@ spring:
active: r4
hapi:
fhir:
- allow_cascading_deletes: true
- allow_contains_searches: true
- allow_external_references: true
- allow_multiple_delete: true
- allow_override_default_search_params: true
- allow_placeholder_references: true
- auto_create_placeholder_reference_targets: false
- default_encoding: JSON
- default_page_size: 20
- enable_index_missing_fields: false
- enforce_referential_integrity_on_delete: false
- enforce_referential_integrity_on_write: false
- etag_support_enabled: true
- expunge_enabled: true
- daoconfig_client_id_strategy: null
- fhirpath_interceptor_enabled: false
- filter_search_enabled: true
- graphql_enabled: true
- logger:
- error_format: 'ERROR - ${requestVerb} ${requestUrl}'
- format: >-
- Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
- Operation[${operationType} ${operationName} ${idOrResourceName}]
- UA[${requestHeader.user-agent}] Params[${requestParameters}]
- ResponseEncoding[${responseEncodingNoDefault}]
- log_exceptions: true
- name: fhirtest.access
- max_binary_size: 104857600
- max_page_size: 200
- retain_cached_searches_mins: 60
- reuse_cached_search_results_millis: 60000
+ #supported_resource_types:
+ # - Patient
+ # - Observation
+# allow_cascading_deletes: true
+# allow_contains_searches: true
+# allow_external_references: true
+# allow_multiple_delete: true
+# allow_override_default_search_params: true
+# allow_placeholder_references: true
+# auto_create_placeholder_reference_targets: false
+# default_encoding: JSON
+# default_pretty_print: true
+# default_page_size: 20
+# enable_index_missing_fields: false
+# enforce_referential_integrity_on_delete: false
+# enforce_referential_integrity_on_write: false
+# etag_support_enabled: true
+# expunge_enabled: true
+# daoconfig_client_id_strategy: null
+# fhirpath_interceptor_enabled: false
+# filter_search_enabled: true
+# graphql_enabled: true
+ #partitioning:
+ # cross_partition_reference_mode: true
+ # multitenancy_enabled: true
+ # partitioning_include_in_search_hashes: true
+ #cors:
+ # allow_Credentials: true
+ # Supports multiple, comma separated allowed origin entries
+ # cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca
+ # allowed_origin:
+ # - '*'
+
+# logger:
+# error_format: 'ERROR - ${requestVerb} ${requestUrl}'
+# format: >-
+# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
+# Operation[${operationType} ${operationName} ${idOrResourceName}]
+# UA[${requestHeader.user-agent}] Params[${requestParameters}]
+# ResponseEncoding[${responseEncodingNoDefault}]
+# log_exceptions: true
+# name: fhirtest.access
+# max_binary_size: 104857600
+# max_page_size: 200
+# retain_cached_searches_mins: 60
+# reuse_cached_search_results_millis: 60000
tester:
-
id: home
name: Local Tester
- server_address: 'http://localhost:8080/fhir'
+ server_address: 'http://localhost:8080/hapi-fhir-jpaserver/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
-
@@ -54,23 +69,35 @@ hapi:
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
- bulk_export_enabled: true
- partitioning_multitenancy_enabled:
- subscription:
- email_enabled: false
- resthook_enabled: false
- websocket_enabled: false
-elasticsearch:
- debug:
- pretty_print_json_log: false
- refresh_after_write: false
- enabled: false
- password: SomePassword
- required_index_status: YELLOW
- rest_url: 'http://localhost:9200'
- schema_management_strategy: CREATE
- username: SomeUsername
+# validation:
+# requests_enabled: true
+# responses_enabled: true
+# binary_storage_enabled: true
+# bulk_export_enabled: true
+# partitioning_multitenancy_enabled:
+# subscription:
+# resthook_enabled: false
+# websocket_enabled: false
+# email:
+# from: some@test.com
+# host: google.com
+# port:
+# username:
+# password:
+# auth:
+# startTlsEnable:
+# startTlsRequired:
+# quitWait:
+
+
+#
+#elasticsearch:
+# debug:
+# pretty_print_json_log: false
+# refresh_after_write: false
+# enabled: false
+# password: SomePassword
+# required_index_status: YELLOW
+# rest_url: 'http://localhost:9200'
+# schema_management_strategy: CREATE
+# username: SomeUsername
diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java
index b34e67d..26a0385 100644
--- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java
+++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java
@@ -26,10 +26,10 @@ public class ExampleServerDstu2IT {
private static Server ourServer;
static {
- HapiProperties.forceReload();
- HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "DSTU2");
- HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr2");
ourCtx = FhirContext.forDstu2();
+ System.setProperty("spring.profiles.active", "dstu2");
+ System.setProperty("spring.batch.job.enabled", "false");
+ System.setProperty("spring.datasource.url", "jdbc:h2:mem:dbr2");
}
@Test
@@ -60,7 +60,8 @@ public class ExampleServerDstu2IT {
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/hapi-fhir-jpaserver");
- webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml");
+
+
webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter");
webAppContext.setParentLoaderPriority(true);