From 63606607b0d5d2d440070029a688dfe32f8db8a2 Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 17 Aug 2020 13:04:00 +0200 Subject: [PATCH 01/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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 { From 9de4f1b248b5f4f25f6fa07c10b83505bdf5bedc Mon Sep 17 00:00:00 2001 From: James Agnew Date: Mon, 14 Sep 2020 05:43:38 -0400 Subject: [PATCH 23/30] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 25464fd..838bef0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ This project is a complete starter project you can use to deploy a FHIR server u Note that this project is specifically intended for end users of the HAPI FHIR JPA server module (in other words, it helps you implement HAPI FHIR, it is not the source of the library itself). If you are looking for the main HAPI FHIR project, see here: https://github.com/jamesagnew/hapi-fhir +Need Help? Please see: https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help + ## Prerequisites In order to use this sample, you should have: From 2979aca07d7a786b8f902d42fc4763720d38288c Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Thu, 17 Sep 2020 05:46:42 -0400 Subject: [PATCH 24/30] Enable terminology uploader by default --- .../fhir/jpa/starter/BaseJpaRestfulServer.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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 814395f..2f7c044 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -16,6 +16,8 @@ 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.SubscriptionTriggeringProvider; +import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; 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,6 +37,7 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; import com.google.common.base.Strings; import org.hl7.fhir.r4.model.Bundle.BundleType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; @@ -95,6 +98,9 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired AppProperties appProperties; + @Autowired + ApplicationContext myApplicationContext; + public BaseJpaRestfulServer() { } @@ -236,16 +242,14 @@ public class BaseJpaRestfulServer extends RestfulServer { * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor * with this feature. */ - if (false) { // <-- DISABLED RIGHT NOW - //registerProvider(appCtx.getBean(TerminologyUploaderProvider.class)); + if (ctx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW + registerProvider(myApplicationContext.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 - .getBean(SubscriptionTriggeringProvider.class); - registerProvider(retriggeringProvider);*/ + if (true) { // <-- ENABLED RIGHT NOW + registerProvider(myApplicationContext.getBean(SubscriptionTriggeringProvider.class)); } // Define your CORS configuration. This is an example From c7d5716ffbf3d6d41fca28c11b641a22c8e015cd Mon Sep 17 00:00:00 2001 From: jvi Date: Fri, 18 Sep 2020 18:29:12 +0200 Subject: [PATCH 25/30] Removing dialect as it is calculated by hibernate --- src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 036f2be..4dbc122 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -14,8 +14,8 @@ 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"); From 58efcffd8140ee30b05e4d27a7cf5ceab0c69d75 Mon Sep 17 00:00:00 2001 From: jvi Date: Fri, 18 Sep 2020 22:56:48 +0200 Subject: [PATCH 26/30] Updated documentation Removed unnecessary scanning Corrected context paths --- README.md | 178 ++++++++++++------ .../ca/uhn/fhir/jpa/starter/Application.java | 8 +- .../jpa/starter/ExampleServerDstu2IT.java | 2 +- .../jpa/starter/ExampleServerDstu3IT.java | 4 +- .../fhir/jpa/starter/ExampleServerR4IT.java | 4 +- .../fhir/jpa/starter/ExampleServerR5IT.java | 4 +- .../jpa/starter/MultitenantServerR4IT.java | 2 +- 7 files changed, 134 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 838bef0..ffe6612 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,13 @@ Need Help? Please see: https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help In order to use this sample, you should have: - [This project](https://github.com/hapifhir/hapi-fhir-jpaserver-starter) checked out. You may wish to create a GitHub Fork of the project and check that out instead so that you can customize the project and save the results to GitHub. -- Oracle Java (JDK) installed: Minimum JDK8 or newer. -- Apache Maven build tool (newest version) + +### and either + - Oracle Java (JDK) installed: Minimum JDK8 or newer. + - Apache Maven build tool (newest version) + +### or + - Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) orr used directly from [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) ## Running via [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) @@ -20,26 +25,26 @@ Each tagged/released version of `hapi-fhir-jpaserver` is built as a Docker image ``` docker pull hapiproject/hapi:latest -docker run -p 8080:8080 hapiproject/hapi:tagname +docker run -p 8080:8080 -e "spring.batch.job.enabled=false" hapiproject/hapi:tagname ``` -This will run the docker image with the default configuration, mapping port 8080 from the container to port 8080 in the host. Once running, you can access `http://localhost:8080/hapi-fhir-jpaserver/fhir` in the browser to access the HAPI FHIR server's UI. +This will run the docker image with the default configuration, mapping port 8080 from the container to port 8080 in the host. Once running, you can access `http://localhost:8080/hapi-fhir-jpaserver/` in the browser to access the HAPI FHIR server's UI. -If you change the mapped port, you need to change the configuration used by HAPI to have the correct `server_address` property/value. +If you change the mapped port, you need to change the configuration used by HAPI to have the correct `hapi.fhir.tester` property/value. ### Configuration via environment variables You can customize HAPI directly from the `run` command using environment variables. For example: -`docker run -p 8090:8080 -e server_address=http://localhost:8090/hapi-fhir-jpaserver/fhir hapiproject/hapi:tagname` +`docker run -p 8080:8080 -e hapi.fhir.default_encoding=xml hapiproject/hapi:tagname` -HAPI looks in the environment variables for properties in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file. +HAPI looks in the environment variables for properties in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file for defaults. -### Configuration via overridden hapi.properties file +### Configuration via overridden application.yaml file -You can customize HAPI by telling HAPI to look for the `hapi.properties` file in a different location: +You can customize HAPI by telling HAPI to look for the configuration file in a different location, eg.: -`docker run -p 8090:8080 -e hapi.properties=/some/directory/with/hapi.properties hapiproject/hapi:tagname` +`docker run -p 8090:8080 -e "--spring.config.location=classpath:/another.application.yaml" hapiproject/hapi:tagname` ### Example docker-compose.yml @@ -52,11 +57,11 @@ services: - "8090:8080" configs: - source: hapi - target: /data/hapi/hapi.properties + target: /data/hapi/application.yaml volumes: - hapi-data:/data/hapi environment: - JAVA_OPTS: '-Dhapi.properties=/data/hapi/hapi.properties' + JAVA_OPTS: '-Dhapi.properties=/data/hapi/application.yaml' configs: hapi: external: true @@ -67,15 +72,13 @@ volumes: ## Running locally -The easiest way to run this server is to run it directly in Maven using a built-in Jetty server. To do this, change `src/main/resources/hapi.properties` `server_address` and `server.base` with the values commented out as _For Jetty, use this_ and then execute the following command: +The easiest way to run this server entirely depends on your environment requirements. At least, the following 4 ways are supported: +### Using jetty ```bash -mvn jetty:run +mvn jetty:run -Dspring.batch.job.enabled=false ``` -Then, browse to the following link to use the server: - -[http://localhost:8080/hapi-fhir-jpaserver/](http://localhost:8080/hapi-fhir-jpaserver/) If you need to run this server on a different port (using Maven), you can change the port in the run command as follows: @@ -83,43 +86,98 @@ If you need to run this server on a different port (using Maven), you can change mvn -Djetty.port=8888 jetty:run ``` -And replacing 8888 with the port of your choice. +Server will then be accessible at http://localhost:8888/ and eg. http://localhost:8888/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. + +```yaml + tester: + - + id: home + name: Local Tester + server_address: 'http://localhost:8888/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 +``` + + + +### Using Spring Boot +```bash +mvn clean package spring-boot:repackage -Pboot && java -jar target/hapi-fhir-jpaserver.war +``` +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. + +```yaml + tester: + - + id: home + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 +``` +### Using Spring Boot and Google distroless +```bash +mvn clean package com.google.cloud.tools:jib-maven-plugin:dockerBuild -Dimage=distroless-hapi && docker run -p 8080:8080 -e spring.batch.job.enabled=false distroless-hapi +``` +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. + +```yaml + tester: + - + id: home + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 +``` + +### Using the Dockerfile and multistage build +```bash +./build-docker-image.sh && docker run -p 8080:8080 -e "spring.batch.job.enabled=false" hapi-fhir/hapi-fhir-jpaserver-starter:latest +``` +Server will then be accessible at http://localhost:8080/hapi-fhir-jpaserver and eg. http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. + +```yaml + 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 +``` ## Configurations -Much of this HAPI starter project can be configured using the properties file in _src/main/resources/hapi.properties_. By default, this starter project is configured to use Derby as the database. +Much of this HAPI starter project can be configured using the yaml file in _src/main/resources/application.yaml_. By default, this starter project is configured to use H2 as the database. ### MySql configuration -To configure the starter app to use MySQL, instead of the default Derby, update the hapi.properties file to have the following: +To configure the starter app to use MySQL, instead of the default H2, update the application.yaml file to have the following: -- datasource.driver=com.mysql.jdbc.Driver -- datasource.url=jdbc:mysql://localhost:3306/hapi_dstu3 -- hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -- datasource.username=admin -- datasource.password=admin +```yaml +spring: + datasource: + url: 'jdbc:mysql://localhost:3306/hapi_dstu3' + username: admin + password: admin + driverClassName: com.mysql.jdbc.Driver +``` ### PostgreSQL configuration -To configure the starter app to use PostgreSQL, instead of the default Derby, update the hapi.properties file to have the following: +To configure the starter app to use PostgreSQL, instead of the default H2, update the application.yaml file to have the following: -- datasource.driver=org.postgresql.Driver -- datasource.url=jdbc:postgresql://localhost:5432/hapi_dstu3 -- hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect -- datasource.username=admin -- datasource.password=admin +```yaml +spring: + datasource: + url: 'jdbc:postgresql://localhost:5432/hapi_dstu3' + username: admin + password: admin + driverClassName: org.postgresql.Driver +``` -Because the integration tests within the project rely on the default Derby database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. - -It is important to use PostgreSQL95Dialect when using PostgreSQL version 10+. - -## Overriding application properties - -You can override the properties that are loaded into the compiled web app (.war file) making a copy of the hapi.properties file on the file system, making changes to it, and then setting the JAVA_OPTS environment variable on the tomcat server to tell hapi-jpaserver-starter where the overriding properties file is. For example: - -`-Dhapi.properties=/some/custom/directory/hapi.properties` - -Note: This property name and the path is case-sensitive. "-DHAPI.PROPERTIES=XXX" will not work. +Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. ## Customizing The Web Testpage UI @@ -129,7 +187,7 @@ The UI is customized using [Thymeleaf](https://www.thymeleaf.org/) template file Several template files that can be customized are found in the following directory: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates) -## Deploying to a Container +## Deploying to an Application Server Using the Maven-Embedded Jetty method above is convenient, but it is not a good solution if you want to leave the server running in the background. @@ -149,6 +207,8 @@ Again, browse to the following link to use the server (note that the port 8080 m [http://localhost:8080/hapi-fhir-jpaserver/](http://localhost:8080/hapi-fhir-jpaserver/) +If you would like it to be hosted at the root, eg. http://localhost:8080/ - then rename the WAR file to ```ROOT.war```. + ## Deploy with docker compose Docker compose is a simple option to build and deploy container. To deploy with docker compose, you should build the project @@ -158,14 +218,20 @@ reached at http://localhost:8080/hapi-fhir-jpaserver/. In order to use another port, change the `ports` parameter inside `docker-compose.yml` to `8888:8080`, where 8888 is a port of your choice. -The docker compose set also includes my MySQL database, if you choose to use MySQL instead of derby, change the following -properties in hapi.properties: +The docker compose set also includes my MySQL database, if you choose to use MySQL instead of H2, change the following +properties in application.yaml: -- datasource.driver=com.mysql.jdbc.Driver -- datasource.url=jdbc:mysql://hapi-fhir-mysql:3306/hapi -- hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -- datasource.username=admin -- datasource.password=admin +```yaml +spring: + datasource: + url: 'jdbc:mysql://hapi-fhir-mysql:3306/hapi' + username: admin + password: admin + driverClassName: com.mysql.jdbc.Driver +``` + +## Running hapi-fhir-jpaserver direclty from IntelliJ as Spring Boot +Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers. ## Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ @@ -203,21 +269,21 @@ It is important to use MySQL5Dialect when using MySQL version 5+. ## Enabling Subscriptions -The server may be configured with subscription support by enabling properties in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file: +The server may be configured with subscription support by enabling properties in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file: -- `subscription.resthook.enabled` - Enables REST Hook subscriptions, where the server will make an outgoing connection to a remote REST server +- `hapi.fhir.subscription.resthook.enabled` - Enables REST Hook subscriptions, where the server will make an outgoing connection to a remote REST server -- `subscription.email.enabled` - Enables email subscriptions. Note that you must also provide the connection details for a usable SMTP server. +- `hapi.fhir.subscription.email.*` - Enables email subscriptions. Note that you must also provide the connection details for a usable SMTP server. -- `subscription.websocket.enabled` - Enables websocket subscriptions. With this enabled, your server will accept incoming websocket connections on the following URL (this example uses the default context path and port, you may need to tweak depending on your deployment environment): [ws://localhost:8080/hapi-fhir-jpaserver/websocket](ws://localhost:8080/hapi-fhir-jpaserver/websocket) +- `hapi.fhir.subscription.websocket.enabled` - Enables websocket subscriptions. With this enabled, your server will accept incoming websocket connections on the following URL (this example uses the default context path and port, you may need to tweak depending on your deployment environment): [ws://localhost:8080/hapi-fhir-jpaserver/websocket](ws://localhost:8080/hapi-fhir-jpaserver/websocket) ## Enabling EMPI -Set `empi.enabled=true` in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file to enable EMPI on this server. The EMPI matching rules are configured in [empi-rules.json](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/empi-rules.json). The rules in this example file should be replaced with actual matching rules appropriate to your data. Note that EMPI relies on subscriptions, so for EMPI to work, subscriptions must be enabled. +Set `hapi.fhir.empi_enabled=true` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable EMPI on this server. The EMPI matching rules are configured in [empi-rules.json](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/empi-rules.json). The rules in this example file should be replaced with actual matching rules appropriate to your data. Note that EMPI relies on subscriptions, so for EMPI to work, subscriptions must be enabled. ## Using Elasticsearch -By default, the server will use embedded lucene indexes for terminology and fulltext indexing purposes. You can switch this to using lucene by editing the properties in [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) +By default, the server will use embedded lucene indexes for terminology and fulltext indexing purposes. You can switch this to using lucene by editing the properties in [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) For example: 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 b0aa670..fab5481 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -20,8 +20,8 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = { - JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") -@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}, scanBasePackages = {"ca.uhn.fhir.jpa.starter"}) + JpaRestfulServer.class}) +@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}) @Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, EmpiConfig.class}) public class Application extends SpringBootServletInitializer { @@ -49,7 +49,7 @@ public class Application extends SpringBootServletInitializer { JpaRestfulServer jpaRestfulServer = new JpaRestfulServer(); beanFactory.autowireBean(jpaRestfulServer); servletRegistrationBean.setServlet(jpaRestfulServer); - servletRegistrationBean.addUrlMappings("/hapi-fhir-jpaserver/fhir/*"); + servletRegistrationBean.addUrlMappings("/fhir/*"); servletRegistrationBean.setLoadOnStartup(1); return servletRegistrationBean; @@ -68,7 +68,7 @@ public class Application extends SpringBootServletInitializer { ServletRegistrationBean registrationBean = new ServletRegistrationBean(); registrationBean.setServlet(dispatcherServlet); - registrationBean.addUrlMappings("/hapi-fhir-jpaserver/*", "/*"); + registrationBean.addUrlMappings("/*"); registrationBean.setLoadOnStartup(1); return registrationBean; 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 aeab8d7..b99ea65 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -50,7 +50,7 @@ public class ExampleServerDstu2IT { ourCtx = FhirContext.forDstu2(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } 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 208ca01..ca1cbf1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -92,7 +92,7 @@ public class ExampleServerDstu3IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -127,7 +127,7 @@ public class ExampleServerDstu3IT { ourCtx = FhirContext.forDstu3(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } 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 dbcfff4..6fc36b3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -119,7 +119,7 @@ public class ExampleServerR4IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -159,7 +159,7 @@ public class ExampleServerR4IT { ourCtx = FhirContext.forR4(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/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 9eea4d6..3a52ec7 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -97,7 +97,7 @@ public class ExampleServerR5IT { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); + URI echoUri = new URI("ws://localhost:" + port + "/websocket"); ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); @@ -129,7 +129,7 @@ public class ExampleServerR5IT { ourCtx = FhirContext.forR5(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); } 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 856ad70..66fb4df 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -99,7 +99,7 @@ public class MultitenantServerR4IT { ourCtx = FhirContext.forR4(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); - String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; + String ourServerBase = "http://localhost:" + port + "/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(ourClientTenantInterceptor); From e24af07f0988f843d496215c0232f368938cf564 Mon Sep 17 00:00:00 2001 From: jvi Date: Fri, 18 Sep 2020 23:00:04 +0200 Subject: [PATCH 27/30] spelling --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffe6612..8a39fba 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ In order to use this sample, you should have: - Apache Maven build tool (newest version) ### or - - Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) orr used directly from [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) + - Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) or used directly from [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) ## Running via [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) From ee337296eeb1adbe4faf21e295d55757767009bf Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen <46567685+jvitrifork@users.noreply.github.com> Date: Mon, 21 Sep 2020 19:19:10 +0200 Subject: [PATCH 28/30] =?UTF-8?q?Renamed=20deployable=20war=20to=20ROOT=20?= =?UTF-8?q?in=20order=20to=20homogenize=20urls=20regardless=E2=80=A6=20(#1?= =?UTF-8?q?41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Renamed deployable war to ROOT in order to homogenize urls regardless of deployment method * Made Maven quite when doing downloading dependencies --- Dockerfile | 4 ++-- README.md | 4 ++-- pom.xml | 16 ++++++++-------- src/main/resources/application.yaml | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6ae7213..a6699d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,12 +2,12 @@ FROM maven:3.6.3-jdk-11-slim as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter COPY pom.xml . -RUN mvn dependency:go-offline +RUN mvn -ntp dependency:go-offline COPY src/ /tmp/hapi-fhir-jpaserver-starter/src/ RUN mvn clean install -DskipTests -FROM tomcat:9.0.37-jdk11-openjdk-slim-buster +FROM tomcat:9.0.38-jdk11-openjdk-slim-buster RUN mkdir -p /data/hapi/lucenefiles && chmod 775 /data/hapi/lucenefiles COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/tomcat/webapps/ diff --git a/README.md b/README.md index 8a39fba..b9b2aca 100644 --- a/README.md +++ b/README.md @@ -135,14 +135,14 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos ```bash ./build-docker-image.sh && docker run -p 8080:8080 -e "spring.batch.job.enabled=false" hapi-fhir/hapi-fhir-jpaserver-starter:latest ``` -Server will then be accessible at http://localhost:8080/hapi-fhir-jpaserver and eg. http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. ```yaml tester: - id: home name: Local Tester - server_address: 'http://localhost:8080/hapi-fhir-jpaserver/fhir' + server_address: 'http://localhost:8080/fhir' refuse_to_fetch_third_party_urls: false fhir_version: R4 ``` diff --git a/pom.xml b/pom.xml index 0e66d1c..e17c0cc 100644 --- a/pom.xml +++ b/pom.xml @@ -21,11 +21,11 @@ 8 - 2.3.3.RELEASE + 2.3.4.RELEASE - 3.6.0 + 3.6.3 war @@ -269,7 +269,7 @@ org.springframework.boot spring-boot-autoconfigure - ${spring.boot} + ${spring_boot_version} @@ -289,7 +289,7 @@ org.springframework.boot spring-boot-starter-test - ${spring.boot} + ${spring_boot_version} test @@ -298,8 +298,8 @@ - - hapi-fhir-jpaserver + + ROOT @@ -495,7 +495,7 @@ org.springframework.boot spring-boot-starter-web - 2.3.3.RELEASE + ${spring_boot_version} @@ -508,7 +508,7 @@ org.springframework.boot spring-boot-starter-web - 2.3.3.RELEASE + ${spring_boot_version} org.springframework.boot diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7a91683..96bb062 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -86,7 +86,7 @@ hapi: - id: home name: Local Tester - server_address: 'http://localhost:8080/hapi-fhir-jpaserver/fhir' + server_address: 'http://localhost:8080/fhir' refuse_to_fetch_third_party_urls: false fhir_version: R4 - From 85e9fc725ad18ba1c0dd10330e4d6e3b255d7541 Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Tue, 22 Sep 2020 19:39:28 +0300 Subject: [PATCH 29/30] Update README.md (#143) The rename from hapi-fhir-jpaserver to ROOT as per ee337296eeb1adbe4faf21e295d55757767009bf requires that the new war file is specified which is now ROOT.war --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9b2aca..d028bd7 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Server will then be accessible at http://localhost:8888/ and eg. http://localhos ### Using Spring Boot ```bash -mvn clean package spring-boot:repackage -Pboot && java -jar target/hapi-fhir-jpaserver.war +mvn clean package spring-boot:repackage -Pboot && java -jar target/ROOT.war ``` Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. From a62de8249507b710ac93a4289ae1068ea4f4e476 Mon Sep 17 00:00:00 2001 From: Sean McIlvenna Date: Tue, 22 Sep 2020 16:05:23 -0700 Subject: [PATCH 30/30] Setting `batch.job.enabled` to `false` by default, since HAPI won't launch on its own without it. Updating the README.md to have the correct example externalized configs in a docker-compose file --- README.md | 2 +- src/main/resources/application.yaml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d028bd7..774af56 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ services: volumes: - hapi-data:/data/hapi environment: - JAVA_OPTS: '-Dhapi.properties=/data/hapi/application.yaml' + SPRING_CONFIG_LOCATION: 'file:///data/hapi/application.yaml' configs: hapi: external: true diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 96bb062..b7ec776 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -24,6 +24,10 @@ spring: hibernate.search.default.indexBase: target/lucenefiles hibernate.search.lucene_version: LUCENE_CURRENT + batch: + job: + enabled: false + hapi: fhir: defer_indexing_for_codesystems_of_size: 101