Merge branch 'master' into rel_4_1_0

This commit is contained in:
James Agnew
2019-11-12 22:37:34 -05:00
13 changed files with 731 additions and 319 deletions

5
.editorconfig Normal file
View File

@@ -0,0 +1,5 @@
[*.java]
charset = utf-8
indent_style = space
indent_size = 2

138
.gitignore vendored
View File

@@ -1,7 +1,6 @@
target/
.idea/
*.iml
*.orig *.orig
target/
*.iml
# Compiled class file # Compiled class file
*.class *.class
@@ -26,3 +25,136 @@ target/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid* hs_err_pid*
### Windows template
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# CMake
cmake-build-*/
# File-based project format
*.iws
# IntelliJ
out/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Eclipse template
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View File

@@ -1,4 +1,23 @@
# Using maven with JDK 8
FROM maven:3.6.1-jdk-8 AS build
# Copy pom and download dependencies. This is done here
# so that docker caches the dependencies and they don't have to be
# re-downloaded on the next run, unless the pom file changes.
COPY pom.xml .
RUN /usr/local/bin/mvn-entrypoint.sh mvn verify clean --fail-never
# Copy all of the source code to the image and build it
COPY . .
RUN mvn package
FROM jetty:9-jre8-alpine FROM jetty:9-jre8-alpine
COPY --from=build ./target/hapi-fhir-jpaserver.war /var/lib/jetty/webapps/hapi-fhir-jpaserver.war
# Copy the default config file to the config directory location. It might be overridden by the docker host.
COPY --from=build ./src/main/resources/hapi.properties /hapi-config/hapi.properties
USER jetty:jetty USER jetty:jetty
ADD ./target/hapi-fhir-jpaserver.war /var/lib/jetty/webapps/hapi-fhir-jpaserver.war
EXPOSE 8080 EXPOSE 8080
CMD ["java","-Dhapi.properties=/hapi-config/hapi.properties","-jar","/usr/local/jetty/start.jar"]

View File

