From 63606607b0d5d2d440070029a688dfe32f8db8a2 Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 17 Aug 2020 13:04:00 +0200 Subject: [PATCH 01/22] Added spring boot example application that can be used during test efforts Added use of spring profiles --- pom.xml | 41 +++++++++++++++++++ .../fhir/jpa/starter/ApplicationContext.java | 4 ++ .../jpa/starter/BaseJpaRestfulServer.java | 20 ++------- .../ca/uhn/fhir/jpa/starter/EmpiConfig.java | 2 + .../jpa/starter/FhirServerConfigDstu2.java | 2 + .../jpa/starter/FhirServerConfigDstu3.java | 2 + .../fhir/jpa/starter/FhirServerConfigR4.java | 2 + .../fhir/jpa/starter/FhirServerConfigR5.java | 2 + .../fhir/jpa/starter/JpaRestfulServer.java | 2 + src/main/resources/logback.xml | 18 -------- .../ca/uhn/fhir/jpa/starter/Application.java | 17 ++++++++ 11 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/Application.java diff --git a/pom.xml b/pom.xml index 6f5a2a1..f05e918 100644 --- a/pom.xml +++ b/pom.xml @@ -275,6 +275,47 @@ test + + org.springframework.boot + spring-boot-starter + 2.3.3.RELEASE + test + + + + org.springframework.boot + spring-boot-starter-web + 2.3.3.RELEASE + test + + + + + org.springframework.boot + spring-boot-starter-tomcat + 2.3.3.RELEASE + test + + + + org.springframework.boot + spring-boot-autoconfigure + 2.3.3.RELEASE + test + + + + + + + + org.springframework.boot + spring-boot-starter-logging + 2.3.3.RELEASE + test + + + junit diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java index c4d2919..5204c14 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java @@ -11,8 +11,12 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon public class ApplicationContext extends AnnotationConfigWebApplicationContext { + public ApplicationContext() { FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion(); + this.getEnvironment().setActiveProfiles(fhirVersion.toString().toLowerCase()); + + if (fhirVersion == FhirVersionEnum.DSTU2) { register(FhirServerConfigDstu2.class, FhirServerConfigCommon.class); } else if (fhirVersion == FhirVersionEnum.DSTU3) { 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 5b482c8..08be966 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,11 +11,7 @@ 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.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; @@ -29,12 +25,7 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; 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; @@ -48,11 +39,8 @@ import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; import javax.servlet.ServletException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; + public class BaseJpaRestfulServer extends RestfulServer { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java index 107aa97..f5d016b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java @@ -12,12 +12,14 @@ import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import java.io.IOException; @Configuration +@Profile("empi") public class EmpiConfig { @Bean diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index d80e70f..562e2bd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -14,6 +15,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration +@Profile("dstu2") public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 2a93154..df0eb6d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -14,6 +15,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration +@Profile("dstu3") public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index 5f3f8a9..d0ac06f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -14,6 +15,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration +@Profile("r4") public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index d6cf537..c73f51f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -14,6 +15,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @Configuration +@Profile("r5") public class FhirServerConfigR5 extends BaseJavaConfigR5 { @Autowired 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 f13ab64..cc1a0b9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java @@ -1,7 +1,9 @@ package ca.uhn.fhir.jpa.starter; import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +@WebServlet public class JpaRestfulServer extends BaseJpaRestfulServer { private static final long serialVersionUID = 1L; diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 9364495..8039731 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -9,24 +9,6 @@ - - DEBUG - ${smile.basedir}/log/empi-troubleshooting.log - - ${smile.basedir}/log/empi-troubleshooting.log.%i.gz - 1 - 9 - - - 5MB - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n${log.stackfilter.pattern} - - - - - diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/Application.java b/src/test/java/ca/uhn/fhir/jpa/starter/Application.java new file mode 100644 index 0000000..f1e3590 --- /dev/null +++ b/src/test/java/ca/uhn/fhir/jpa/starter/Application.java @@ -0,0 +1,17 @@ +package ca.uhn.fhir.jpa.starter; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; + +@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + + System.setProperty("spring.profiles.active", "r4"); + System.setProperty("elasticsearch.enabled", "false "); + SpringApplication.run(Application.class, args); + } +} From 53415f1c54766ed3e6ede22bb39e0e79309e30fe Mon Sep 17 00:00:00 2001 From: jvi Date: Wed, 19 Aug 2020 21:42:55 +0200 Subject: [PATCH 02/22] Adjusted imports and comments --- .../java/ca/uhn/fhir/jpa/starter/ApplicationContext.java | 3 +++ src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java | 5 ----- .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 7 +++++-- src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java | 8 +------- src/test/java/ca/uhn/fhir/jpa/starter/Application.java | 7 +++++-- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java index 5204c14..c0a2d3c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java @@ -9,6 +9,9 @@ import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +/** + * The class is unused for Spring Boot + */ public class ApplicationContext extends AnnotationConfigWebApplicationContext { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java index f5d016b..080261f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EmpiConfig.java @@ -1,15 +1,10 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.context.FhirContext; 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.empi.svc.EmpiSearchParamSvc; -import ca.uhn.fhir.jpa.subscription.channel.subscription.IChannelNamer; -import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; 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 123b7a0..4193ed2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender; import org.apache.commons.dbcp2.BasicDataSource; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; @@ -51,8 +52,10 @@ public class FhirServerConfigCommon { private Boolean emailStartTlsEnable = HapiProperties.getEmailStartTlsEnable(); private Boolean emailStartTlsRequired = HapiProperties.getEmailStartTlsRequired(); private Boolean emailQuitWait = HapiProperties.getEmailQuitWait(); + + @Autowired - private ApplicationContext myAppCtx; + private ApplicationContext appContext; public FhirServerConfigCommon() { ourLog.info("Server configured to " + (this.allowContainsSearches ? "allow" : "deny") + " contains searches"); @@ -209,7 +212,7 @@ public class FhirServerConfigCommon { retVal.setStartTlsRequired(this.emailStartTlsRequired); retVal.setQuitWait(this.emailQuitWait); - SubscriptionDeliveryHandlerFactory subscriptionDeliveryHandlerFactory = myAppCtx.getBean(SubscriptionDeliveryHandlerFactory.class); + SubscriptionDeliveryHandlerFactory subscriptionDeliveryHandlerFactory = appContext.getBean(SubscriptionDeliveryHandlerFactory.class); Validate.notNull(subscriptionDeliveryHandlerFactory, "No subscription delivery handler"); subscriptionDeliveryHandlerFactory.setEmailSender(retVal); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java index 20628e5..844fcbd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java @@ -15,16 +15,10 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import java.io.FileInputStream; import java.io.InputStream; -import java.util.Arrays; -import java.util.Locale; -import java.util.Properties; -import java.util.Set; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import static org.apache.commons.lang3.StringUtils.defaultString; -import static org.apache.commons.lang3.StringUtils.isNotBlank; -import static org.apache.commons.lang3.StringUtils.trim; public class HapiProperties { static final String ENABLE_INDEX_MISSING_FIELDS = "enable_index_missing_fields"; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/Application.java b/src/test/java/ca/uhn/fhir/jpa/starter/Application.java index f1e3590..d771840 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/Application.java @@ -2,16 +2,19 @@ package ca.uhn.fhir.jpa.starter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; import org.springframework.boot.web.servlet.ServletComponentScan; @ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) -@SpringBootApplication +@SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) public class Application { public static void main(String[] args) { System.setProperty("spring.profiles.active", "r4"); - System.setProperty("elasticsearch.enabled", "false "); + System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); + + //Server is now accessible at eg. http://localhost:8080/metadata } } From 5f237256cabbd1d3dc5f7708b9e2c6e7eefb9d31 Mon Sep 17 00:00:00 2001 From: jkv Date: Fri, 4 Sep 2020 23:23:04 +0200 Subject: [PATCH 03/22] Added boot application --- pom.xml | 35 ++++++++-------- .../ca/uhn/fhir/jpa/starter/Application.java | 42 +++++++++++++++++++ .../fhir/jpa/starter/JpaRestfulServer.java | 2 +- src/main/resources/hapi.properties | 2 +- 4 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/Application.java diff --git a/pom.xml b/pom.xml index f05e918..69dbab6 100644 --- a/pom.xml +++ b/pom.xml @@ -2,6 +2,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + org.springframework.boot spring-boot-starter-tomcat 2.3.3.RELEASE - test + org.springframework.boot spring-boot-autoconfigure 2.3.3.RELEASE - test + @@ -332,6 +319,20 @@ hapi-fhir-jpaserver + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + ca.uhn.fhir.jpa.starter.Application + + + + org.eclipse.jetty diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java new file mode 100644 index 0000000..21ce953 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -0,0 +1,42 @@ +package ca.uhn.fhir.jpa.starter; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) +@SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) +public class Application { + + public static void main(String[] args) { + + System.setProperty("spring.profiles.active", "r4"); + System.setProperty("spring.batch.job.enabled", "false"); + SpringApplication.run(Application.class, args); + + //Server is now accessible at eg. http://localhost:8080/fhir/metadata + } + + @Bean + public ServletRegistrationBean servletRegistrationBean() { + + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + + ctx.register(FhirTesterConfig.class); + + DispatcherServlet api = new DispatcherServlet(ctx); + api.setContextClass(AnnotationConfigWebApplicationContext.class); + api.setContextConfigLocation(FhirTesterConfig.class.getName()); + ServletRegistrationBean registrationBean = new ServletRegistrationBean(); + registrationBean.setServlet(api); + registrationBean.addUrlMappings("/*"); + registrationBean.setLoadOnStartup(1); + return registrationBean; + + } +} 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 cc1a0b9..d9f6369 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java @@ -3,7 +3,7 @@ package ca.uhn.fhir.jpa.starter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; -@WebServlet +@WebServlet(urlPatterns = {"/fhir/*"}) public class JpaRestfulServer extends BaseJpaRestfulServer { private static final long serialVersionUID = 1L; diff --git a/src/main/resources/hapi.properties b/src/main/resources/hapi.properties index b7ef0f8..22a7b2f 100644 --- a/src/main/resources/hapi.properties +++ b/src/main/resources/hapi.properties @@ -11,7 +11,7 @@ fhir_version=R4 # (the web UI similar to the one at http://hapi.fhir.org) will use to # connect internally to the FHIR server, so this also needs to be a name # accessible from the server itself. -server_address=http://localhost:8080/hapi-fhir-jpaserver/fhir/ +server_address=http://localhost:8080/fhir enable_index_missing_fields=false auto_create_placeholder_reference_targets=false From 5981456e54c58f9a94fa373e17d8a5fc2e636b37 Mon Sep 17 00:00:00 2001 From: jkv Date: Sat, 5 Sep 2020 21:28:25 +0200 Subject: [PATCH 04/22] Got examples .... sort of --- .../uhn/fhir/jpa/starter/AppProperties.java | 379 ++++++++++++++++++ .../ca/uhn/fhir/jpa/starter/Application.java | 6 +- .../jpa/starter/BaseJpaRestfulServer.java | 55 ++- .../fhir/jpa/starter/JpaRestfulServer.java | 6 + src/main/resources/application.yaml | 62 +++ 5 files changed, 493 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java create mode 100644 src/main/resources/application.yaml diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java new file mode 100644 index 0000000..570ed95 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -0,0 +1,379 @@ +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 org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + + +@ConfigurationProperties(prefix = "hapi.fhir") +@Configuration +@EnableConfigurationProperties +public class AppProperties { + + + private Boolean allow_cascading_deletes = false; + private Boolean allow_contains_searches = true; + private Boolean allow_external_references = false; + private Boolean allow_multiple_delete = false; + 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; + private Boolean etag_support_enabled = true; + private Boolean expunge_enabled = true; + private Boolean fhirpath_interceptor_enabled = false; + private Boolean filter_search_enabled = true; + private Boolean graphql_enabled = true; + private Boolean binary_storage_enabled = true; + private Boolean bulk_export_enabled = true; + private EncodingEnum default_encoding = EncodingEnum.JSON; + private FhirVersionEnum fhir_version = FhirVersionEnum.R4; + private Integer max_binary_size = 104857600; + private Integer max_page_size = 200; + private Integer retain_cached_searches_mins = 60; + private Integer reuse_cached_search_results_millis = 60000; + private ClientIdStrategyEnum client_id_strategy = ClientIdStrategyEnum.ALPHANUMERIC; + + + private Validation validation; + private Server server; + private Logger logger; + + public Validation getValidation() { + return validation; + } + + public void setValidation(Validation validation) { + this.validation = validation; + } + + public Server getServer() { + return server; + } + + public void setServer(Server server) { + this.server = server; + } + + public Logger getLogger() { + return logger; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } + + public ClientIdStrategyEnum getClient_id_strategy() { + return client_id_strategy; + } + + public void setClient_id_strategy( + ClientIdStrategyEnum client_id_strategy) { + this.client_id_strategy = client_id_strategy; + } + + public Boolean getAllow_cascading_deletes() { + return allow_cascading_deletes; + } + + public void setAllow_cascading_deletes(Boolean allow_cascading_deletes) { + this.allow_cascading_deletes = allow_cascading_deletes; + } + + public Boolean getAllow_contains_searches() { + return allow_contains_searches; + } + + public void setAllow_contains_searches(Boolean allow_contains_searches) { + this.allow_contains_searches = allow_contains_searches; + } + + public Boolean getAllow_external_references() { + return allow_external_references; + } + + public void setAllow_external_references(Boolean allow_external_references) { + this.allow_external_references = allow_external_references; + } + + public Boolean getAllow_multiple_delete() { + return allow_multiple_delete; + } + + public void setAllow_multiple_delete(Boolean allow_multiple_delete) { + this.allow_multiple_delete = allow_multiple_delete; + } + + public Boolean getAllow_override_default_search_params() { + return allow_override_default_search_params; + } + + public void setAllow_override_default_search_params( + Boolean allow_override_default_search_params) { + this.allow_override_default_search_params = allow_override_default_search_params; + } + + public Boolean getAllow_placeholder_references() { + return allow_placeholder_references; + } + + public void setAllow_placeholder_references(Boolean allow_placeholder_references) { + this.allow_placeholder_references = allow_placeholder_references; + } + + public Boolean getAuto_create_placeholder_reference_targets() { + return auto_create_placeholder_reference_targets; + } + + public void setAuto_create_placeholder_reference_targets( + Boolean auto_create_placeholder_reference_targets) { + this.auto_create_placeholder_reference_targets = auto_create_placeholder_reference_targets; + } + + public Integer getDefault_page_size() { + return default_page_size; + } + + public void setDefault_page_size(Integer default_page_size) { + this.default_page_size = default_page_size; + } + + public Boolean getEnable_index_missing_fields() { + return enable_index_missing_fields; + } + + public void setEnable_index_missing_fields(Boolean enable_index_missing_fields) { + this.enable_index_missing_fields = enable_index_missing_fields; + } + + public Boolean getEnforce_referential_integrity_on_delete() { + return enforce_referential_integrity_on_delete; + } + + public void setEnforce_referential_integrity_on_delete( + Boolean enforce_referential_integrity_on_delete) { + this.enforce_referential_integrity_on_delete = enforce_referential_integrity_on_delete; + } + + public Boolean getEnforce_referential_integrity_on_write() { + return enforce_referential_integrity_on_write; + } + + public void setEnforce_referential_integrity_on_write( + Boolean enforce_referential_integrity_on_write) { + this.enforce_referential_integrity_on_write = enforce_referential_integrity_on_write; + } + + public Boolean getEtag_support_enabled() { + return etag_support_enabled; + } + + public void setEtag_support_enabled(Boolean etag_support_enabled) { + this.etag_support_enabled = etag_support_enabled; + } + + public Boolean getExpunge_enabled() { + return expunge_enabled; + } + + public void setExpunge_enabled(Boolean expunge_enabled) { + this.expunge_enabled = expunge_enabled; + } + + public Boolean getFhirpath_interceptor_enabled() { + return fhirpath_interceptor_enabled; + } + + public void setFhirpath_interceptor_enabled(Boolean fhirpath_interceptor_enabled) { + this.fhirpath_interceptor_enabled = fhirpath_interceptor_enabled; + } + + public Boolean getFilter_search_enabled() { + return filter_search_enabled; + } + + public void setFilter_search_enabled(Boolean filter_search_enabled) { + this.filter_search_enabled = filter_search_enabled; + } + + public Boolean getGraphql_enabled() { + return graphql_enabled; + } + + public void setGraphql_enabled(Boolean graphql_enabled) { + this.graphql_enabled = graphql_enabled; + } + + public Boolean getBinary_storage_enabled() { + return binary_storage_enabled; + } + + public void setBinary_storage_enabled(Boolean binary_storage_enabled) { + this.binary_storage_enabled = binary_storage_enabled; + } + + public Boolean getBulk_export_enabled() { + return bulk_export_enabled; + } + + public void setBulk_export_enabled(Boolean bulk_export_enabled) { + this.bulk_export_enabled = bulk_export_enabled; + } + + public EncodingEnum getDefault_encoding() { + return default_encoding; + } + + public void setDefault_encoding(EncodingEnum default_encoding) { + this.default_encoding = default_encoding; + } + + public FhirVersionEnum getFhir_version() { + return fhir_version; + } + + public void setFhir_version(FhirVersionEnum fhir_version) { + this.fhir_version = fhir_version; + } + + public Integer getMax_binary_size() { + return max_binary_size; + } + + public void setMax_binary_size(Integer max_binary_size) { + this.max_binary_size = max_binary_size; + } + + public Integer getMax_page_size() { + return max_page_size; + } + + public void setMax_page_size(Integer max_page_size) { + this.max_page_size = max_page_size; + } + + public Integer getRetain_cached_searches_mins() { + return retain_cached_searches_mins; + } + + public void setRetain_cached_searches_mins(Integer retain_cached_searches_mins) { + this.retain_cached_searches_mins = retain_cached_searches_mins; + } + + public Integer getReuse_cached_search_results_millis() { + return reuse_cached_search_results_millis; + } + + public void setReuse_cached_search_results_millis(Integer reuse_cached_search_results_millis) { + this.reuse_cached_search_results_millis = reuse_cached_search_results_millis; + } + + public static class Logger { + + private String name = "fhirtest.access"; + private String error_format = "ERROR - ${requestVerb} ${requestUrl}"; + private String format = "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"; + private Boolean log_exceptions = true; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getError_format() { + return error_format; + } + + public void setError_format(String error_format) { + this.error_format = error_format; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public Boolean getLog_exceptions() { + return log_exceptions; + } + + public void setLog_exceptions(Boolean log_exceptions) { + this.log_exceptions = log_exceptions; + } + } + + + public static class Server { + + private String id = "home"; + private String name = "Local Tester"; + private String address = "http://localhost:8080/fhir"; + private Boolean refuse_to_fetch_third_party_urls = true; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Boolean getRefuse_to_fetch_third_party_urls() { + return refuse_to_fetch_third_party_urls; + } + + public void setRefuse_to_fetch_third_party_urls(Boolean refuse_to_fetch_third_party_urls) { + this.refuse_to_fetch_third_party_urls = refuse_to_fetch_third_party_urls; + } + } + + public static class Validation { + + private Boolean requests_enabled = false; + private Boolean responses_enabled = false; + + public Boolean getRequests_enabled() { + return requests_enabled; + } + + public void setRequests_enabled(Boolean requests_enabled) { + this.requests_enabled = requests_enabled; + } + + public Boolean getResponses_enabled() { + return responses_enabled; + } + + public void setResponses_enabled(Boolean responses_enabled) { + this.responses_enabled = responses_enabled; + } + } +} 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 19b9418..36897d8 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,16 +1,20 @@ package ca.uhn.fhir.jpa.starter; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) +@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) +@EnableConfigurationProperties +@EnableAutoConfiguration public class Application { public static void main(String[] args) { 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 08be966..686bf45 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,7 +11,11 @@ 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.*; +import ca.uhn.fhir.jpa.provider.GraphQLProvider; +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.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; @@ -25,12 +29,23 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; import ca.uhn.fhir.rest.server.RestfulServer; -import ca.uhn.fhir.rest.server.interceptor.*; +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.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 org.hl7.fhir.r4.model.Bundle.BundleType; @@ -38,12 +53,15 @@ import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; -import javax.servlet.ServletException; -import java.util.*; - public class BaseJpaRestfulServer extends RestfulServer { + AppProperties hapiProperties; + + public BaseJpaRestfulServer(AppProperties appProperties) { + this.hapiProperties = appProperties; + } + private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @@ -107,24 +125,32 @@ public class BaseJpaRestfulServer extends RestfulServer { DaoConfig daoConfig = appCtx.getBean(DaoConfig.class); ISearchParamRegistry searchParamRegistry = appCtx.getBean(ISearchParamRegistry.class); if (fhirVersion == FhirVersionEnum.DSTU2) { - IFhirSystemDao systemDao = appCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, daoConfig); + IFhirSystemDao systemDao = appCtx + .getBean("mySystemDaoDstu2", IFhirSystemDao.class); + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, + daoConfig); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); setServerConformanceProvider(confProvider); } else { if (fhirVersion == FhirVersionEnum.DSTU3) { - IFhirSystemDao systemDao = appCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, daoConfig, searchParamRegistry); + IFhirSystemDao systemDao = appCtx + .getBean("mySystemDaoDstu3", IFhirSystemDao.class); + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, + daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R4) { - IFhirSystemDao systemDao = appCtx.getBean("mySystemDaoR4", IFhirSystemDao.class); - JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, daoConfig, searchParamRegistry); + IFhirSystemDao systemDao = appCtx + .getBean("mySystemDaoR4", IFhirSystemDao.class); + JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, + daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R4 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R5) { - IFhirSystemDao systemDao = appCtx.getBean("mySystemDaoR5", IFhirSystemDao.class); - JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, daoConfig, searchParamRegistry); + IFhirSystemDao systemDao = appCtx + .getBean("mySystemDaoR5", IFhirSystemDao.class); + JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, + daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R5 Server"); setServerConformanceProvider(confProvider); } else { @@ -257,7 +283,8 @@ public class BaseJpaRestfulServer extends RestfulServer { DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class); IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class); if (HapiProperties.getAllowCascadingDeletes()) { - CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(ctx, daoRegistry, interceptorBroadcaster); + CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(ctx, + daoRegistry, interceptorBroadcaster); getInterceptorService().registerInterceptor(cascadingDeleteInterceptor); } 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 d9f6369..491aae3 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java @@ -2,12 +2,18 @@ package ca.uhn.fhir.jpa.starter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; +import org.springframework.context.annotation.Import; @WebServlet(urlPatterns = {"/fhir/*"}) +@Import(AppProperties.class) public class JpaRestfulServer extends BaseJpaRestfulServer { private static final long serialVersionUID = 1L; + public JpaRestfulServer(AppProperties appProperties) { + super(appProperties); + } + @Override protected void initialize() throws ServletException { super.initialize(); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..482571a --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,62 @@ +spring: + datasource: + url: 'jdbc:h2:file:./target/database/h2' + username: sa + password: + driverClassName: org.h2.Driver + max-active: 15 +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 + fhir_version: DSTU3 + daoconfig_client_id_strategy: + 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 + server: + id: home + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + validation: + requests_enabled: false + responses_enabled: false + + binary_storage_enabled: true + bulk_export_enabled: true +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 \ No newline at end of file From d5c6abece972747208f02e65a77707c17487ac96 Mon Sep 17 00:00:00 2001 From: jkv Date: Sun, 6 Sep 2020 07:29:32 +0200 Subject: [PATCH 05/22] Further adaption of new config class --- .../uhn/fhir/jpa/starter/AppProperties.java | 29 +++++------ .../ca/uhn/fhir/jpa/starter/Application.java | 3 -- .../jpa/starter/FhirServerConfigCommon.java | 51 ++++++++++--------- .../fhir/jpa/starter/FhirServerConfigR4.java | 2 + .../fhir/jpa/starter/FhirTesterConfig.java | 19 ++++--- src/main/resources/application.yaml | 8 +-- 6 files changed, 55 insertions(+), 57 deletions(-) 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 570ed95..092cd37 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -32,18 +32,17 @@ 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 Integer max_page_size = Integer.MAX_VALUE; + private Integer retain_cached_searches_mins = 60; + private Long reuse_cached_search_results_millis = 60000L; private EncodingEnum default_encoding = EncodingEnum.JSON; private FhirVersionEnum fhir_version = FhirVersionEnum.R4; - private Integer max_binary_size = 104857600; - private Integer max_page_size = 200; - private Integer retain_cached_searches_mins = 60; - private Integer reuse_cached_search_results_millis = 60000; private ClientIdStrategyEnum client_id_strategy = ClientIdStrategyEnum.ALPHANUMERIC; - - private Validation validation; - private Server server; - private Logger logger; + private Validation validation = new Validation(); + private Tester tester = new Tester(); + private Logger logger = new Logger(); public Validation getValidation() { return validation; @@ -53,12 +52,12 @@ public class AppProperties { this.validation = validation; } - public Server getServer() { - return server; + public Tester getTester() { + return tester; } - public void setServer(Server server) { - this.server = server; + public void setTester(Tester tester) { + this.tester = tester; } public Logger getLogger() { @@ -266,11 +265,11 @@ public class AppProperties { this.retain_cached_searches_mins = retain_cached_searches_mins; } - public Integer getReuse_cached_search_results_millis() { + public Long getReuse_cached_search_results_millis() { return reuse_cached_search_results_millis; } - public void setReuse_cached_search_results_millis(Integer reuse_cached_search_results_millis) { + public void setReuse_cached_search_results_millis(Long reuse_cached_search_results_millis) { this.reuse_cached_search_results_millis = reuse_cached_search_results_millis; } @@ -315,7 +314,7 @@ public class AppProperties { } - public static class Server { + public static class Tester { private String id = "home"; private String name = "Local Tester"; 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 36897d8..5b89775 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,7 +1,6 @@ package ca.uhn.fhir.jpa.starter; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -13,8 +12,6 @@ import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) -@EnableConfigurationProperties -@EnableAutoConfiguration public class Application { public static void main(String[] args) { 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 4193ed2..4768e17 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -30,6 +30,7 @@ public class FhirServerConfigCommon { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); + private Boolean enableIndexMissingFields = HapiProperties.getEnableIndexMissingFields(); private Boolean autoCreatePlaceholderReferenceTargets = HapiProperties.getAutoCreatePlaceholderReferenceTargets(); private Boolean enforceReferentialIntegrityOnWrite = HapiProperties.getEnforceReferentialIntegrityOnWrite(); @@ -57,13 +58,13 @@ public class FhirServerConfigCommon { @Autowired private ApplicationContext appContext; - public FhirServerConfigCommon() { - ourLog.info("Server configured to " + (this.allowContainsSearches ? "allow" : "deny") + " contains searches"); - ourLog.info("Server configured to " + (this.allowMultipleDelete ? "allow" : "deny") + " multiple deletes"); - ourLog.info("Server configured to " + (this.allowExternalReferences ? "allow" : "deny") + " external references"); - ourLog.info("Server configured to " + (this.expungeEnabled ? "enable" : "disable") + " expunges"); - ourLog.info("Server configured to " + (this.allowPlaceholderReferences ? "allow" : "deny") + " placeholder references"); - ourLog.info("Server configured to " + (this.allowOverrideDefaultSearchParams ? "allow" : "deny") + " overriding default search params"); + public FhirServerConfigCommon(AppProperties appProperties) { + ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches"); + ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny") + " multiple deletes"); + ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny") + " external references"); + ourLog.info("Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges"); + 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()); @@ -91,25 +92,25 @@ public class FhirServerConfigCommon { * Configure FHIR properties around the the JPA server via this bean */ @Bean() - public DaoConfig daoConfig() { + public DaoConfig daoConfig(AppProperties appProperties) { DaoConfig retVal = new DaoConfig(); - retVal.setIndexMissingFields(this.enableIndexMissingFields ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED); - retVal.setAutoCreatePlaceholderReferenceTargets(this.autoCreatePlaceholderReferenceTargets); - retVal.setEnforceReferentialIntegrityOnWrite(this.enforceReferentialIntegrityOnWrite); - retVal.setEnforceReferentialIntegrityOnDelete(this.enforceReferentialIntegrityOnDelete); - retVal.setAllowContainsSearches(this.allowContainsSearches); - retVal.setAllowMultipleDelete(this.allowMultipleDelete); - retVal.setAllowExternalReferences(this.allowExternalReferences); - retVal.setExpungeEnabled(this.expungeEnabled); - retVal.setAutoCreatePlaceholderReferenceTargets(this.allowPlaceholderReferences); + retVal.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED); + retVal.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); + retVal.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); + retVal.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); + retVal.setAllowContainsSearches(appProperties.getAllow_contains_searches()); + retVal.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); + retVal.setAllowExternalReferences(appProperties.getAllow_external_references()); + retVal.setExpungeEnabled(appProperties.getExpunge_enabled()); + retVal.setAutoCreatePlaceholderReferenceTargets(appProperties.getAllow_placeholder_references()); retVal.setEmailFromAddress(this.emailFrom); - Integer maxFetchSize = HapiProperties.getMaximumFetchSize(); + Integer maxFetchSize = appProperties.getMax_page_size(); retVal.setFetchSizeDefaultMaximum(maxFetchSize); ourLog.info("Server configured to have a maximum fetch size of " + (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize)); - Long reuseCachedSearchResultsMillis = HapiProperties.getReuseCachedSearchResultsMillis(); + Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis(); retVal.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis); ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis); @@ -149,11 +150,11 @@ public class FhirServerConfigCommon { @Bean - public ModelConfig modelConfig() { + public ModelConfig modelConfig(AppProperties appProperties) { ModelConfig modelConfig = new ModelConfig(); - modelConfig.setAllowContainsSearches(this.allowContainsSearches); - modelConfig.setAllowExternalReferences(this.allowExternalReferences); - modelConfig.setDefaultSearchParamsCanBeOverridden(this.allowOverrideDefaultSearchParams); + modelConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches()); + modelConfig.setAllowExternalReferences(appProperties.getAllow_external_references()); + modelConfig.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params()); modelConfig.setEmailFromAddress(this.emailFrom); // You can enable these if you want to support Subscriptions from your server @@ -174,7 +175,7 @@ public class FhirServerConfigCommon { *

* A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. */ - @Bean(destroyMethod = "close") + /*@Bean(destroyMethod = "close") public BasicDataSource dataSource() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { BasicDataSource retVal = new BasicDataSource(); Driver driver = (Driver) Class.forName(HapiProperties.getDataSourceDriver()).getConstructor().newInstance(); @@ -184,7 +185,7 @@ public class FhirServerConfigCommon { retVal.setPassword(HapiProperties.getDataSourcePassword()); retVal.setMaxTotal(HapiProperties.getDataSourceMaxPoolSize()); return retVal; - } + }*/ @Lazy @Bean diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index d0ac06f..587f313 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -16,6 +17,7 @@ import javax.sql.DataSource; @Configuration @Profile("r4") +@ConditionalOnClass(DataSource.class) public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java index 11ccbcb..dbcca69 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java @@ -1,11 +1,10 @@ package ca.uhn.fhir.jpa.starter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - import ca.uhn.fhir.to.FhirTesterMvcConfig; import ca.uhn.fhir.to.TesterConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; //@formatter:off /** @@ -35,15 +34,15 @@ public class FhirTesterConfig { * you might want to use that instead of using the variable. */ @Bean - public TesterConfig testerConfig() { + public TesterConfig testerConfig(AppProperties appProperties) { TesterConfig retVal = new TesterConfig(); retVal .addServer() - .withId(HapiProperties.getServerId()) - .withFhirVersion(HapiProperties.getFhirVersion()) - .withBaseUrl(HapiProperties.getServerAddress()) - .withName(HapiProperties.getServerName()); - retVal.setRefuseToFetchThirdPartyUrls(HapiProperties.getTesterConfigRefustToFetchThirdPartyUrls()); + .withId(appProperties.getTester().getId()) + .withFhirVersion(appProperties.getFhir_version()) + .withBaseUrl(appProperties.getTester().getAddress()) + .withName(appProperties.getTester().getName()); + retVal.setRefuseToFetchThirdPartyUrls(appProperties.getTester().getRefuse_to_fetch_third_party_urls()); return retVal; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 482571a..4c0c72c 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/h2' + url: 'jdbc:h2:file:./target/database/h2dflkjglkj' username: sa password: driverClassName: org.h2.Driver @@ -39,14 +39,14 @@ hapi: max_page_size: 200 retain_cached_searches_mins: 60 reuse_cached_search_results_millis: 60000 - server: + tester: id: home name: Local Tester server_address: 'http://localhost:8080/fhir' refuse_to_fetch_third_party_urls: false validation: - requests_enabled: false - responses_enabled: false + requests_enabled: true + responses_enabled: true binary_storage_enabled: true bulk_export_enabled: true From 8bf930b3c3e6f97c9aa1a8495f919c0854ae8a64 Mon Sep 17 00:00:00 2001 From: jkv Date: Mon, 7 Sep 2020 00:19:42 +0200 Subject: [PATCH 06/22] Moved more configuration values --- .vscode/settings.json | 8 ++ pom.xml | 6 +- .../uhn/fhir/jpa/starter/AppProperties.java | 79 +++++++++++++--- .../ca/uhn/fhir/jpa/starter/Application.java | 1 - .../fhir/jpa/starter/ApplicationContext.java | 56 ----------- .../jpa/starter/BaseJpaRestfulServer.java | 92 +++++++++++-------- .../jpa/starter/FhirServerConfigCommon.java | 22 ++--- .../fhir/jpa/starter/FhirServerConfigR4.java | 1 - .../fhir/jpa/starter/FhirTesterConfig.java | 28 +++--- src/main/resources/application.yaml | 32 +++++-- 10 files changed, 175 insertions(+), 150 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2421e38 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.exclude": { + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5adb46c..661ee01 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ hapi-fhir-jpaserver-starter - 3.5.0 + 3.6.0 war @@ -351,9 +351,9 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 - 1.8 - 1.8 + 11 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 092cd37..a3cd5d2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -1,8 +1,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.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -41,8 +44,17 @@ public class AppProperties { private ClientIdStrategyEnum client_id_strategy = ClientIdStrategyEnum.ALPHANUMERIC; private Validation validation = new Validation(); - private Tester tester = new Tester(); + private List tester = new ArrayList<>(); private Logger logger = new Logger(); + private Subscription subscription = new Subscription(); + + public Subscription getSubscription() { + return subscription; + } + + public void setSubscription(Subscription subscription) { + this.subscription = subscription; + } public Validation getValidation() { return validation; @@ -52,13 +64,6 @@ public class AppProperties { this.validation = validation; } - public Tester getTester() { - return tester; - } - - public void setTester(Tester tester) { - this.tester = tester; - } public Logger getLogger() { return logger; @@ -273,6 +278,14 @@ public class AppProperties { this.reuse_cached_search_results_millis = reuse_cached_search_results_millis; } + public List getTester() { + return tester; + } + + public void setTester(List tester) { + this.tester = tester; + } + public static class Logger { private String name = "fhirtest.access"; @@ -318,8 +331,17 @@ public class AppProperties { private String id = "home"; private String name = "Local Tester"; - private String address = "http://localhost:8080/fhir"; + private String server_address = "http://localhost:8080/fhir"; private Boolean refuse_to_fetch_third_party_urls = true; + private FhirVersionEnum fhir_version = FhirVersionEnum.R4; + + public FhirVersionEnum getFhir_version() { + return fhir_version; + } + + public void setFhir_version(FhirVersionEnum fhir_version) { + this.fhir_version = fhir_version; + } public String getId() { return id; @@ -337,12 +359,12 @@ public class AppProperties { this.name = name; } - public String getAddress() { - return address; + public String getServer_address() { + return server_address; } - public void setAddress(String address) { - this.address = address; + public void setServer_address(String server_address) { + this.server_address = server_address; } public Boolean getRefuse_to_fetch_third_party_urls() { @@ -375,4 +397,35 @@ public class AppProperties { this.responses_enabled = responses_enabled; } } + + 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; + } + + public void setResthook_enabled(Boolean resthook_enabled) { + this.resthook_enabled = resthook_enabled; + } + + public Boolean getWebsocket_enabled() { + return websocket_enabled; + } + + public void setWebsocket_enabled(Boolean websocket_enabled) { + this.websocket_enabled = websocket_enabled; + } + + private Boolean email_enabled = false; + private Boolean resthook_enabled = false; + private Boolean websocket_enabled = 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 5b89775..be03b5f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -16,7 +16,6 @@ public class Application { public static void main(String[] args) { - System.setProperty("spring.profiles.active", "r4"); System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java deleted file mode 100644 index a7bdc3e..0000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java +++ /dev/null @@ -1,56 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.jpa.empi.EmpiConfig; -import ca.uhn.fhir.jpa.empi.config.EmpiConsumerConfig; -import ca.uhn.fhir.jpa.empi.config.EmpiSubmitterConfig; -import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; -import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; -import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; -import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; - -/** - * The class is unused for Spring Boot - */ -public class ApplicationContext extends AnnotationConfigWebApplicationContext { - - - public ApplicationContext() { - FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion(); - this.getEnvironment().setActiveProfiles(fhirVersion.toString().toLowerCase()); - - - if (fhirVersion == FhirVersionEnum.DSTU2) { - register(FhirServerConfigDstu2.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.DSTU3) { - register(FhirServerConfigDstu3.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.R4) { - register(FhirServerConfigR4.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.R5) { - register(FhirServerConfigR5.class, FhirServerConfigCommon.class); - } else { - throw new IllegalStateException(); - } - - if (HapiProperties.getSubscriptionWebsocketEnabled()) { - register(WebsocketDispatcherConfig.class); - } - - if (HapiProperties.getSubscriptionEmailEnabled() - || HapiProperties.getSubscriptionRestHookEnabled() - || HapiProperties.getSubscriptionWebsocketEnabled()) { - register(SubscriptionSubmitterConfig.class); - register(SubscriptionProcessorConfig.class); - register(SubscriptionChannelConfig.class); - } - - if (HapiProperties.getEmpiEnabled()) { - register(EmpiSubmitterConfig.class); - register(EmpiConsumerConfig.class); - register(EmpiConfig.class); - } - - } - -} 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 686bf45..e359e3d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -4,6 +4,7 @@ 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,6 +13,7 @@ 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; @@ -49,6 +51,9 @@ import javax.servlet.ServletException; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Meta; 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; @@ -58,6 +63,24 @@ public class BaseJpaRestfulServer extends RestfulServer { AppProperties hapiProperties; + @Autowired + DaoRegistry daoRegistry; + + @Autowired + DaoConfig daoConfig; + + @Autowired + ISearchParamRegistry searchParamRegistry; + + @Autowired + IFhirSystemDao fhirSystemDao; + + @Autowired + ResourceProviderFactory resourceProviders; + + @Autowired + IJpaSystemProvider jpaSystemProvider; + public BaseJpaRestfulServer(AppProperties appProperties) { this.hapiProperties = appProperties; } @@ -69,12 +92,13 @@ 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. */ - ApplicationContext appCtx = (ApplicationContext) getServletContext() - .getAttribute("org.springframework.web.context.WebApplicationContext.ROOT"); // Customize supported resource types Set supportedResourceTypes = HapiProperties.getSupportedResourceTypes(); @@ -83,37 +107,16 @@ public class BaseJpaRestfulServer extends RestfulServer { } if (!supportedResourceTypes.isEmpty()) { - DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class); daoRegistry.setSupportedResourceTypes(supportedResourceTypes); } - /* - * ResourceProviders are fetched from the Spring context - */ - FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion(); - ResourceProviderFactory resourceProviders; - Object systemProvider; - if (fhirVersion == FhirVersionEnum.DSTU2) { - resourceProviders = appCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class); - } else if (fhirVersion == FhirVersionEnum.DSTU3) { - resourceProviders = appCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class); - } else if (fhirVersion == FhirVersionEnum.R4) { - resourceProviders = appCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class); - } else if (fhirVersion == FhirVersionEnum.R5) { - resourceProviders = appCtx.getBean("myResourceProvidersR5", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderR5", JpaSystemProviderR5.class); - } else { - throw new IllegalStateException(); - } - setFhirContext(appCtx.getBean(FhirContext.class)); + setFhirContext(fhirSystemDao.getContext()); registerProviders(resourceProviders.createProviders()); - registerProvider(systemProvider); + registerProvider(jpaSystemProvider); + FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); /* * The conformance provider exports the supported resources, search parameters, etc for * this server. The JPA version adds resourceProviders counts to the exported statement, so it @@ -122,34 +125,30 @@ public class BaseJpaRestfulServer extends RestfulServer { * You can also create your own subclass of the conformance provider if you need to * provide further customization of your server's CapabilityStatement */ - DaoConfig daoConfig = appCtx.getBean(DaoConfig.class); - ISearchParamRegistry searchParamRegistry = appCtx.getBean(ISearchParamRegistry.class); + + if (fhirVersion == FhirVersionEnum.DSTU2) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoDstu2", IFhirSystemDao.class); - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, + + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, fhirSystemDao, daoConfig); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); setServerConformanceProvider(confProvider); } else { if (fhirVersion == FhirVersionEnum.DSTU3) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoDstu3", IFhirSystemDao.class); - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, + + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R4) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoR4", IFhirSystemDao.class); - JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, + + JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R4 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R5) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoR5", IFhirSystemDao.class); - JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, + + JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R5 Server"); setServerConformanceProvider(confProvider); @@ -185,6 +184,7 @@ public class BaseJpaRestfulServer extends RestfulServer { * a performance hit when performing searches that return lots of results, * but makes the server much more scalable. */ + setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class)); /* @@ -349,4 +349,16 @@ public class BaseJpaRestfulServer extends RestfulServer { } } + 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 4768e17..d81361b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -31,18 +31,10 @@ public class FhirServerConfigCommon { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); - private Boolean enableIndexMissingFields = HapiProperties.getEnableIndexMissingFields(); - private Boolean autoCreatePlaceholderReferenceTargets = HapiProperties.getAutoCreatePlaceholderReferenceTargets(); - private Boolean enforceReferentialIntegrityOnWrite = HapiProperties.getEnforceReferentialIntegrityOnWrite(); - private Boolean enforceReferentialIntegrityOnDelete = HapiProperties.getEnforceReferentialIntegrityOnDelete(); - private Boolean allowContainsSearches = HapiProperties.getAllowContainsSearches(); - private Boolean allowMultipleDelete = HapiProperties.getAllowMultipleDelete(); - private Boolean allowExternalReferences = HapiProperties.getAllowExternalReferences(); - private Boolean expungeEnabled = HapiProperties.getExpungeEnabled(); - private Boolean allowPlaceholderReferences = HapiProperties.getAllowPlaceholderReferences(); + private Boolean subscriptionRestHookEnabled = HapiProperties.getSubscriptionRestHookEnabled(); private Boolean subscriptionEmailEnabled = HapiProperties.getSubscriptionEmailEnabled(); - private Boolean allowOverrideDefaultSearchParams = HapiProperties.getAllowOverrideDefaultSearchParams(); + private String emailFrom = HapiProperties.getEmailFrom(); private Boolean emailEnabled = HapiProperties.getEmailEnabled(); private String emailHost = HapiProperties.getEmailHost(); @@ -118,26 +110,26 @@ public class FhirServerConfigCommon { retVal.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); // Subscriptions are enabled by channel type - if (HapiProperties.getSubscriptionRestHookEnabled()) { + if (appProperties.getSubscription().getResthook_enabled()) { ourLog.info("Enabling REST-hook subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); } - if (HapiProperties.getSubscriptionEmailEnabled()) { + if (appProperties.getSubscription().getEmail_enabled()) { ourLog.info("Enabling email subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); } - if (HapiProperties.getSubscriptionWebsocketEnabled()) { + if (appProperties.getSubscription().getWebsocket_enabled()) { ourLog.info("Enabling websocket subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); } - retVal.setFilterParameterEnabled(HapiProperties.getFilterSearchEnabled()); + retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); return retVal; } @Bean - public PartitionSettings partitionSettings() { + public PartitionSettings partitionSettings(AppProperties appProperties) { PartitionSettings retVal = new PartitionSettings(); // Partitioning diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index 587f313..68190ec 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -17,7 +17,6 @@ import javax.sql.DataSource; @Configuration @Profile("r4") -@ConditionalOnClass(DataSource.class) public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java index dbcca69..45a7808 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java @@ -33,18 +33,22 @@ public class FhirTesterConfig { * deploying your server to a place with a fully qualified domain name, * you might want to use that instead of using the variable. */ - @Bean - public TesterConfig testerConfig(AppProperties appProperties) { - TesterConfig retVal = new TesterConfig(); - retVal - .addServer() - .withId(appProperties.getTester().getId()) - .withFhirVersion(appProperties.getFhir_version()) - .withBaseUrl(appProperties.getTester().getAddress()) - .withName(appProperties.getTester().getName()); - retVal.setRefuseToFetchThirdPartyUrls(appProperties.getTester().getRefuse_to_fetch_third_party_urls()); - return retVal; - } + @Bean + public TesterConfig testerConfig(AppProperties appProperties) { + TesterConfig retVal = new TesterConfig(); + appProperties.getTester().stream().forEach(t -> { + retVal + .addServer() + .withId(t.getId()) + .withFhirVersion(t.getFhir_version()) + .withBaseUrl(t.getServer_address()) + .withName(t.getName()); + retVal.setRefuseToFetchThirdPartyUrls( + t.getRefuse_to_fetch_third_party_urls()); + + }); + return retVal; + } } //@formatter:on diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4c0c72c..13ec39d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -2,9 +2,12 @@ spring: datasource: url: 'jdbc:h2:file:./target/database/h2dflkjglkj' username: sa - password: + password: null driverClassName: org.h2.Driver max-active: 15 + profiles: + ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 + active: r4 hapi: fhir: allow_cascading_deletes: true @@ -21,8 +24,7 @@ hapi: enforce_referential_integrity_on_write: false etag_support_enabled: true expunge_enabled: true - fhir_version: DSTU3 - daoconfig_client_id_strategy: + daoconfig_client_id_strategy: null fhirpath_interceptor_enabled: false filter_search_enabled: true graphql_enabled: true @@ -40,16 +42,28 @@ hapi: retain_cached_searches_mins: 60 reuse_cached_search_results_millis: 60000 tester: - id: home - name: Local Tester - server_address: 'http://localhost:8080/fhir' - refuse_to_fetch_third_party_urls: false + - + id: home + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 + - + id: 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 bulk_export_enabled: true + partitioning_multitenancy_enabled: + subscription: + email_enabled: false + resthook_enabled: false + websocket_enabled: false elasticsearch: debug: pretty_print_json_log: false @@ -59,4 +73,4 @@ elasticsearch: required_index_status: YELLOW rest_url: 'http://localhost:9200' schema_management_strategy: CREATE - username: SomeUsername \ No newline at end of file + username: SomeUsername From 437d22e460322fe9e9b5d7121378184886457459 Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 13:47:09 +0200 Subject: [PATCH 07/22] All but tests works --- pom.xml | 11 +- .../java/ca/uhn/fhir/jpa/empi/EmpiConfig.java | 5 +- .../uhn/fhir/jpa/starter/AppProperties.java | 217 ++++++++++++++++-- .../ca/uhn/fhir/jpa/starter/Application.java | 2 +- .../jpa/starter/BaseJpaRestfulServer.java | 181 +++++++-------- .../jpa/starter/FhirServerConfigCommon.java | 110 ++++----- .../fhir/jpa/starter/JpaRestfulServer.java | 11 +- src/main/resources/application.yaml | 133 ++++++----- .../jpa/starter/ExampleServerDstu2IT.java | 9 +- 9 files changed, 436 insertions(+), 243 deletions(-) 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); From dc34e6f7858a69e6bb7027dc6ffb3965da1ac617 Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 13:58:39 +0200 Subject: [PATCH 08/22] Removed use of web.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 94d87c0..c3426d9 100644 --- a/pom.xml +++ b/pom.xml @@ -377,7 +377,7 @@ hapi-fhir-testpage-overlay - src/main/webapp/WEB-INF/web.xml + false From 4dc398c5a17c0f837c49efe6e4ef035b4fb4708f Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 15:04:12 +0200 Subject: [PATCH 09/22] Now works with mvn jetty:run --- pom.xml | 22 +++++--- .../ca/uhn/fhir/jpa/starter/Application.java | 29 +++++++++- .../jpa/starter/BaseJpaRestfulServer.java | 11 ++-- .../fhir/jpa/starter/JpaRestfulServer.java | 2 +- src/main/webapp/WEB-INF/web.xml | 54 ------------------- 5 files changed, 51 insertions(+), 67 deletions(-) delete mode 100644 src/main/webapp/WEB-INF/web.xml diff --git a/pom.xml b/pom.xml index c3426d9..507cc40 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ 11 ${java.version} ${java.version} + 9.4.31.v20200723 @@ -283,19 +284,26 @@ test - org.springframework.boot - spring-boot-starter-tomcat + spring-boot-starter-web + 2.3.3.RELEASE + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty 2.3.3.RELEASE - - org.springframework.boot spring-boot-autoconfigure 2.3.3.RELEASE - @@ -377,9 +385,9 @@ hapi-fhir-testpage-overlay - - false + + 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 e09c995..d773ad9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,18 +1,24 @@ package ca.uhn.fhir.jpa.starter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; +import java.util.Arrays; + @ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) -public class Application { +public class Application extends SpringBootServletInitializer { public static void main(String[] args) { @@ -23,6 +29,27 @@ public class Application { //UI is now accessible at http://localhost:8080/ } + @Override + protected SpringApplicationBuilder configure( + SpringApplicationBuilder builder) { + return builder.sources(Application.class); + } + + + @Autowired + AutowireCapableBeanFactory beanFactory; + + @Bean + public ServletRegistrationBean hapiServletRegistration() { + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); + JpaRestfulServer jpaRestfulServer = new JpaRestfulServer(); + beanFactory.autowireBean(jpaRestfulServer); + servletRegistrationBean.setServlet(jpaRestfulServer); + servletRegistrationBean.addUrlMappings("/hapi-fhir-jpaserver/fhir/*"); + servletRegistrationBean.setLoadOnStartup(1); + return servletRegistrationBean; + } + @Bean public ServletRegistrationBean servletRegistrationBean() { 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 168a06b..616854b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,7 +11,9 @@ 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.*; +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.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5; @@ -35,13 +37,14 @@ import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; import javax.servlet.ServletException; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; - public class BaseJpaRestfulServer extends RestfulServer { - @Autowired DaoRegistry daoRegistry; 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 8669fc8..773cc32 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java @@ -6,7 +6,7 @@ import javax.servlet.annotation.WebServlet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Import; -@WebServlet(urlPatterns = {"/hapi-fhir-jpaserver/fhir/*"}) +//@WebServlet(urlPatterns = {"/hapi-fhir-jpaserver/fhir/*"}) @Import(AppProperties.class) public class JpaRestfulServer extends BaseJpaRestfulServer { diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 6ce88b0..0000000 --- a/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - org.springframework.web.context.ContextLoaderListener - - - contextClass - - ca.uhn.fhir.jpa.starter.ApplicationContext - - - - contextConfigLocation - - - - - - - spring - org.springframework.web.servlet.DispatcherServlet - - contextClass - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - contextConfigLocation - - ca.uhn.fhir.jpa.starter.FhirTesterConfig - - - 2 - - - spring - / - - - - fhirServlet - ca.uhn.fhir.jpa.starter.JpaRestfulServer - 1 - - - fhirServlet - /fhir/* - - - From 0fd6409bc3a967ee20d476f963ca52b3c103acbc Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 15:06:07 +0200 Subject: [PATCH 10/22] updated example instructions --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 507cc40..cc21fc7 100644 --- a/pom.xml +++ b/pom.xml @@ -346,7 +346,7 @@ - + org.eclipse.jetty jetty-maven-plugin From 8894711d8e7d599029c1c182795b32d21cc9d3b8 Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 22:00:54 +0200 Subject: [PATCH 11/22] Added profiles --- pom.xml | 104 +++++++++--------- .../uhn/fhir/jpa/starter/AppProperties.java | 5 +- .../ca/uhn/fhir/jpa/starter/Application.java | 10 +- .../jpa/starter/FhirServerConfigCommon.java | 8 -- .../fhir/jpa/starter/FhirServerConfigR4.java | 1 - .../fhir/jpa/starter/JpaRestfulServer.java | 6 +- 6 files changed, 57 insertions(+), 77 deletions(-) diff --git a/pom.xml b/pom.xml index cc21fc7..e368bc4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - @@ -248,18 +239,7 @@ jetty-webapp test - + - - org.springframework.boot - spring-boot-starter-logging - 2.3.3.RELEASE - test + ${spring.boot} @@ -347,6 +302,7 @@ + @@ -365,7 +322,7 @@ maven-compiler-plugin 3.8.1 - 11 + 8 @@ -385,10 +342,7 @@ hapi-fhir-testpage-overlay - - false - @@ -503,9 +457,49 @@ - - + + + + + + + boot + + + org.springframework.boot + spring-boot-starter-web + 2.3.3.RELEASE + + + + + + + + jetty + + + org.springframework.boot + spring-boot-starter-web + 2.3.3.RELEASE + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + 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 b8613b4..a18abf4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -8,6 +8,7 @@ import ca.uhn.fhir.rest.api.EncodingEnum; import java.util.ArrayList; import java.util.List; +import com.google.common.collect.ImmutableList; import org.hl7.fhir.r4.model.Bundle; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -51,7 +52,7 @@ public class AppProperties { private List allowed_bundle_types = null; private Validation validation = new Validation(); - private List tester = new ArrayList<>(); + private List tester = ImmutableList.of(new Tester()); private Logger logger = new Logger(); private Subscription subscription = new Subscription(); private Cors cors = null; @@ -353,7 +354,7 @@ public class AppProperties { public static class Cors { private Boolean allow_Credentials = true; - private List allowed_origin = new ArrayList<>();//List.of("*"); + private List allowed_origin = ImmutableList.of("*"); public List getAllowed_origin() { return allowed_origin; 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 d773ad9..e8decb9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -6,7 +6,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @@ -14,8 +13,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -import java.util.Arrays; - @ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) public class Application extends SpringBootServletInitializer { @@ -25,8 +22,8 @@ public class Application extends SpringBootServletInitializer { System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); - //Server is now accessible at eg. http://localhost:8080/fhir/metadata - //UI is now accessible at http://localhost:8080/ + //Server is now accessible at eg. http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata + //UI is now accessible at http://localhost:8080/hapi-fhir-jpaserver/ } @Override @@ -35,7 +32,6 @@ public class Application extends SpringBootServletInitializer { return builder.sources(Application.class); } - @Autowired AutowireCapableBeanFactory beanFactory; @@ -51,7 +47,7 @@ public class Application extends SpringBootServletInitializer { } @Bean - public ServletRegistrationBean servletRegistrationBean() { + public ServletRegistrationBean overlayRegistrationBean() { AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext(); annotationConfigWebApplicationContext.register(FhirTesterConfig.class); 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 28aab92..cfe9bde 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -9,18 +9,12 @@ import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHan 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; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.thymeleaf.util.Validate; -import java.lang.reflect.InvocationTargetException; -import java.sql.Driver; import java.util.Optional; /** @@ -32,8 +26,6 @@ public class FhirServerConfigCommon { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); - @Autowired - private ApplicationContext appContext; public FhirServerConfigCommon(AppProperties appProperties) { ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches"); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index 68190ec..d0ac06f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -4,7 +4,6 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; 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 773cc32..c895c22 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java @@ -1,12 +1,10 @@ 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 = {"/hapi-fhir-jpaserver/fhir/*"}) +import javax.servlet.ServletException; + @Import(AppProperties.class) public class JpaRestfulServer extends BaseJpaRestfulServer { From d208f12546d871c554e74ca92b6b54d7dab07aac Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 7 Sep 2020 23:41:04 +0200 Subject: [PATCH 12/22] rewrote unit tests --- pom.xml | 21 +++- .../java/ca/uhn/fhir/jpa/empi/EmpiConfig.java | 1 - .../jpa/starter/FhirServerConfigDstu2.java | 19 ++-- .../jpa/starter/FhirServerConfigDstu3.java | 13 ++- .../fhir/jpa/starter/FhirServerConfigR4.java | 19 ++-- .../fhir/jpa/starter/FhirServerConfigR5.java | 16 +-- .../starter/{Application.java => Demo.java} | 4 +- .../jpa/starter/ExampleServerDstu2IT.java | 74 ++++--------- .../jpa/starter/ExampleServerDstu3IT.java | 78 +++++-------- .../fhir/jpa/starter/ExampleServerR4IT.java | 96 ++++++---------- .../fhir/jpa/starter/ExampleServerR5IT.java | 70 +++++------- .../jpa/starter/MultitenantServerR4IT.java | 94 ++++++---------- .../jpa/starter/RandomServerPortProvider.java | 36 ------ .../application-integrationtest.yaml | 103 ++++++++++++++++++ 14 files changed, 302 insertions(+), 342 deletions(-) rename src/test/java/ca/uhn/fhir/jpa/starter/{Application.java => Demo.java} (90%) delete mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/RandomServerPortProvider.java create mode 100644 src/test/resources/application-integrationtest.yaml diff --git a/pom.xml b/pom.xml index e368bc4..30c6e51 100644 --- a/pom.xml +++ b/pom.xml @@ -271,13 +271,26 @@ - - junit - junit - 4.12 + org.junit.jupiter + junit-jupiter-api + 5.6.2 test + + org.junit.jupiter + junit-jupiter-engine + 5.6.2 + test + + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot} + test + + 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 d54dfea..6b8f2d2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java @@ -4,7 +4,6 @@ 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; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 562e2bd..55b0995 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -26,13 +26,16 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { * the default/max page sizes for search results. You can set these however * you want, although very large page sizes will require a lot of RAM. */ - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(HapiProperties.getDefaultPageSize()); - pagingProvider.setMaximumPageSize(HapiProperties.getMaximumPageSize()); - return pagingProvider; - } + @Autowired + AppProperties appProperties; + + @Override + public DatabaseBackedPagingProvider databaseBackedPagingProvider() { + DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } @Override @Bean() @@ -46,7 +49,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(HapiProperties.getJpaProperties()); + return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index df0eb6d..0ff5914 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -26,12 +26,15 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { * the default/max page sizes for search results. You can set these however * you want, although very large page sizes will require a lot of RAM. */ + @Autowired + AppProperties appProperties; + @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(HapiProperties.getDefaultPageSize()); - pagingProvider.setMaximumPageSize(HapiProperties.getMaximumPageSize()); - return pagingProvider; + DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; } @Override @@ -46,7 +49,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(HapiProperties.getJpaProperties()); + return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index d0ac06f..574d93b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -26,13 +26,16 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { * the default/max page sizes for search results. You can set these however * you want, although very large page sizes will require a lot of RAM. */ - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(HapiProperties.getDefaultPageSize()); - pagingProvider.setMaximumPageSize(HapiProperties.getMaximumPageSize()); - return pagingProvider; - } + @Autowired + AppProperties appProperties; + + @Override + public DatabaseBackedPagingProvider databaseBackedPagingProvider() { + DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } @Override @Bean() @@ -46,7 +49,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(HapiProperties.getJpaProperties()); + return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index c73f51f..050f1c3 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -26,14 +26,16 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { * the default/max page sizes for search results. You can set these however * you want, although very large page sizes will require a lot of RAM. */ - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(HapiProperties.getDefaultPageSize()); - pagingProvider.setMaximumPageSize(HapiProperties.getMaximumPageSize()); - return pagingProvider; - } + @Autowired + AppProperties appProperties; + @Override + public DatabaseBackedPagingProvider databaseBackedPagingProvider() { + DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } @Override @Bean() public LocalContainerEntityManagerFactoryBean entityManagerFactory() { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/Application.java b/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java similarity index 90% rename from src/test/java/ca/uhn/fhir/jpa/starter/Application.java rename to src/test/java/ca/uhn/fhir/jpa/starter/Demo.java index d771840..5dadf14 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java @@ -7,13 +7,13 @@ import org.springframework.boot.web.servlet.ServletComponentScan; @ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) -public class Application { +public class Demo { public static void main(String[] args) { System.setProperty("spring.profiles.active", "r4"); System.setProperty("spring.batch.job.enabled", "false"); - SpringApplication.run(Application.class, args); + SpringApplication.run(Demo.class, args); //Server is now accessible at eg. http://localhost:8080/metadata } 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 26a0385..dc9fcce 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -5,80 +5,54 @@ import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import ca.uhn.fhir.test.utilities.JettyUtil; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import java.nio.file.Paths; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = + { + "spring.batch.job.enabled=false", + "spring.profiles.active=dstu2", + "spring.datasource.url=jdbc:h2:mem:dbr2" + }) public class ExampleServerDstu2IT { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); - private static IGenericClient ourClient; - private static FhirContext ourCtx; - private static int ourPort; - private static Server ourServer; + private IGenericClient ourClient; + private FhirContext ourCtx; - static { - 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"); - } + @LocalServerPort + private int port; + + @Test + void testCreateAndRead() { - @Test - public void testCreateAndRead() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); String methodName = "testCreateResourceConditional"; Patient pt = new Patient(); pt.addName().addFamily(methodName); IIdType id = ourClient.create().resource(pt).execute().getId(); - Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute(); assertEquals(methodName, pt2.getName().get(0).getFamily().get(0).getValue()); } - @AfterAll - public static void afterClass() throws Exception { - ourServer.stop(); - } - @BeforeAll - public static void beforeClass() throws Exception { - String path = Paths.get("").toAbsolutePath().toString(); - - ourLog.info("Project base path is: {}", path); - - ourServer = new Server(0); - - WebAppContext webAppContext = new WebAppContext(); - webAppContext.setContextPath("/hapi-fhir-jpaserver"); - - - webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter"); - webAppContext.setParentLoaderPriority(true); - - ourServer.setHandler(webAppContext); - ourServer.start(); - - ourPort = JettyUtil.getPortForStartedServer(ourServer); + @BeforeEach + void beforeEach() { + ourCtx = FhirContext.forDstu2(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } - - public static void main(String[] theArgs) throws Exception { - ourPort = 8080; - beforeClass(); - } } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 5ff9de5..208ca01 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -7,9 +7,6 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import ca.uhn.fhir.test.utilities.JettyUtil; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; @@ -18,39 +15,44 @@ import org.hl7.fhir.dstu3.model.Observation; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Subscription; import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit.jupiter.SpringExtension; import java.net.URI; -import java.nio.file.Paths; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static ca.uhn.fhir.util.TestUtil.waitForSize; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = + { + "spring.batch.job.enabled=false", + "spring.profiles.active=dstu3", + "spring.datasource.url=jdbc:h2:mem:dbr3", + "hapi.fhir.subscription.websocket_enabled=true", + "hapi.fhir.allow_external_references=true", + "hapi.fhir.allow_placeholder_references=true", + }) + + public class ExampleServerDstu3IT { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu3IT.class); - private static IGenericClient ourClient; - private static FhirContext ourCtx; - private static int ourPort; - private static Server ourServer; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + private IGenericClient ourClient; + private FhirContext ourCtx; - static { - HapiProperties.forceReload(); - HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "DSTU3"); - HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr3"); - HapiProperties.setProperty(HapiProperties.SUBSCRIPTION_WEBSOCKET_ENABLED, "true"); - HapiProperties.setProperty(HapiProperties.ALLOW_EXTERNAL_REFERENCES, "true"); - HapiProperties.setProperty(HapiProperties.ALLOW_PLACEHOLDER_REFERENCES, "true"); - ourCtx = FhirContext.forDstu3(); - } + @LocalServerPort + private int port; @Test public void testCreateAndRead() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); + String methodName = "testCreateResourceConditional"; Patient pt = new Patient(); @@ -90,7 +92,7 @@ public class ExampleServerDstu3IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + ourPort + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -119,39 +121,15 @@ public class ExampleServerDstu3IT { ourClient.delete().resourceById(mySubscriptionId).execute(); } - @AfterAll - public static void afterClass() throws Exception { - ourServer.stop(); - } - - @BeforeAll - public static void beforeClass() throws Exception { - String path = Paths.get("").toAbsolutePath().toString(); - - ourLog.info("Project base path is: {}", path); - - ourServer = new Server(0); - - 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); - - ourServer.setHandler(webAppContext); - ourServer.start(); - - ourPort = JettyUtil.getPortForStartedServer(ourServer); + @BeforeEach + void beforeEach() { + ourCtx = FhirContext.forDstu3(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } - public static void main(String[] theArgs) throws Exception { - ourPort = 8080; - beforeClass(); - } } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index c610481..2b0f1ae 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -7,26 +7,20 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import ca.uhn.fhir.test.utilities.JettyUtil; import ca.uhn.fhir.util.BundleUtil; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.Observation; -import org.hl7.fhir.r4.model.Patient; -import org.hl7.fhir.r4.model.Person; -import org.hl7.fhir.r4.model.Reference; -import org.hl7.fhir.r4.model.Subscription; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.hl7.fhir.r4.model.*; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit.jupiter.SpringExtension; import java.net.URI; -import java.nio.file.Paths; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -38,26 +32,28 @@ import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = + { + "spring.batch.job.enabled=false", + "spring.profiles.active=r5", + "spring.datasource.url=jdbc:h2:mem:dbr5", + "hapi.fhir.subscription.websocket_enabled=true", + "hapi.fhir.empi_enabled=true" + }) public class ExampleServerR4IT { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4IT.class); - private static IGenericClient ourClient; - private static FhirContext ourCtx; - private static int ourPort; - private static Server ourServer; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + private IGenericClient ourClient; + private FhirContext ourCtx; + + @LocalServerPort + private int port; - static { - HapiProperties.forceReload(); - HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr4"); - HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "R4"); - HapiProperties.setProperty(HapiProperties.SUBSCRIPTION_WEBSOCKET_ENABLED, "true"); - HapiProperties.setProperty(HapiProperties.EMPI_ENABLED, "true"); - ourCtx = FhirContext.forR4(); - } @Test - public void testCreateAndRead() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); + void testCreateAndRead() { + String methodName = "testCreateResourceConditional"; Patient pt = new Patient(); @@ -121,7 +117,7 @@ public class ExampleServerR4IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + ourPort + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -154,42 +150,16 @@ public class ExampleServerR4IT { return ourClient.search().forResource(Subscription.class).where(Subscription.STATUS.exactly().code("active")).cacheControl(new CacheControlDirective().setNoCache(true)).returnBundle(Bundle.class).execute().getEntry().size(); } - @AfterAll - public static void afterClass() throws Exception { - ourServer.stop(); - } - @BeforeAll - public static void beforeClass() throws Exception { - String path = Paths.get("").toAbsolutePath().toString(); - ourLog.info("Project base path is: {}", path); + @BeforeEach + void beforeEach() { - ourServer = new Server(0); - - WebAppContext webAppContext = new WebAppContext(); - webAppContext.setContextPath("/hapi-fhir-jpaserver"); - webAppContext.setDisplayName("HAPI FHIR"); - webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml"); - webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter"); - webAppContext.setParentLoaderPriority(true); - - ourServer.setHandler(webAppContext); - ourServer.start(); - - ourPort = JettyUtil.getPortForStartedServer(ourServer); - - ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); - ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = HapiProperties.getServerAddress(); - ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/"; - - ourClient = ourCtx.newRestfulGenericClient(ourServerBase); - ourClient.registerInterceptor(new LoggingInterceptor(true)); - } - - public static void main(String[] theArgs) throws Exception { - ourPort = 8080; - beforeClass(); - } + ourCtx = FhirContext.forR4(); + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + ourClient = ourCtx.newRestfulGenericClient(ourServerBase); + ourClient.registerInterceptor(new LoggingInterceptor(true)); + } } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index ea9855f..bc0e517 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -22,7 +22,12 @@ import org.hl7.fhir.r5.model.Subscription; import org.hl7.fhir.r5.model.SubscriptionTopic; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit.jupiter.SpringExtension; import java.net.URI; import java.nio.file.Paths; @@ -33,25 +38,27 @@ import static ca.uhn.fhir.util.TestUtil.waitForSize; import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = + { + "spring.batch.job.enabled=false", + "spring.profiles.active=r5", + "spring.datasource.url=jdbc:h2:mem:dbr5", + "hapi.fhir.subscription.websocket_enabled=true" + }) public class ExampleServerR5IT { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR5IT.class); - private static IGenericClient ourClient; - private static FhirContext ourCtx; - private static int ourPort; - private static Server ourServer; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + private IGenericClient ourClient; + private FhirContext ourCtx; + + @LocalServerPort + private int port; - static { - HapiProperties.forceReload(); - HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr5"); - HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "R5"); - HapiProperties.setProperty(HapiProperties.SUBSCRIPTION_WEBSOCKET_ENABLED, "true"); - ourCtx = FhirContext.forR5(); - } @Test public void testCreateAndRead() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); + String methodName = "testCreateResourceConditional"; Patient pt = new Patient(); @@ -97,7 +104,7 @@ public class ExampleServerR5IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + ourPort + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -123,41 +130,14 @@ public class ExampleServerR5IT { ourClient.delete().resourceById(mySubscriptionId).execute(); } - @AfterAll - public static void afterClass() throws Exception { - ourServer.stop(); - } - - @BeforeAll - public static void beforeClass() throws Exception { - String path = Paths.get("").toAbsolutePath().toString(); - - ourLog.info("Project base path is: {}", path); - - ourServer = new Server(0); - - WebAppContext webAppContext = new WebAppContext(); - webAppContext.setContextPath("/hapi-fhir-jpaserver"); - webAppContext.setDisplayName("HAPI FHIR"); - webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml"); - webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter"); - webAppContext.setParentLoaderPriority(true); - - ourServer.setHandler(webAppContext); - ourServer.start(); - - ourPort = JettyUtil.getPortForStartedServer(ourServer); + @BeforeEach + void beforeEach() { + ourCtx = FhirContext.forR5(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/"; - + String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } - - public static void main(String[] theArgs) throws Exception { - ourPort = 8080; - beforeClass(); - } } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 25e7315..fa29203 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -7,44 +7,43 @@ import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.client.interceptor.UrlTenantSelectionInterceptor; import ca.uhn.fhir.rest.server.provider.ProviderConstants; -import ca.uhn.fhir.test.utilities.JettyUtil; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; -import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.CodeType; -import org.hl7.fhir.r4.model.IntegerType; -import org.hl7.fhir.r4.model.Parameters; -import org.hl7.fhir.r4.model.Patient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.hl7.fhir.r4.model.*; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import java.nio.file.Paths; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = + { + "spring.batch.job.enabled=false", + "spring.profiles.active=r4", + "spring.datasource.url=jdbc:h2:mem:dbr4-mt", + "hapi.fhir.subscription.websocket_enabled=true", + "hapi.fhir.subscription.websocket_enabled=true", + "hapi.fhir.partitioning_multitenancy_enabled" + + }) public class MultitenantServerR4IT { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MultitenantServerR4IT.class); - private static IGenericClient ourClient; - private static FhirContext ourCtx; - private static int ourPort; - private static Server ourServer; + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + private IGenericClient ourClient; + private FhirContext ourCtx; + + @LocalServerPort + private int port; + private static UrlTenantSelectionInterceptor ourClientTenantInterceptor; - static { - HapiProperties.forceReload(); - HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr4-mt"); - HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "R4"); - HapiProperties.setProperty(HapiProperties.SUBSCRIPTION_WEBSOCKET_ENABLED, "true"); - HapiProperties.setProperty(HapiProperties.PARTITIONING_ENABLED, "true"); - HapiProperties.setProperty(HapiProperties.PARTITIONING_MULTITENANCY_ENABLED, "true"); - ourCtx = FhirContext.forR4(); - } @Test public void testCreateAndReadInTenantA() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); + // Create tenant A ourClientTenantInterceptor.setTenantId("DEFAULT"); @@ -70,7 +69,7 @@ public class MultitenantServerR4IT { @Test public void testCreateAndReadInTenantB() { - ourLog.info("Base URL is: " + HapiProperties.getServerAddress()); + // Create tenant A ourClientTenantInterceptor.setTenantId("DEFAULT"); @@ -94,45 +93,14 @@ public class MultitenantServerR4IT { assertEquals("Family B", pt2.getName().get(0).getFamily()); } - @AfterAll - public static void afterClass() throws Exception { - ourServer.stop(); - } - - @BeforeAll - public static void beforeClass() throws Exception { - String path = Paths.get("").toAbsolutePath().toString(); - - ourLog.info("Project base path is: {}", path); - - ourServer = new Server(0); - - WebAppContext webAppContext = new WebAppContext(); - webAppContext.setContextPath("/hapi-fhir-jpaserver"); - webAppContext.setDisplayName("HAPI FHIR"); - webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml"); - webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter"); - webAppContext.setParentLoaderPriority(true); - - ourServer.setHandler(webAppContext); - ourServer.start(); - - ourPort = JettyUtil.getPortForStartedServer(ourServer); + @BeforeEach + void beforeEach() { + ourCtx = FhirContext.forR4(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = HapiProperties.getServerAddress(); - ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/"; - + String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); - - ourClientTenantInterceptor = new UrlTenantSelectionInterceptor(); - ourClient.registerInterceptor(ourClientTenantInterceptor); - } - - public static void main(String[] theArgs) throws Exception { - ourPort = 8080; - beforeClass(); } } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/RandomServerPortProvider.java b/src/test/java/ca/uhn/fhir/jpa/starter/RandomServerPortProvider.java deleted file mode 100644 index 65446f0..0000000 --- a/src/test/java/ca/uhn/fhir/jpa/starter/RandomServerPortProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import java.io.IOException; -import java.net.ServerSocket; -import java.util.ArrayList; -import java.util.List; - -/** - * Provides server ports - */ -public class RandomServerPortProvider { - - private static List ourPorts = new ArrayList(); - - public static int findFreePort() { - ServerSocket server; - try { - server = new ServerSocket(0); - int port = server.getLocalPort(); - ourPorts.add(port); - server.close(); - Thread.sleep(500); - return port; - } catch (IOException e) { - throw new Error(e); - } catch (InterruptedException e) { - throw new Error(e); - } - } - - public static List list() { - return ourPorts; - } - -} - \ No newline at end of file diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml new file mode 100644 index 0000000..f43409e --- /dev/null +++ b/src/test/resources/application-integrationtest.yaml @@ -0,0 +1,103 @@ +spring: + datasource: + url: 'jdbc:h2:file:./target/database/h2' + username: sa + password: null + driverClassName: org.h2.Driver + max-active: 15 + profiles: + ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 + active: r4 +hapi: + fhir: + #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/hapi-fhir-jpaserver/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 + - + id: 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 +# 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 From 9f0b32ff71132bb55dbf1354e924d857959570c7 Mon Sep 17 00:00:00 2001 From: jvi Date: Tue, 8 Sep 2020 12:39:39 +0200 Subject: [PATCH 13/22] Unit tests are starting to work again ... --- .../fhir/jpa/starter/EnvironmentHelper.java | 92 +++++++++++++++++++ .../jpa/starter/FhirServerConfigDstu2.java | 58 +++++++----- .../jpa/starter/FhirServerConfigDstu3.java | 78 ++++++++-------- .../fhir/jpa/starter/FhirServerConfigR4.java | 57 +++++++----- .../fhir/jpa/starter/FhirServerConfigR5.java | 55 ++++++----- src/main/resources/application.yaml | 18 +++- .../jpa/starter/ExampleServerDstu2IT.java | 2 + .../application-integrationtest.yaml | 3 +- 8 files changed, 249 insertions(+), 114 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java new file mode 100644 index 0000000..036f2be --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -0,0 +1,92 @@ +package ca.uhn.fhir.jpa.starter; + +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +public class EnvironmentHelper { + + public static Properties getHibernateProperties(ConfigurableEnvironment environment) { + Properties properties = new Properties(); + if (environment.getProperty("spring.jpa.properties", String.class) == null) { + properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + properties.put("hibernate.search.model_mapping", "ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory"); + properties.put("hibernate.format_sql", "false"); + properties.put("hibernate.show_sql", "false"); + properties.put("hibernate.hbm2ddl.auto", "update"); + properties.put("hibernate.jdbc.batch_size", "20"); + properties.put("hibernate.cache.use_query_cache", "false"); + properties.put("hibernate.cache.use_second_level_cache", "false"); + properties.put("hibernate.cache.use_structured_entries", "false"); + properties.put("hibernate.cache.use_minimal_puts", "false"); + properties.put("hibernate.search.default.directory_provider", "filesystem"); + properties.put("hibernate.search.default.indexBase", "target/lucenefiles"); + properties.put("hibernate.search.lucene_version", "LUCENE_CURRENT"); + } else { + Arrays.asList(environment.getProperty("spring.jpa.properties", String.class).split(" ")).stream().forEach(s -> + { + String[] values = s.split("="); + properties.put(values[0], values[1]); + }); + } + return properties; + } + + public static Map getPropertiesStartingWith(ConfigurableEnvironment aEnv, + String aKeyPrefix) { + Map result = new HashMap<>(); + + Map map = getAllProperties(aEnv); + + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + + if (key.startsWith(aKeyPrefix)) { + result.put(key, entry.getValue()); + } + } + + return result; + } + + public static Map getAllProperties(ConfigurableEnvironment aEnv) { + Map result = new HashMap<>(); + aEnv.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); + return result; + } + + public static Map getAllProperties(PropertySource aPropSource) { + Map result = new HashMap<>(); + + if (aPropSource instanceof CompositePropertySource) { + CompositePropertySource cps = (CompositePropertySource) aPropSource; + cps.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); + return result; + } + + if (aPropSource instanceof EnumerablePropertySource) { + EnumerablePropertySource ps = (EnumerablePropertySource) aPropSource; + Arrays.asList(ps.getPropertyNames()).forEach(key -> result.put(key, ps.getProperty(key))); + return result; + } + + return result; + + } + + private static void addAll(Map aBase, Map aToBeAdded) { + for (Map.Entry entry : aToBeAdded.entrySet()) { + if (aBase.containsKey(entry.getKey())) { + continue; + } + + aBase.put(entry.getKey(), entry.getValue()); + } + } +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 55b0995..8efc81f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -8,26 +8,31 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; @Configuration @Profile("dstu2") public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { - @Autowired - private DataSource myDataSource; + @Autowired + private DataSource myDataSource; - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; + /** + * We override the paging provider definition so that we can customize + * the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Autowired + AppProperties appProperties; @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @@ -37,28 +42,31 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { return pagingProvider; } - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); - retVal.setPersistenceUnitName("HAPI_PU"); + @Autowired + private ConfigurableEnvironment configurableEnvironment; - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } + @Override + @Bean() + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + retVal.setPersistenceUnitName("HAPI_PU"); - - return retVal; + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + return retVal; + } @Bean @Primary public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } + } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 0ff5914..ace88af 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -8,6 +8,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -18,47 +19,50 @@ import javax.sql.DataSource; @Profile("dstu3") public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { - @Autowired - private DataSource myDataSource; + @Autowired + private DataSource myDataSource; - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; + /** + * We override the paging provider definition so that we can customize + * the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Autowired + AppProperties appProperties; - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; + @Override + public DatabaseBackedPagingProvider databaseBackedPagingProvider() { + DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } + + @Autowired + private ConfigurableEnvironment configurableEnvironment; + + @Override + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + retVal.setPersistenceUnitName("HAPI_PU"); + + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - @Override - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); - retVal.setPersistenceUnitName("HAPI_PU"); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + return retVal; + } - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - - - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } + @Bean + @Primary + public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index 574d93b..8d8e699 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -8,26 +8,30 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; +import java.util.Arrays; +import java.util.Properties; @Configuration @Profile("r4") public class FhirServerConfigR4 extends BaseJavaConfigR4 { - @Autowired - private DataSource myDataSource; + @Autowired + private DataSource myDataSource; - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; + /** + * We override the paging provider definition so that we can customize + * the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Autowired + AppProperties appProperties; @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @@ -37,28 +41,31 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { return pagingProvider; } - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); - retVal.setPersistenceUnitName("HAPI_PU"); + @Autowired + private ConfigurableEnvironment configurableEnvironment; - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } + @Override + @Bean() + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + retVal.setPersistenceUnitName("HAPI_PU"); - - return retVal; + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + return retVal; + } + @Bean @Primary public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 050f1c3..5a5145b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -8,6 +8,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -18,16 +19,16 @@ import javax.sql.DataSource; @Profile("r5") public class FhirServerConfigR5 extends BaseJavaConfigR5 { - @Autowired - private DataSource myDataSource; + @Autowired + private DataSource myDataSource; - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; + /** + * We override the paging provider definition so that we can customize + * the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Autowired + AppProperties appProperties; @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @@ -36,28 +37,32 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); return pagingProvider; } - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); - retVal.setPersistenceUnitName("HAPI_PU"); - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } + @Autowired + private ConfigurableEnvironment configurableEnvironment; - retVal.setJpaProperties(HapiProperties.getJpaProperties()); - return retVal; + @Override + @Bean() + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + retVal.setPersistenceUnitName("HAPI_PU"); + + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + return retVal; + } + @Bean @Primary public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f43409e..b47792e 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -7,7 +7,23 @@ spring: max-active: 15 profiles: ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 - active: r4 + active: dstu2 + jpa: + properties: + hibernate.dialect: org.hibernate.dialect.H2Dialect + hibernate.search.model_mapping: ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory + hibernate.format_sql: false + hibernate.show_sql: false + hibernate.hbm2ddl.auto: update + hibernate.jdbc.batch_size: 20 + hibernate.cache.use_query_cache: false + hibernate.cache.use_second_level_cache: false + hibernate.cache.use_structured_entries: false + hibernate.cache.use_minimal_puts: false + hibernate.search.default.directory_provider: filesystem + hibernate.search.default.indexBase: target/lucenefiles + hibernate.search.lucene_version: LUCENE_CURRENT + hapi: fhir: #supported_resource_types: 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 dc9fcce..c4d3b82 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -12,11 +12,13 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) +@TestPropertySource(locations = "/application-integrationtest.yaml") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { "spring.batch.job.enabled=false", diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml index f43409e..2153cbb 100644 --- a/src/test/resources/application-integrationtest.yaml +++ b/src/test/resources/application-integrationtest.yaml @@ -7,7 +7,8 @@ spring: max-active: 15 profiles: ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 - active: r4 + active: dstu2 + hapi: fhir: #supported_resource_types: From fb3cbcca8be85e6a4cbbb52f5e437ba5e6b67620 Mon Sep 17 00:00:00 2001 From: jvi Date: Tue, 8 Sep 2020 13:03:42 +0200 Subject: [PATCH 14/22] Formatting ... --- .../jpa/starter/ExampleServerDstu2IT.java | 3 - .../fhir/jpa/starter/ExampleServerR4IT.java | 141 +++++++++--------- .../fhir/jpa/starter/ExampleServerR5IT.java | 2 +- 3 files changed, 71 insertions(+), 75 deletions(-) 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 c4d3b82..aeab8d7 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -11,14 +11,11 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) -@TestPropertySource(locations = "/application-integrationtest.yaml") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { "spring.batch.job.enabled=false", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 2b0f1ae..b502674 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -51,37 +51,37 @@ public class ExampleServerR4IT { private int port; - @Test - void testCreateAndRead() { + @Test + void testCreateAndRead() { - String methodName = "testCreateResourceConditional"; + String methodName = "testCreateResourceConditional"; - Patient pt = new Patient(); - pt.setActive(true); - pt.getBirthDateElement().setValueAsString("2020-01-01"); - pt.addIdentifier().setSystem("http://foo").setValue("12345"); - pt.addName().setFamily(methodName); - IIdType id = ourClient.create().resource(pt).execute().getId(); + Patient pt = new Patient(); + pt.setActive(true); + pt.getBirthDateElement().setValueAsString("2020-01-01"); + pt.addIdentifier().setSystem("http://foo").setValue("12345"); + pt.addName().setFamily(methodName); + IIdType id = ourClient.create().resource(pt).execute().getId(); - Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute(); - assertEquals(methodName, pt2.getName().get(0).getFamily()); + Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute(); + assertEquals(methodName, pt2.getName().get(0).getFamily()); - // Test EMPI + // Test EMPI - // Wait until the EMPI message has been processed - await().until(() -> getPeople().size() > 0); - List persons = getPeople(); + // Wait until the EMPI message has been processed + await().until(() -> getPeople().size() > 0); + List persons = getPeople(); - // Verify a Person was created that links to our Patient - Optional personLinkToCreatedPatient = persons.stream() - .map(Person::getLink) - .flatMap(Collection::stream) - .map(Person.PersonLinkComponent::getTarget) - .map(Reference::getReference) - .filter(pid -> id.toUnqualifiedVersionless().getValue().equals(pid)) - .findAny(); - assertTrue(personLinkToCreatedPatient.isPresent()); - } + // Verify a Person was created that links to our Patient + Optional personLinkToCreatedPatient = persons.stream() + .map(Person::getLink) + .flatMap(Collection::stream) + .map(Person.PersonLinkComponent::getTarget) + .map(Reference::getReference) + .filter(pid -> id.toUnqualifiedVersionless().getValue().equals(pid)) + .findAny(); + assertTrue(personLinkToCreatedPatient.isPresent()); + } private List getPeople() { Bundle bundle = ourClient.search().forResource(Person.class).cacheControl(new CacheControlDirective().setNoCache(true)).returnBundle(Bundle.class).execute(); @@ -89,69 +89,68 @@ public class ExampleServerR4IT { } @Test - public void testWebsocketSubscription() throws Exception { - /* - * Create subscription - */ - Subscription subscription = new Subscription(); - subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); - subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED); - subscription.setCriteria("Observation?status=final"); + public void testWebsocketSubscription() throws Exception { + /* + * Create subscription + */ + Subscription subscription = new Subscription(); + subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); + subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED); + subscription.setCriteria("Observation?status=final"); - Subscription.SubscriptionChannelComponent channel = new Subscription.SubscriptionChannelComponent(); - channel.setType(Subscription.SubscriptionChannelType.WEBSOCKET); - channel.setPayload("application/json"); - subscription.setChannel(channel); + Subscription.SubscriptionChannelComponent channel = new Subscription.SubscriptionChannelComponent(); + channel.setType(Subscription.SubscriptionChannelType.WEBSOCKET); + channel.setPayload("application/json"); + subscription.setChannel(channel); - MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); - IIdType mySubscriptionId = methodOutcome.getId(); + MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); + IIdType mySubscriptionId = methodOutcome.getId(); - // Wait for the subscription to be activated - await().until(() -> activeSubscriptionCount() == 3); + // Wait for the subscription to be activated + await().until(() -> activeSubscriptionCount() == 3); - /* - * Attach websocket - */ + /* + * Attach websocket + */ - WebSocketClient myWebSocketClient = new WebSocketClient(); - SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); + WebSocketClient myWebSocketClient = new WebSocketClient(); + SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); - myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - ourLog.info("Connecting to : {}", echoUri); - Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); - Session session = connection.get(2, TimeUnit.SECONDS); + myWebSocketClient.start(); + URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); + ClientUpgradeRequest request = new ClientUpgradeRequest(); + ourLog.info("Connecting to : {}", echoUri); + Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); + Session session = connection.get(2, TimeUnit.SECONDS); - ourLog.info("Connected to WS: {}", session.isOpen()); + ourLog.info("Connected to WS: {}", session.isOpen()); - /* - * Create a matching resource - */ - Observation obs = new Observation(); - obs.setStatus(Observation.ObservationStatus.FINAL); - ourClient.create().resource(obs).execute(); + /* + * Create a matching resource + */ + Observation obs = new Observation(); + obs.setStatus(Observation.ObservationStatus.FINAL); + ourClient.create().resource(obs).execute(); - // Give some time for the subscription to deliver - Thread.sleep(2000); + // Give some time for the subscription to deliver + Thread.sleep(2000); - /* - * Ensure that we receive a ping on the websocket - */ - waitForSize(1, () -> mySocketImplementation.myPingCount); + /* + * Ensure that we receive a ping on the websocket + */ + waitForSize(1, () -> mySocketImplementation.myPingCount); - /* - * Clean up - */ - ourClient.delete().resourceById(mySubscriptionId).execute(); - } + /* + * Clean up + */ + ourClient.delete().resourceById(mySubscriptionId).execute(); + } private int activeSubscriptionCount() { return ourClient.search().forResource(Subscription.class).where(Subscription.STATUS.exactly().code("active")).cacheControl(new CacheControlDirective().setNoCache(true)).returnBundle(Bundle.class).execute().getEntry().size(); } - @BeforeEach void beforeEach() { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index bc0e517..a8b1981 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -122,7 +122,7 @@ public class ExampleServerR5IT { /* * Ensure that we receive a ping on the websocket */ - await().until(()->mySocketImplementation.myPingCount > 0); + await().until(() -> mySocketImplementation.myPingCount > 0); /* * Clean up From 3af0d403ef475e4799a7c244809aca7e992e23b0 Mon Sep 17 00:00:00 2001 From: jvi Date: Tue, 8 Sep 2020 13:05:08 +0200 Subject: [PATCH 15/22] Removed old format --- .../uhn/fhir/jpa/starter/HapiProperties.java | 529 ------------------ src/main/resources/hapi.properties | 167 ------ 2 files changed, 696 deletions(-) delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java delete mode 100644 src/main/resources/hapi.properties diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java deleted file mode 100644 index 844fcbd..0000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/HapiProperties.java +++ /dev/null @@ -1,529 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.jpa.api.config.DaoConfig; -import ca.uhn.fhir.jpa.search.elastic.ElasticsearchHibernatePropertiesBuilder; -import ca.uhn.fhir.rest.api.EncodingEnum; -import ca.uhn.fhir.rest.server.ETagSupportEnum; -import com.google.common.annotations.VisibleForTesting; -import org.apache.commons.lang3.StringUtils; -import org.hibernate.search.elasticsearch.cfg.ElasticsearchIndexStatus; -import org.hibernate.search.elasticsearch.cfg.IndexSchemaManagementStrategy; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nonnull; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.*; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.StringUtils.defaultString; - -public class HapiProperties { - static final String ENABLE_INDEX_MISSING_FIELDS = "enable_index_missing_fields"; - static final String AUTO_CREATE_PLACEHOLDER_REFERENCE_TARGETS = "auto_create_placeholder_reference_targets"; - static final String ENFORCE_REFERENTIAL_INTEGRITY_ON_WRITE = "enforce_referential_integrity_on_write"; - static final String ENFORCE_REFERENTIAL_INTEGRITY_ON_DELETE = "enforce_referential_integrity_on_delete"; - static final String BINARY_STORAGE_ENABLED = "binary_storage.enabled"; - static final String ALLOW_EXTERNAL_REFERENCES = "allow_external_references"; - static final String ALLOW_MULTIPLE_DELETE = "allow_multiple_delete"; - static final String ALLOW_PLACEHOLDER_REFERENCES = "allow_placeholder_references"; - static final String REUSE_CACHED_SEARCH_RESULTS_MILLIS = "reuse_cached_search_results_millis"; - static final String DATASOURCE_DRIVER = "datasource.driver"; - static final String DATASOURCE_MAX_POOL_SIZE = "datasource.max_pool_size"; - static final String DATASOURCE_PASSWORD = "datasource.password"; - static final String DATASOURCE_URL = "datasource.url"; - static final String DATASOURCE_USERNAME = "datasource.username"; - static final String DEFAULT_ENCODING = "default_encoding"; - static final String DEFAULT_PAGE_SIZE = "default_page_size"; - static final String DEFAULT_PRETTY_PRINT = "default_pretty_print"; - static final String ETAG_SUPPORT = "etag_support"; - static final String FHIR_VERSION = "fhir_version"; - static final String ALLOW_CASCADING_DELETES = "allow_cascading_deletes"; - static final String HAPI_PROPERTIES = "hapi.properties"; - static final String LOGGER_ERROR_FORMAT = "logger.error_format"; - static final String LOGGER_FORMAT = "logger.format"; - static final String LOGGER_LOG_EXCEPTIONS = "logger.log_exceptions"; - static final String LOGGER_NAME = "logger.name"; - static final String MAX_FETCH_SIZE = "max_fetch_size"; - static final String MAX_PAGE_SIZE = "max_page_size"; - static final String SERVER_ADDRESS = "server_address"; - static final String SERVER_ID = "server.id"; - static final String SERVER_NAME = "server.name"; - static final String SUBSCRIPTION_EMAIL_ENABLED = "subscription.email.enabled"; - static final String SUBSCRIPTION_RESTHOOK_ENABLED = "subscription.resthook.enabled"; - static final String SUBSCRIPTION_WEBSOCKET_ENABLED = "subscription.websocket.enabled"; - static final String EMPI_ENABLED = "empi.enabled"; - static final String PARTITIONING_ENABLED = "partitioning.enabled"; - static final String PARTITIONING_CROSS_PARTITION_REFERENCE_MODE = "partitioning.cross_partition_reference_mode"; - static final String ALLOWED_BUNDLE_TYPES = "allowed_bundle_types"; - static final String TEST_PORT = "test.port"; - static final String TESTER_CONFIG_REFUSE_TO_FETCH_THIRD_PARTY_URLS = "tester.config.refuse_to_fetch_third_party_urls"; - static final String CORS_ENABLED = "cors.enabled"; - static final String CORS_ALLOWED_ORIGIN = "cors.allowed_origin"; - static final String CORS_ALLOW_CREDENTIALS = "cors.allowCredentials"; - static final String ALLOW_CONTAINS_SEARCHES = "allow_contains_searches"; - static final String ALLOW_OVERRIDE_DEFAULT_SEARCH_PARAMS = "allow_override_default_search_params"; - static final String EMAIL_FROM = "email.from"; - static final String VALIDATE_REQUESTS_ENABLED = "validation.requests.enabled"; - static final String VALIDATE_RESPONSES_ENABLED = "validation.responses.enabled"; - static final String FILTER_SEARCH_ENABLED = "filter_search.enabled"; - static final String GRAPHQL_ENABLED = "graphql.enabled"; - static final String BULK_EXPORT_ENABLED = "bulk.export.enabled"; - static final String EXPIRE_SEARCH_RESULTS_AFTER_MINS = "retain_cached_searches_mins"; - static final String MAX_BINARY_SIZE = "max_binary_size"; - static final String PARTITIONING_MULTITENANCY_ENABLED = "partitioning.multitenancy.enabled"; - private static final String PARTITIONING_INCLUDE_PARTITION_IN_SEARCH_HASHES = "partitioning.partitioning_include_in_search_hashes"; - static final String CLIENT_ID_STRATEGY = "daoconfig.client_id_strategy"; - private static Properties ourProperties; - - public static boolean isElasticSearchEnabled() { - return HapiProperties.getPropertyBoolean("elasticsearch.enabled", false); - } - - /* - * Force the configuration to be reloaded - */ - public static void forceReload() { - ourProperties = null; - getProperties(); - } - - /** - * This is mostly here for unit tests. Use the actual properties file - * to set values - */ - @VisibleForTesting - public static void setProperty(String theKey, String theValue) { - getProperties().setProperty(theKey, theValue); - } - - public static Properties getJpaProperties() { - Properties retVal = loadProperties(); - - if (isElasticSearchEnabled()) { - ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder(); - builder.setRequiredIndexStatus(getPropertyEnum("elasticsearch.required_index_status", ElasticsearchIndexStatus.class, ElasticsearchIndexStatus.YELLOW)); - builder.setRestUrl(getProperty("elasticsearch.rest_url")); - builder.setUsername(getProperty("elasticsearch.username")); - builder.setPassword(getProperty("elasticsearch.password")); - builder.setIndexSchemaManagementStrategy(getPropertyEnum("elasticsearch.schema_management_strategy", IndexSchemaManagementStrategy.class, IndexSchemaManagementStrategy.CREATE)); - builder.setDebugRefreshAfterWrite(getPropertyBoolean("elasticsearch.debug.refresh_after_write", false)); - builder.setDebugPrettyPrintJsonLog(getPropertyBoolean("elasticsearch.debug.pretty_print_json_log", false)); - builder.apply(retVal); - } - - return retVal; - } - - private static Properties getProperties() { - if (ourProperties == null) { - Properties properties = loadProperties(); - HapiProperties.ourProperties = properties; - } - - return ourProperties; - } - - @NotNull - private static Properties loadProperties() { - // Load the configurable properties file - Properties properties; - try (InputStream in = HapiProperties.class.getClassLoader().getResourceAsStream(HAPI_PROPERTIES)) { - properties = new Properties(); - properties.load(in); - } catch (Exception e) { - throw new ConfigurationException("Could not load HAPI properties", e); - } - - Properties overrideProps = loadOverrideProperties(); - if (overrideProps != null) { - properties.putAll(overrideProps); - } - properties.putAll(System.getenv().entrySet() - .stream() - .filter(e -> e.getValue() != null && properties.containsKey(e.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); - return properties; - } - - /** - * If a configuration file path is explicitly specified via -Dhapi.properties=, the properties there will - * be used to override the entries in the default hapi.properties file (currently under WEB-INF/classes) - * - * @return properties loaded from the explicitly specified configuraiton file if there is one, or null otherwise. - */ - private static Properties loadOverrideProperties() { - String confFile = System.getProperty(HAPI_PROPERTIES); - if (confFile != null) { - try { - Properties props = new Properties(); - props.load(new FileInputStream(confFile)); - return props; - } catch (Exception e) { - throw new ConfigurationException("Could not load HAPI properties file: " + confFile, e); - } - } - - return null; - } - - private static String getProperty(String propertyName) { - String env = "HAPI_" + propertyName.toUpperCase(Locale.US); - env = env.replace(".", "_"); - env = env.replace("-", "_"); - - String propertyValue = System.getenv(env); - if (propertyValue != null) { - return propertyValue; - } - - Properties properties = HapiProperties.getProperties(); - if (properties != null) { - propertyValue = properties.getProperty(propertyName); - } - - return propertyValue; - } - - private static String getProperty(String propertyName, String defaultValue) { - String value = getProperty(propertyName); - - if (value != null && value.length() > 0) { - return value; - } - - return defaultValue; - } - - private static Boolean getBooleanProperty(String propertyName, Boolean defaultValue) { - String value = HapiProperties.getProperty(propertyName); - - if (value == null || value.length() == 0) { - return defaultValue; - } - - return Boolean.parseBoolean(value); - } - - private static boolean getBooleanProperty(String propertyName, boolean defaultValue) { - return getBooleanProperty(propertyName, Boolean.valueOf(defaultValue)); - } - - private static Integer getIntegerProperty(String propertyName, Integer defaultValue) { - String value = HapiProperties.getProperty(propertyName); - - if (value == null || value.length() == 0) { - return defaultValue; - } - - return Integer.parseInt(value); - } - - public static FhirVersionEnum getFhirVersion() { - String fhirVersionString = HapiProperties.getProperty(FHIR_VERSION); - - if (fhirVersionString != null && fhirVersionString.length() > 0) { - return FhirVersionEnum.valueOf(fhirVersionString); - } - - return FhirVersionEnum.DSTU3; - } - - public static boolean isBinaryStorageEnabled() { - return HapiProperties.getBooleanProperty(BINARY_STORAGE_ENABLED, true); - } - - public static ETagSupportEnum getEtagSupport() { - String etagSupportString = HapiProperties.getProperty(ETAG_SUPPORT); - - if (etagSupportString != null && etagSupportString.length() > 0) { - return ETagSupportEnum.valueOf(etagSupportString); - } - - return ETagSupportEnum.ENABLED; - } - - public static DaoConfig.ClientIdStrategyEnum getClientIdStrategy() { - String idStrategy = HapiProperties.getProperty(CLIENT_ID_STRATEGY); - - if (idStrategy != null && idStrategy.length() > 0) { - return DaoConfig.ClientIdStrategyEnum.valueOf(idStrategy); - } - - return DaoConfig.ClientIdStrategyEnum.ALPHANUMERIC; - } - - public static EncodingEnum getDefaultEncoding() { - String defaultEncodingString = HapiProperties.getProperty(DEFAULT_ENCODING); - - if (defaultEncodingString != null && defaultEncodingString.length() > 0) { - return EncodingEnum.valueOf(defaultEncodingString); - } - - return EncodingEnum.JSON; - } - - public static Boolean getDefaultPrettyPrint() { - return HapiProperties.getBooleanProperty(DEFAULT_PRETTY_PRINT, true); - } - - public static String getServerAddress() { - return HapiProperties.getProperty(SERVER_ADDRESS); - } - - public static Integer getDefaultPageSize() { - return HapiProperties.getIntegerProperty(DEFAULT_PAGE_SIZE, 20); - } - - public static Integer getMaximumPageSize() { - return HapiProperties.getIntegerProperty(MAX_PAGE_SIZE, 200); - } - - public static Integer getMaximumFetchSize() { - return HapiProperties.getIntegerProperty(MAX_FETCH_SIZE, Integer.MAX_VALUE); - } - - public static String getLoggerName() { - return HapiProperties.getProperty(LOGGER_NAME, "fhirtest.access"); - } - - public static String getLoggerFormat() { - return HapiProperties.getProperty(LOGGER_FORMAT, "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); - } - - public static String getLoggerErrorFormat() { - return HapiProperties.getProperty(LOGGER_ERROR_FORMAT, "ERROR - ${requestVerb} ${requestUrl}"); - } - - public static Boolean getLoggerLogExceptions() { - return HapiProperties.getBooleanProperty(LOGGER_LOG_EXCEPTIONS, true); - } - - public static String getDataSourceDriver() { - return HapiProperties.getProperty(DATASOURCE_DRIVER, "org.apache.derby.jdbc.EmbeddedDriver"); - } - - public static Integer getDataSourceMaxPoolSize() { - return HapiProperties.getIntegerProperty(DATASOURCE_MAX_POOL_SIZE, 10); - } - - public static String getDataSourceUrl() { - return HapiProperties.getProperty(DATASOURCE_URL, "jdbc:derby:directory:target/jpaserver_derby_files;create=true"); - } - - public static String getDataSourceUsername() { - return HapiProperties.getProperty(DATASOURCE_USERNAME); - } - - public static String getDataSourcePassword() { - return HapiProperties.getProperty(DATASOURCE_PASSWORD); - } - - public static Boolean getAllowMultipleDelete() { - return HapiProperties.getBooleanProperty(ALLOW_MULTIPLE_DELETE, false); - } - - public static Boolean getAllowCascadingDeletes() { - return HapiProperties.getBooleanProperty(ALLOW_CASCADING_DELETES, false); - } - - public static Boolean getAllowExternalReferences() { - return HapiProperties.getBooleanProperty(ALLOW_EXTERNAL_REFERENCES, false); - } - - public static Boolean getExpungeEnabled() { - return HapiProperties.getBooleanProperty("expunge_enabled", true); - } - - public static Boolean getTesterConfigRefustToFetchThirdPartyUrls() { - return HapiProperties.getBooleanProperty(TESTER_CONFIG_REFUSE_TO_FETCH_THIRD_PARTY_URLS, false); - } - - public static Boolean getCorsEnabled() { - return HapiProperties.getBooleanProperty(CORS_ENABLED, true); - } - - public static String getCorsAllowedOrigin() { - return HapiProperties.getProperty(CORS_ALLOWED_ORIGIN, "*"); - } - - public static String getAllowedBundleTypes() { - return HapiProperties.getProperty(ALLOWED_BUNDLE_TYPES, ""); - } - - @Nonnull - public static Set getSupportedResourceTypes() { - String[] types = defaultString(getProperty("supported_resource_types")).split(","); - return Arrays.stream(types) - .map(StringUtils::trim) - .filter(StringUtils::isNotBlank) - .collect(Collectors.toSet()); - } - - public static String getServerName() { - return HapiProperties.getProperty(SERVER_NAME, "Local Tester"); - } - - public static String getServerId() { - return HapiProperties.getProperty(SERVER_ID, "home"); - } - - public static Boolean getAllowPlaceholderReferences() { - return HapiProperties.getBooleanProperty(ALLOW_PLACEHOLDER_REFERENCES, true); - } - - public static Boolean getSubscriptionEmailEnabled() { - return HapiProperties.getBooleanProperty(SUBSCRIPTION_EMAIL_ENABLED, false); - } - - public static Boolean getSubscriptionRestHookEnabled() { - return HapiProperties.getBooleanProperty(SUBSCRIPTION_RESTHOOK_ENABLED, false); - } - - public static Boolean getSubscriptionWebsocketEnabled() { - return HapiProperties.getBooleanProperty(SUBSCRIPTION_WEBSOCKET_ENABLED, false); - } - - public static Boolean getEmpiEnabled() { - return HapiProperties.getBooleanProperty(EMPI_ENABLED, false); - } - - public static Boolean getPartitioningEnabled() { - return HapiProperties.getBooleanProperty(PARTITIONING_ENABLED, false); - } - - - public static String getPartitioningCrossPartitionReferenceMode() { - return HapiProperties.getProperty(PARTITIONING_CROSS_PARTITION_REFERENCE_MODE, "NOT_ALLOWED"); - } - - public static Boolean getIncludePartitionInSearchHashes() { - return HapiProperties.getBooleanProperty(PARTITIONING_INCLUDE_PARTITION_IN_SEARCH_HASHES, true); - } - - public static Boolean getAllowContainsSearches() { - return HapiProperties.getBooleanProperty(ALLOW_CONTAINS_SEARCHES, true); - } - - public static Boolean getAllowOverrideDefaultSearchParams() { - return HapiProperties.getBooleanProperty(ALLOW_OVERRIDE_DEFAULT_SEARCH_PARAMS, true); - } - - public static String getEmailFrom() { - return HapiProperties.getProperty(EMAIL_FROM, "some@test.com"); - } - - public static Boolean getEmailEnabled() { - return HapiProperties.getBooleanProperty("email.enabled", false); - } - - public static String getEmailHost() { - return HapiProperties.getProperty("email.host"); - } - - public static Integer getEmailPort() { - return HapiProperties.getIntegerProperty("email.port", 0); - } - - public static String getEmailUsername() { - return HapiProperties.getProperty("email.username"); - } - - public static String getEmailPassword() { - return HapiProperties.getProperty("email.password"); - } - - // Defaults from https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html - public static Boolean getEmailAuth() { - return HapiProperties.getBooleanProperty("email.auth", false); - } - - public static Boolean getEmailStartTlsEnable() { - return HapiProperties.getBooleanProperty("email.starttls.enable", false); - } - - public static Boolean getEmailStartTlsRequired() { - return HapiProperties.getBooleanProperty("email.starttls.required", false); - } - - public static Boolean getEmailQuitWait() { - return HapiProperties.getBooleanProperty("email.quitwait", true); - } - - public static Long getReuseCachedSearchResultsMillis() { - String value = HapiProperties.getProperty(REUSE_CACHED_SEARCH_RESULTS_MILLIS, "60000"); - return Long.valueOf(value); - } - - public static Long getExpireSearchResultsAfterMins() { - String value = HapiProperties.getProperty(EXPIRE_SEARCH_RESULTS_AFTER_MINS, "60"); - return Long.valueOf(value); - } - - public static Boolean getCorsAllowedCredentials() { - return HapiProperties.getBooleanProperty(CORS_ALLOW_CREDENTIALS, false); - } - - public static boolean getValidateRequestsEnabled() { - return HapiProperties.getBooleanProperty(VALIDATE_REQUESTS_ENABLED, false); - } - - public static boolean getValidateResponsesEnabled() { - return HapiProperties.getBooleanProperty(VALIDATE_RESPONSES_ENABLED, false); - } - - public static boolean getFilterSearchEnabled() { - return HapiProperties.getBooleanProperty(FILTER_SEARCH_ENABLED, true); - } - - public static boolean getGraphqlEnabled() { - return HapiProperties.getBooleanProperty(GRAPHQL_ENABLED, true); - } - - public static boolean getEnforceReferentialIntegrityOnDelete() { - return HapiProperties.getBooleanProperty(ENFORCE_REFERENTIAL_INTEGRITY_ON_DELETE, true); - } - - public static boolean getEnforceReferentialIntegrityOnWrite() { - return HapiProperties.getBooleanProperty(ENFORCE_REFERENTIAL_INTEGRITY_ON_WRITE, true); - } - - public static boolean getAutoCreatePlaceholderReferenceTargets() { - return HapiProperties.getBooleanProperty(AUTO_CREATE_PLACEHOLDER_REFERENCE_TARGETS, true); - } - - public static boolean getEnableIndexMissingFields() { - return HapiProperties.getBooleanProperty(ENABLE_INDEX_MISSING_FIELDS, false); - } - - public static Integer getMaxBinarySize() { - return getIntegerProperty(MAX_BINARY_SIZE, null); - } - - private static boolean getPropertyBoolean(String thePropertyName, boolean theDefaultValue) { - String value = getProperty(thePropertyName, Boolean.toString(theDefaultValue)); - return Boolean.parseBoolean(value); - } - - private static T getPropertyEnum(String thePropertyName, Class theEnumType, T theDefaultValue) { - String value = getProperty(thePropertyName, theDefaultValue.name()); - return (T) Enum.valueOf(theEnumType, value); - } - - public static boolean getBulkExportEnabled() { - return HapiProperties.getBooleanProperty(BULK_EXPORT_ENABLED, true); - } - - public static boolean isFhirPathFilterInterceptorEnabled() { - return HapiProperties.getBooleanProperty("fhirpath_interceptor.enabled", false); - } - - public static boolean getPartitioningMultitenancyEnabled() { - return HapiProperties.getBooleanProperty(PARTITIONING_MULTITENANCY_ENABLED, false); - } - - -} - diff --git a/src/main/resources/hapi.properties b/src/main/resources/hapi.properties deleted file mode 100644 index 22a7b2f..0000000 --- a/src/main/resources/hapi.properties +++ /dev/null @@ -1,167 +0,0 @@ -# Adjust this to set the version of FHIR supported by this server. See -# FhirVersionEnum for a list of available constants. Example values include -# DSTU2, DSTU3, R4. -fhir_version=R4 - -# This is the address that the FHIR server will report as its own address. -# If this server will be deployed (for example) to an internet accessible -# server, put the DNS name of that server here. -# -# Note that this is also the address that the hapi-fhir-testpage-overlay -# (the web UI similar to the one at http://hapi.fhir.org) will use to -# connect internally to the FHIR server, so this also needs to be a name -# accessible from the server itself. -server_address=http://localhost:8080/fhir - -enable_index_missing_fields=false -auto_create_placeholder_reference_targets=false -enforce_referential_integrity_on_write=false -enforce_referential_integrity_on_delete=false -default_encoding=JSON -etag_support=ENABLED -reuse_cached_search_results_millis=60000 -retain_cached_searches_mins=60 -default_page_size=20 -max_page_size=200 -allow_override_default_search_params=true -allow_contains_searches=true -allow_multiple_delete=true -allow_external_references=true -allow_cascading_deletes=true -allow_placeholder_references=true -expunge_enabled=true -persistence_unit_name=HAPI_PU -logger.name=fhirtest.access -logger.format=Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}] -logger.error_format=ERROR - ${requestVerb} ${requestUrl} -logger.log_exceptions=true -datasource.driver=org.h2.Driver -datasource.url=jdbc:h2:file:./target/database/h2 -datasource.username= -datasource.password= -server.name=Local Tester -server.id=home -test.port= - -################################################### -# Binary Storage (104857600 = 100mb) -################################################### -max_binary_size=104857600 - -################################################### -# Validation -################################################### -# Should all incoming requests be validated -validation.requests.enabled=false -# Should outgoing responses be validated -validation.responses.enabled=false - -################################################### -# Search Features -################################################### -filter_search.enabled=true -graphql.enabled=true -# See FhirPathFilterInterceptor -fhirpath_interceptor.enabled=false - -################################################### -# Supported Resources -################################################### -# Enable the following property if you want to customize the -# list of resources that is supported by the server (i.e. to -# disable specific resources) -#supported_resource_types=Patient,Observation,Encounter - -################################################### -# Database Settings -################################################### -hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.search.model_mapping=ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory -hibernate.format_sql=false -hibernate.show_sql=false -hibernate.hbm2ddl.auto=update -hibernate.jdbc.batch_size=20 -hibernate.cache.use_query_cache=false -hibernate.cache.use_second_level_cache=false -hibernate.cache.use_structured_entries=false -hibernate.cache.use_minimal_puts=false -hibernate.search.default.directory_provider=filesystem -hibernate.search.default.indexBase=target/lucenefiles -hibernate.search.lucene_version=LUCENE_CURRENT -tester.config.refuse_to_fetch_third_party_urls=false - -################################################## -# ElasticSearch -# Note that using ElasticSearch is disabled by -# default and the server will use Lucene instead. -################################################## -elasticsearch.enabled=false -elasticsearch.rest_url=http://localhost:9200 -elasticsearch.username=SomeUsername -elasticsearch.password=SomePassword -elasticsearch.required_index_status=YELLOW -elasticsearch.schema_management_strategy=CREATE -# Immediately refresh indexes after every write. This is very bad for -# performance, but can be helpful for testing. -elasticsearch.debug.refresh_after_write=false -elasticsearch.debug.pretty_print_json_log=false - - -################################################## -# Binary Storage Operations -################################################## -binary_storage.enabled=true - -################################################## -# Bulk Data Specification -################################################## -bulk.export.enabled=true - -################################################## -# CORS Settings -################################################## -cors.enabled=true -cors.allowCredentials=true -# Supports multiple, comma separated allowed origin entries -# cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca -cors.allowed_origin=* - -################################################## -# Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE) -################################################## -#allowed_bundle_types=COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET - -################################################## -# Subscriptions -################################################## - -# Enable REST Hook Subscription Channel -subscription.resthook.enabled=false - -# Enable Email Subscription Channel -subscription.email.enabled=false -email.enabled=false -email.from=some@test.com -email.host= -email.port=0 -email.username= -email.password= - -# Enable Websocket Subscription Channel -subscription.websocket.enabled=false - -################################################### -# EMPI -################################################### -empi.enabled=false - -################################################### -# Partitioning And Multitenancy -################################################### -partitioning.enabled=false -partitioning.cross_partition_reference_mode=NOT_ALLOWED -partitioning.partitioning_include_in_search_hashes=true -partitioning.multitenancy.enabled=false - -#daoconfig.client_id_strategy=ANY - From afad974f92f55cc8558e70b0b1b0be014c997874 Mon Sep 17 00:00:00 2001 From: jvi Date: Tue, 8 Sep 2020 13:37:30 +0200 Subject: [PATCH 16/22] add jib oneliner --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 30c6e51..333a3ed 100644 --- a/pom.xml +++ b/pom.xml @@ -3,6 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + + + boot 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 a18abf4..fd22023 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -10,6 +10,7 @@ import java.util.List; import com.google.common.collect.ImmutableList; 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; @@ -42,6 +43,7 @@ public class AppProperties { private Integer default_page_size = 20; private Integer max_binary_size = null; private Integer max_page_size = Integer.MAX_VALUE; + private Integer defer_indexing_for_codesystems_of_size = 100; private Long retain_cached_searches_mins = 60L; private Long reuse_cached_search_results_millis = 60000L; private String server_address = null; @@ -57,6 +59,23 @@ public class AppProperties { private Subscription subscription = new Subscription(); private Cors cors = null; private Partitioning partitioning = null; + private List implementationGuides = null; + + public Integer getDefer_indexing_for_codesystems_of_size() { + return defer_indexing_for_codesystems_of_size; + } + + public void setDefer_indexing_for_codesystems_of_size(Integer defer_indexing_for_codesystems_of_size) { + this.defer_indexing_for_codesystems_of_size = defer_indexing_for_codesystems_of_size; + } + + public List getImplementationGuides() { + return implementationGuides; + } + + public void setImplementationGuides(List implementationGuides) { + this.implementationGuides = implementationGuides; + } public Partitioning getPartitioning() { return partitioning; @@ -465,6 +484,37 @@ public class AppProperties { } } + public static class ImplementationGuide + { + private String url; + private String name; + private String version; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + } + public static class Validation { private Boolean requests_enabled = false; 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 616854b..814395f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -10,6 +10,8 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; 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.packages.IPackageInstallerSvc; +import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider; import ca.uhn.fhir.jpa.provider.IJpaSystemProvider; @@ -87,6 +89,9 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired BinaryStorageInterceptor binaryStorageInterceptor; + @Autowired + IPackageInstallerSvc packageInstallerSvc; + @Autowired AppProperties appProperties; @@ -162,7 +167,7 @@ public class BaseJpaRestfulServer extends RestfulServer { * ETag Support */ - if(appProperties.getEtag_support_enabled() == false) + if (appProperties.getEtag_support_enabled() == false) setETagSupport(ETagSupportEnum.DISABLED); @@ -320,6 +325,8 @@ public class BaseJpaRestfulServer extends RestfulServer { daoConfig.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet())); } + daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); + // Bulk Export if (appProperties.getBulk_export_enabled()) { registerProvider(bulkDataExportProvider); @@ -336,6 +343,17 @@ public class BaseJpaRestfulServer extends RestfulServer { daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID); daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); } + + if (appProperties.getImplementationGuides() != null) { + List guides = appProperties.getImplementationGuides(); + for (AppProperties.ImplementationGuide guide : guides) { + packageInstallerSvc.install(new PackageInstallationSpec() + .setPackageUrl(guide.getUrl()) + .setName(guide.getName()) + .setVersion(guide.getVersion()) + .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)); + } + } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b47792e..6841215 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -7,7 +7,7 @@ spring: max-active: 15 profiles: ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 - active: dstu2 + active: r4 jpa: properties: hibernate.dialect: org.hibernate.dialect.H2Dialect @@ -26,6 +26,16 @@ spring: hapi: fhir: + defer_indexing_for_codesystems_of_size: 101 + implementationguides: + - + url: https://build.fhir.org/ig/hl7dk/dk-medcom/branches/corrections/package.tgz + name: dk.fhir.ig.medcom-core + version: 0.8.0 + - + name: hl7.fhir.uv.ips + version: 0.3.0 + #supported_resource_types: # - Patient # - Observation From 7d79d5d8b523bca60abd1be8843c52d9e0d079ac Mon Sep 17 00:00:00 2001 From: jkv Date: Tue, 8 Sep 2020 23:46:42 +0200 Subject: [PATCH 18/22] Got subscription stuff working again --- .../ca/uhn/fhir/jpa/starter/Application.java | 18 ++++++++++++++-- src/main/resources/application.yaml | 16 +++++++------- .../fhir/jpa/starter/ExampleServerR4IT.java | 4 ++-- .../fhir/jpa/starter/ExampleServerR5IT.java | 21 +++++++------------ .../jpa/starter/MultitenantServerR4IT.java | 4 ++-- .../application-integrationtest.yaml | 2 +- 6 files changed, 36 insertions(+), 29 deletions(-) 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 e8decb9..ba23124 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,5 +1,9 @@ package ca.uhn.fhir.jpa.starter; +import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; +import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; +import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; +import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.boot.SpringApplication; @@ -13,7 +17,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") +@ServletComponentScan(basePackageClasses = { + JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) public class Application extends SpringBootServletInitializer { @@ -43,15 +48,24 @@ public class Application extends SpringBootServletInitializer { servletRegistrationBean.setServlet(jpaRestfulServer); servletRegistrationBean.addUrlMappings("/hapi-fhir-jpaserver/fhir/*"); servletRegistrationBean.setLoadOnStartup(1); + return servletRegistrationBean; } + @Bean public ServletRegistrationBean overlayRegistrationBean() { AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext(); annotationConfigWebApplicationContext.register(FhirTesterConfig.class); - DispatcherServlet dispatcherServlet = new DispatcherServlet(annotationConfigWebApplicationContext); + + annotationConfigWebApplicationContext.register(SubscriptionSubmitterConfig.class); + annotationConfigWebApplicationContext.register(SubscriptionProcessorConfig.class); + annotationConfigWebApplicationContext.register(SubscriptionChannelConfig.class); + annotationConfigWebApplicationContext.register(WebsocketDispatcherConfig.class); + + DispatcherServlet dispatcherServlet = new DispatcherServlet( + annotationConfigWebApplicationContext); dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class); dispatcherServlet.setContextConfigLocation(FhirTesterConfig.class.getName()); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 6841215..7a91683 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -27,14 +27,14 @@ spring: hapi: fhir: defer_indexing_for_codesystems_of_size: 101 - implementationguides: - - - url: https://build.fhir.org/ig/hl7dk/dk-medcom/branches/corrections/package.tgz - name: dk.fhir.ig.medcom-core - version: 0.8.0 - - - name: hl7.fhir.uv.ips - version: 0.3.0 +# implementationguides: +# - +# url: https://build.fhir.org/ig/hl7dk/dk-medcom/branches/corrections/package.tgz +# name: dk.fhir.ig.medcom-core +# version: 0.8.0 +# - +# name: hl7.fhir.uv.ips +# version: 0.3.0 #supported_resource_types: # - Patient diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index b502674..36774dc 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -36,8 +36,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { "spring.batch.job.enabled=false", - "spring.profiles.active=r5", - "spring.datasource.url=jdbc:h2:mem:dbr5", + "spring.profiles.active=r4", + "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.empi_enabled=true" }) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index a8b1981..9eea4d6 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -1,5 +1,9 @@ package ca.uhn.fhir.jpa.starter; +import static ca.uhn.fhir.util.TestUtil.waitForSize; +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; + import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; @@ -7,9 +11,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import ca.uhn.fhir.test.utilities.JettyUtil; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; +import java.net.URI; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; @@ -20,8 +24,6 @@ import org.hl7.fhir.r5.model.Observation; import org.hl7.fhir.r5.model.Patient; import org.hl7.fhir.r5.model.Subscription; import org.hl7.fhir.r5.model.SubscriptionTopic; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,15 +31,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.net.URI; -import java.nio.file.Paths; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import static ca.uhn.fhir.util.TestUtil.waitForSize; -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertEquals; - @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index fa29203..7b487b4 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -24,8 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; "spring.profiles.active=r4", "spring.datasource.url=jdbc:h2:mem:dbr4-mt", "hapi.fhir.subscription.websocket_enabled=true", - "hapi.fhir.subscription.websocket_enabled=true", - "hapi.fhir.partitioning_multitenancy_enabled" + "hapi.fhir.partitioning.partitioning_include_in_search_hashes=false" }) public class MultitenantServerR4IT { @@ -96,6 +95,7 @@ public class MultitenantServerR4IT { @BeforeEach void beforeEach() { + ourClientTenantInterceptor = new UrlTenantSelectionInterceptor(); ourCtx = FhirContext.forR4(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml index 2153cbb..038a343 100644 --- a/src/test/resources/application-integrationtest.yaml +++ b/src/test/resources/application-integrationtest.yaml @@ -7,7 +7,7 @@ spring: max-active: 15 profiles: ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 - active: dstu2 + active: r4 hapi: fhir: From de9a02994728fc4f2e43819a073cc0064957c1d9 Mon Sep 17 00:00:00 2001 From: jkv Date: Wed, 9 Sep 2020 00:43:41 +0200 Subject: [PATCH 19/22] import is sufficient --- src/main/java/ca/uhn/fhir/jpa/starter/Application.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 ba23124..083a3bf 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -14,12 +14,14 @@ import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = { JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) +@Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class,WebsocketDispatcherConfig.class }) public class Application extends SpringBootServletInitializer { public static void main(String[] args) { @@ -52,18 +54,12 @@ public class Application extends SpringBootServletInitializer { return servletRegistrationBean; } - @Bean public ServletRegistrationBean overlayRegistrationBean() { AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext(); annotationConfigWebApplicationContext.register(FhirTesterConfig.class); - annotationConfigWebApplicationContext.register(SubscriptionSubmitterConfig.class); - annotationConfigWebApplicationContext.register(SubscriptionProcessorConfig.class); - annotationConfigWebApplicationContext.register(SubscriptionChannelConfig.class); - annotationConfigWebApplicationContext.register(WebsocketDispatcherConfig.class); - DispatcherServlet dispatcherServlet = new DispatcherServlet( annotationConfigWebApplicationContext); dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class); From ec878a9205859447c69506c36ca1fe1236b5732a Mon Sep 17 00:00:00 2001 From: jvi Date: Wed, 9 Sep 2020 11:30:01 +0200 Subject: [PATCH 20/22] Added partition interceptor --- src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java | 5 ++++- .../ca/uhn/fhir/jpa/empi/EmpiConfigCondition.java | 13 +++++++++++++ .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 6 +++--- .../java/ca/uhn/fhir/jpa/starter/Application.java | 3 ++- .../uhn/fhir/jpa/starter/MultitenantServerR4IT.java | 1 + 5 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfigCondition.java 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 6b8f2d2..fd6e5c8 100644 --- a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java @@ -6,7 +6,9 @@ import ca.uhn.fhir.empi.rules.config.EmpiSettings; import ca.uhn.fhir.jpa.starter.AppProperties; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; @@ -18,10 +20,11 @@ import java.io.IOException; * in 5.1.0 picks this up even if EMPI is disabled currently. */ @Configuration +@Conditional(EmpiConfigCondition.class) public class EmpiConfig { @Bean - IEmpiSettings empiSettings(EmpiRuleValidator theEmpiRuleValidator, AppProperties appProperties) throws IOException { + IEmpiSettings empiSettings(@Autowired 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); diff --git a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfigCondition.java new file mode 100644 index 0000000..4854bde --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfigCondition.java @@ -0,0 +1,13 @@ +package ca.uhn.fhir.jpa.empi; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class EmpiConfigCondition implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { + String property = conditionContext.getEnvironment().getProperty("hapi.fhir.empi_enabled"); + return Boolean.parseBoolean(property); + } +} 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 fd22023..2835656 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -36,9 +36,9 @@ public class AppProperties { private Boolean expunge_enabled = true; private Boolean fhirpath_interceptor_enabled = false; private Boolean filter_search_enabled = true; - private Boolean graphql_enabled = true; - private Boolean binary_storage_enabled = true; - private Boolean bulk_export_enabled = true; + private Boolean graphql_enabled = false; + private Boolean binary_storage_enabled = false; + private Boolean bulk_export_enabled = false; private Boolean default_pretty_print = true; private Integer default_page_size = 20; private Integer max_binary_size = null; 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 083a3bf..3670b37 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.starter; +import ca.uhn.fhir.jpa.empi.EmpiConfig; import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; @@ -21,7 +22,7 @@ import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = { JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") @SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) -@Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class,WebsocketDispatcherConfig.class }) +@Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, EmpiConfig.class}) public class Application extends SpringBootServletInitializer { public static void main(String[] args) { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 7b487b4..856ad70 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -102,5 +102,6 @@ public class MultitenantServerR4IT { String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); + ourClient.registerInterceptor(ourClientTenantInterceptor); } } From ae97eabdfcbfa8edfb8904690c65baeec9b15da4 Mon Sep 17 00:00:00 2001 From: jvi Date: Wed, 9 Sep 2020 11:49:54 +0200 Subject: [PATCH 21/22] Added beans to complete the required graph --- .../java/ca/uhn/fhir/jpa/empi/EmpiConfig.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 fd6e5c8..3fb9152 100644 --- a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java @@ -1,13 +1,18 @@ package ca.uhn.fhir.jpa.empi; +import ca.uhn.fhir.context.FhirContext; 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.empi.svc.EmpiSearchParamSvc; import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.DefaultResourceLoader; @@ -23,6 +28,17 @@ import java.io.IOException; @Conditional(EmpiConfigCondition.class) public class EmpiConfig { + @Bean + EmpiRuleValidator empiRuleValidator(FhirContext theFhirContext, ISearchParamRetriever theSearchParamRetriever) { + return new EmpiRuleValidator(theFhirContext, theSearchParamRetriever); + } + + @Bean + EmpiSearchParamSvc empiSearchParamSvc() { + return new EmpiSearchParamSvc(); + } + + @Bean IEmpiSettings empiSettings(@Autowired EmpiRuleValidator theEmpiRuleValidator, AppProperties appProperties) throws IOException { DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); From ebe04d881ac31159533089028c91b813200cfd29 Mon Sep 17 00:00:00 2001 From: jvi Date: Thu, 10 Sep 2020 23:07:22 +0200 Subject: [PATCH 22/22] someone owes me a beer ... or twenty --- src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java | 13 ++++--------- .../java/ca/uhn/fhir/jpa/starter/Application.java | 2 +- .../ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java | 4 +++- 3 files changed, 8 insertions(+), 11 deletions(-) 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 3fb9152..66317fc 100644 --- a/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/empi/EmpiConfig.java @@ -4,17 +4,17 @@ import ca.uhn.fhir.context.FhirContext; 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.empi.svc.EmpiSearchParamSvc; +import ca.uhn.fhir.jpa.empi.config.EmpiConsumerConfig; +import ca.uhn.fhir.jpa.empi.config.EmpiSubmitterConfig; import ca.uhn.fhir.jpa.starter.AppProperties; import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; @@ -26,6 +26,7 @@ import java.io.IOException; */ @Configuration @Conditional(EmpiConfigCondition.class) +@Import({EmpiConsumerConfig.class, EmpiSubmitterConfig.class}) public class EmpiConfig { @Bean @@ -33,12 +34,6 @@ public class EmpiConfig { return new EmpiRuleValidator(theFhirContext, theSearchParamRetriever); } - @Bean - EmpiSearchParamSvc empiSearchParamSvc() { - return new EmpiSearchParamSvc(); - } - - @Bean IEmpiSettings empiSettings(@Autowired EmpiRuleValidator theEmpiRuleValidator, AppProperties appProperties) throws IOException { DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); 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 3670b37..b0aa670 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -21,7 +21,7 @@ import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = { JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") -@SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) +@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}, scanBasePackages = {"ca.uhn.fhir.jpa.starter"}) @Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, EmpiConfig.class}) public class Application extends SpringBootServletInitializer { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 36774dc..dbcfff4 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -39,7 +39,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; "spring.profiles.active=r4", "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.subscription.websocket_enabled=true", - "hapi.fhir.empi_enabled=true" + "hapi.fhir.empi_enabled=true", + //Override is currently required when using Empi as the construction of the Empi beans are ambiguous as they are constructed multiple places. This is evident when running in a spring boot environment + "spring.main.allow-bean-definition-overriding=true" }) public class ExampleServerR4IT {