@@ -2,6 +2,8 @@
This project is a complete starter project you can use to deploy a FHIR server using HAPI FHIR JPA. This project is a complete starter project you can use to deploy a FHIR server using HAPI FHIR JPA.
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
# Prerequisites # Prerequisites
In order to use this sample, you should have: In order to use this sample, you should have:
@@ -39,6 +41,8 @@ To configure the starter app to use MySQL, instead of the default Derby, update
* datasource.driver=com.mysql.jdbc.Driver * datasource.driver=com.mysql.jdbc.Driver
* datasource.url=jdbc:mysql://localhost:3306/hapi_dstu3 * datasource.url=jdbc:mysql://localhost:3306/hapi_dstu3
* hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect * hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
* datasource.username=admin
* datasource.password=admin
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 MySQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. 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 MySQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure.
@@ -72,6 +76,24 @@ 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/) [http://localhost:8080/hapi-fhir-jpaserver/](http://localhost:8080/hapi-fhir-jpaserver/)
# 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
with ```mvn clean install``` and then bring up the containers with ```docker-compose up -d --build```. The server can be
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:
* 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
# Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ # Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ
Install Tomcat. Install Tomcat.

1
build-docker-image.bat Normal file
View File

@@ -0,0 +1 @@
docker build -t hapi-fhir/hapi-fhir-jpaserver-starter .

View File

@@ -1,5 +1,4 @@
#!/bin/sh #!/bin/sh
mvn package && \
docker build -t hapi-fhir/hapi-fhir-jpaserver-starter . docker build -t hapi-fhir/hapi-fhir-jpaserver-starter .

21
docker-compose.yml Normal file
View File

@@ -0,0 +1,21 @@
version: "3"
services:
hapi-fhir-jpaserver-start:
build: .
container_name: hapi-fhir-jpaserver-start
restart: on-failure
ports:
- "8080:8080"
hapi-fhir-mysql:
image: mysql:latest
container_name: hapi-fhir-mysql
restart: always
environment:
MYSQL_DATABASE: 'hapi'
MYSQL_USER: 'admin'
MYSQL_PASSWORD: 'admin'
MYSQL_ROOT_PASSWORD: 'admin'
volumes:
- hapi-fhir-mysql:/var/lib/mysql
volumes:
hapi-fhir-mysql:

View File

@@ -15,6 +15,11 @@
</parent> </parent>
<artifactId>hapi-fhir-jpaserver-starter</artifactId> <artifactId>hapi-fhir-jpaserver-starter</artifactId>
<prerequisites>
<maven>3.5.0</maven>
</prerequisites>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.eclipse.jetty.websocket</groupId> <groupId>org.eclipse.jetty.websocket</groupId>
@@ -29,7 +34,7 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version> <version>8.0.11</version>
</dependency> </dependency>
<!-- Needed for Email subscriptions --> <!-- Needed for Email subscriptions -->

View File

@@ -12,27 +12,17 @@
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<<<<<<< HEAD <<<<<<< HEAD
<version>3.7.0</version> <version>4.1.0</version>
======= =======
<version>3.7.0-SNAPSHOT</version> <version>4.0.3</version>
>>>>>>> 18c85900e500863b2b24080da9fe5e11c6d0a434 >>>>>>> master
</parent> </parent>
<groupId>ca.uhn.hapi.fhir.demo</groupId>
<artifactId>hapi-fhir-jpaserver-starter</artifactId> <artifactId>hapi-fhir-jpaserver-starter</artifactId>
<packaging>war</packaging>
<name>HAPI FHIR JPA Server - Starter Project</name> <prerequisites>
<maven>3.5.0</maven>
<repositories> </prerequisites>
<repository>
<id>oss-snapshots</id>
<snapshots>
<enabled>true</enabled>
</snapshots>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -48,9 +38,27 @@
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version> <version>8.0.11</version>
</dependency> </dependency>
<!-- Needed for Email subscriptions -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<exclusions>
<exclusion>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
</dependency>
-->
<!-- This dependency includes the core HAPI-FHIR classes --> <!-- This dependency includes the core HAPI-FHIR classes -->
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
@@ -58,24 +66,21 @@
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!-- At least one "structures" JAR must also be included -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>${project.version}</version>
</dependency>
<!-- This dependency includes the JPA server itself, which is packaged separately from the rest of HAPI FHIR --> <!-- This dependency includes the JPA server itself, which is packaged separately from the rest of HAPI FHIR -->
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId> <artifactId>hapi-fhir-jpaserver-base</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> <exclusions>
<exclusion>
<dependency> <groupId>org.springframework</groupId>
<groupId>ca.uhn.hapi.fhir</groupId> <artifactId>spring-jcl</artifactId>
<artifactId>hapi-fhir-jpaserver-elasticsearch</artifactId> </exclusion>
<version>${project.version}</version> <exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- This dependency is used for the "FHIR Tester" web app overlay --> <!-- This dependency is used for the "FHIR Tester" web app overlay -->
@@ -115,17 +120,6 @@
</dependency> </dependency>
<!-- Used for CORS support --> <!-- Used for CORS support -->
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring Web is used to deploy the server to a web container. --> <!-- Spring Web is used to deploy the server to a web container. -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
@@ -136,21 +130,61 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId> <artifactId>commons-dbcp2</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- This example uses Derby embedded database. If you are using another database such as Mysql or Oracle, you may omit the following dependencies and replace them with an appropriate database client <!-- This example uses H2 embedded database. If you are using another database such as Mysql or Oracle, you may omit the following dependencies and replace them with an appropriate database client
dependency for your database platform. --> dependency for your database platform. -->
<dependency> <dependency>
<groupId>org.apache.derby</groupId> <groupId>com.h2database</groupId>
<artifactId>derby</artifactId> <artifactId>h2</artifactId>
</dependency>
<!-- webjars -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.derby</groupId> <groupId>org.webjars</groupId>
<artifactId>derbynet</artifactId> <artifactId>Eonasdan-bootstrap-datetimepicker</artifactId>
<version>4.17.43</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.derby</groupId> <groupId>org.webjars</groupId>
<artifactId>derbyclient</artifactId> <artifactId>font-awesome</artifactId>
<version>5.8.2</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>awesome-bootstrap-checkbox</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jstimezonedetect</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>select2</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>moment</artifactId>
<version>2.15.1</version>
</dependency> </dependency>
<!-- The following dependencies are only needed for automated unit tests, you do not neccesarily need them to run the example. --> <!-- The following dependencies are only needed for automated unit tests, you do not neccesarily need them to run the example. -->
@@ -184,6 +218,7 @@
<artifactId>jetty-webapp</artifactId> <artifactId>jetty-webapp</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!--
<dependency> <dependency>
<groupId>com.helger</groupId> <groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId> <artifactId>ph-schematron</artifactId>
@@ -194,6 +229,7 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
-->
<!-- <!--
For some reason JavaDoc crashed during site generation unless we have this dependency For some reason JavaDoc crashed during site generation unless we have this dependency
@@ -204,16 +240,37 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-test-utilities</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<packaging>war</packaging>
<name>HAPI FHIR JPA Server - Starter Project</name>
<repositories>
<repository>
<id>oss-snapshots</id>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<build> <build>
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver.war --> <!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver.war -->
<finalName>hapi-fhir-jpaserver</finalName> <finalName>hapi-fhir-jpaserver</finalName>
<!-- The following is not required for the application to build, but allows you to test it by issuing "mvn jetty:run" from the command line. -->
<pluginManagement>
<plugins> <plugins>
<!-- The following is not required for the application to build, but allows you to test it by issuing "mvn jetty:run" from the command line. -->
<plugin> <plugin>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
@@ -225,10 +282,7 @@
</webApp> </webApp>
</configuration> </configuration>
</plugin> </plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- Tell Maven which Java source version you want to use --> <!-- Tell Maven which Java source version you want to use -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -259,15 +313,6 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- This plugin is just a part of the HAPI internal build process, you do not need to incude it in your own projects -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<!-- This is to run the integration tests --> <!-- This is to run the integration tests -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -285,6 +330,100 @@
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<inherited>true</inherited>
</execution>
</executions>
<configuration>
<failBuildInCaseOfConflict>true</failBuildInCaseOfConflict>
<checkTestClasspath>false</checkTestClasspath>
<!--
<printEqualFiles>false</printEqualFiles>
<failBuildInCaseOfDifferentContentConflict>true</failBuildInCaseOfDifferentContentConflict>
<failBuildInCaseOfEqualContentConflict>true</failBuildInCaseOfEqualContentConflict>
<failBuildInCaseOfConflict>true</failBuildInCaseOfConflict>
<checkCompileClasspath>true</checkCompileClasspath>
<checkRuntimeClasspath>false</checkRuntimeClasspath>
<skip>false</skip>
<quiet>false</quiet>
<preferLocal>true</preferLocal>
<useResultFile>true</useResultFile>
<resultFileMinClasspathCount>2</resultFileMinClasspathCount>
<resultFile>${project.build.directory}/duplicate-finder-result.xml</resultFile>
-->
<!--
<ignoredDependencies>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jscience</groupId>
<artifactId>jscience</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jcl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jcl</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
</dependency>
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-compat-qual</artifactId>
</dependency>
</ignoredDependencies>
-->
<ignoredResourcePatterns>
<ignoredResourcePattern>.*\.txt$</ignoredResourcePattern>
<ignoredResourcePattern>.*\.html$</ignoredResourcePattern>
</ignoredResourcePatterns>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@@ -28,6 +28,10 @@ public class FhirServerConfigCommon {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); 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 allowContainsSearches = HapiProperties.getAllowContainsSearches();
private Boolean allowMultipleDelete = HapiProperties.getAllowMultipleDelete(); private Boolean allowMultipleDelete = HapiProperties.getAllowMultipleDelete();
private Boolean allowExternalReferences = HapiProperties.getAllowExternalReferences(); private Boolean allowExternalReferences = HapiProperties.getAllowExternalReferences();
@@ -82,6 +86,10 @@ public class FhirServerConfigCommon {
public DaoConfig daoConfig() { public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig(); 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.setAllowContainsSearches(this.allowContainsSearches);
retVal.setAllowMultipleDelete(this.allowMultipleDelete); retVal.setAllowMultipleDelete(this.allowMultipleDelete);
retVal.setAllowExternalReferences(this.allowExternalReferences); retVal.setAllowExternalReferences(this.allowExternalReferences);

View File

@@ -20,7 +20,11 @@ import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.*;
public class HapiProperties { public class HapiProperties {
public static final String BINARY_STORAGE_ENABLED = "binary_storage.enabled"; 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_EXTERNAL_REFERENCES = "allow_external_references";
static final String ALLOW_MULTIPLE_DELETE = "allow_multiple_delete"; static final String ALLOW_MULTIPLE_DELETE = "allow_multiple_delete";
static final String ALLOW_PLACEHOLDER_REFERENCES = "allow_placeholder_references"; static final String ALLOW_PLACEHOLDER_REFERENCES = "allow_placeholder_references";
@@ -49,6 +53,7 @@ public class HapiProperties {
static final String SUBSCRIPTION_EMAIL_ENABLED = "subscription.email.enabled"; static final String SUBSCRIPTION_EMAIL_ENABLED = "subscription.email.enabled";
static final String SUBSCRIPTION_RESTHOOK_ENABLED = "subscription.resthook.enabled"; static final String SUBSCRIPTION_RESTHOOK_ENABLED = "subscription.resthook.enabled";
static final String SUBSCRIPTION_WEBSOCKET_ENABLED = "subscription.websocket.enabled"; static final String SUBSCRIPTION_WEBSOCKET_ENABLED = "subscription.websocket.enabled";
static final String ALLOWED_BUNDLE_TYPES = "allowed_bundle_types";
static final String TEST_PORT = "test.port"; 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 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_ENABLED = "cors.enabled";
@@ -321,6 +326,10 @@ public class HapiProperties {
return HapiProperties.getProperty(CORS_ALLOWED_ORIGIN, "*"); return HapiProperties.getProperty(CORS_ALLOWED_ORIGIN, "*");
} }
public static String getAllowedBundleTypes() {
return HapiProperties.getProperty(ALLOWED_BUNDLE_TYPES, "");
}
public static Set<String> getSupportedResourceTypes() { public static Set<String> getSupportedResourceTypes() {
String[] types = defaultString(getProperty("supported_resource_types")).split(","); String[] types = defaultString(getProperty("supported_resource_types")).split(",");
return Arrays.stream(types) return Arrays.stream(types)
@@ -410,6 +419,21 @@ public class HapiProperties {
return HapiProperties.getBooleanProperty(GRAPHQL_ENABLED, true); 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);
}
private static boolean getPropertyBoolean(String thePropertyName, boolean theDefaultValue) { private static boolean getPropertyBoolean(String thePropertyName, boolean theDefaultValue) {
String value = getProperty(thePropertyName, Boolean.toString(theDefaultValue)); String value = getProperty(thePropertyName, Boolean.toString(theDefaultValue));
return Boolean.parseBoolean(value); return Boolean.parseBoolean(value);

View File

@@ -36,7 +36,10 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
import ca.uhn.fhir.validation.IValidatorModule; import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ResultSeverityEnum; import ca.uhn.fhir.validation.ResultSeverityEnum;
import java.util.HashSet;
import java.util.TreeSet;
import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Meta; import org.hl7.fhir.dstu3.model.Meta;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@@ -60,7 +63,8 @@ public class JpaRestfulServer extends RestfulServer {
* Create a FhirContext object that uses the version of FHIR * Create a FhirContext object that uses the version of FHIR
* specified in the properties file. * specified in the properties file.
*/ */
ApplicationContext appCtx = (ApplicationContext) getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT"); ApplicationContext appCtx = (ApplicationContext) getServletContext()
.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
// Customize supported resource types // Customize supported resource types
Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes(); Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
if (!supportedResourceTypes.isEmpty()) { if (!supportedResourceTypes.isEmpty()) {
@@ -104,23 +108,31 @@ public class JpaRestfulServer extends RestfulServer {
* provide further customization of your server's CapabilityStatement * provide further customization of your server's CapabilityStatement
*/ */
if (fhirVersion == FhirVersionEnum.DSTU2) { if (fhirVersion == FhirVersionEnum.DSTU2) {
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, appCtx.getBean(DaoConfig.class)); .getBean("mySystemDaoDstu2", IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
setServerConformanceProvider(confProvider); setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.DSTU3) { } else if (fhirVersion == FhirVersionEnum.DSTU3) {
IFhirSystemDao<Bundle, Meta> systemDao = appCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); IFhirSystemDao<Bundle, Meta> systemDao = appCtx
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, appCtx.getBean(DaoConfig.class)); .getBean("mySystemDaoDstu3", IFhirSystemDao.class);
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
setServerConformanceProvider(confProvider); setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R4) { } else if (fhirVersion == FhirVersionEnum.R4) {
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx.getBean("mySystemDaoR4", IFhirSystemDao.class); IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, appCtx.getBean(DaoConfig.class)); .getBean("mySystemDaoR4", IFhirSystemDao.class);
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R4 Server"); confProvider.setImplementationDescription("HAPI FHIR R4 Server");
setServerConformanceProvider(confProvider); setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R5) { } else if (fhirVersion == FhirVersionEnum.R5) {
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx.getBean("mySystemDaoR5", IFhirSystemDao.class); IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, appCtx.getBean(DaoConfig.class)); .getBean("mySystemDaoR5", IFhirSystemDao.class);
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R5 Server"); confProvider.setImplementationDescription("HAPI FHIR R5 Server");
setServerConformanceProvider(confProvider); setServerConformanceProvider(confProvider);
} else { } else {
@@ -200,7 +212,8 @@ public class JpaRestfulServer extends RestfulServer {
// If you want to enable the $trigger-subscription operation to allow // If you want to enable the $trigger-subscription operation to allow
// manual triggering of a subscription delivery, enable this provider // manual triggering of a subscription delivery, enable this provider
if (false) { // <-- DISABLED RIGHT NOW if (false) { // <-- DISABLED RIGHT NOW
SubscriptionTriggeringProvider retriggeringProvider = appCtx.getBean(SubscriptionTriggeringProvider.class); SubscriptionTriggeringProvider retriggeringProvider = appCtx
.getBean(SubscriptionTriggeringProvider.class);
registerProvider(retriggeringProvider); registerProvider(retriggeringProvider);
} }
@@ -241,7 +254,8 @@ public class JpaRestfulServer extends RestfulServer {
HapiProperties.getSubscriptionRestHookEnabled()) { HapiProperties.getSubscriptionRestHookEnabled()) {
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor) // Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
// with activation of scheduled subscription // with activation of scheduled subscription
SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx.getBean(SubscriptionInterceptorLoader.class); SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx
.getBean(SubscriptionInterceptorLoader.class);
subscriptionInterceptorLoader.registerInterceptors(); subscriptionInterceptorLoader.registerInterceptors();
// Subscription debug logging // Subscription debug logging
@@ -253,13 +267,15 @@ public class JpaRestfulServer extends RestfulServer {
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class); DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class); IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
if (HapiProperties.getAllowCascadingDeletes()) { if (HapiProperties.getAllowCascadingDeletes()) {
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(daoRegistry, interceptorBroadcaster); CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(
daoRegistry, interceptorBroadcaster);
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor); getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
} }
// Binary Storage // Binary Storage
if (HapiProperties.isBinaryStorageEnabled()) { if (HapiProperties.isBinaryStorageEnabled()) {
BinaryStorageInterceptor binaryStorageInterceptor = appCtx.getBean(BinaryStorageInterceptor.class); BinaryStorageInterceptor binaryStorageInterceptor = appCtx
.getBean(BinaryStorageInterceptor.class);
getInterceptorService().registerInterceptor(binaryStorageInterceptor); getInterceptorService().registerInterceptor(binaryStorageInterceptor);
} }
@@ -307,6 +323,18 @@ public class JpaRestfulServer extends RestfulServer {
} }
} }
if (!HapiProperties.getAllowedBundleTypes().isEmpty()) {
String allowedBundleTypesString = HapiProperties.getAllowedBundleTypes();
Set<String> allowedBundleTypes = new HashSet<>();
Arrays.stream(allowedBundleTypesString.split(",")).forEach(o -> {
BundleType type = BundleType.valueOf(o);
allowedBundleTypes.add(type.toCode());
});
DaoConfig config = appCtx.getBean(DaoConfig.class);
config.setBundleTypesAllowedForStorage(
Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
}
// Bulk Export // Bulk Export
if (HapiProperties.getBulkExportEnabled()) { if (HapiProperties.getBulkExportEnabled()) {
registerProvider(appCtx.getBean(BulkDataExportProvider.class)); registerProvider(appCtx.getBean(BulkDataExportProvider.class));

View File

@@ -13,6 +13,10 @@ fhir_version=R4
# accessible from the server itself. # accessible from the server itself.
server_address=http://localhost:8080/hapi-fhir-jpaserver/fhir/ server_address=http://localhost:8080/hapi-fhir-jpaserver/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 default_encoding=JSON
etag_support=ENABLED etag_support=ENABLED
reuse_cached_search_results_millis=-1 reuse_cached_search_results_millis=-1
@@ -115,6 +119,11 @@ cors.allowCredentials=true
# cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca # cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca
cors.allow_origin=* cors.allow_origin=*
##################################################
# Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE)
##################################################
#allowed_bundle_types=COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET
################################################## ##################################################
# Subscriptions # Subscriptions
################################################## ##################################################