Merge branch 'master' into rel_4_1_0
This commit is contained in:
5
.editorconfig
Normal file
5
.editorconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
[*.java]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
138
.gitignore
vendored
138
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
target/
|
||||
.idea/
|
||||
*.iml
|
||||
*.orig
|
||||
target/
|
||||
*.iml
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
@@ -26,3 +25,136 @@ target/
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
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
|
||||
21
Dockerfile
21
Dockerfile
@@ -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
|
||||
|
||||
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
|
||||
ADD ./target/hapi-fhir-jpaserver.war /var/lib/jetty/webapps/hapi-fhir-jpaserver.war
|
||||
EXPOSE 8080
|
||||
CMD ["java","-Dhapi.properties=/hapi-config/hapi.properties","-jar","/usr/local/jetty/start.jar"]
|
||||
22
README.md
22
README.md
@@ -2,6 +2,8 @@
|
||||
|
||||
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
|
||||
|
||||
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.url=jdbc:mysql://localhost:3306/hapi_dstu3
|
||||
* 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.
|
||||
|
||||
@@ -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/)
|
||||
|
||||
# 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
|
||||
|
||||
Install Tomcat.
|
||||
|
||||
1
build-docker-image.bat
Normal file
1
build-docker-image.bat
Normal file
@@ -0,0 +1 @@
|
||||
docker build -t hapi-fhir/hapi-fhir-jpaserver-starter .
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/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
21
docker-compose.yml
Normal 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:
|
||||
9
pom.xml
9
pom.xml
@@ -15,6 +15,11 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-jpaserver-starter</artifactId>
|
||||
|
||||
<prerequisites>
|
||||
<maven>3.5.0</maven>
|
||||
</prerequisites>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
@@ -29,7 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>6.0.5</version>
|
||||
<version>8.0.11</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Needed for Email subscriptions -->
|
||||
@@ -208,7 +213,7 @@
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
|
||||
287
pom.xml.orig
287
pom.xml.orig
@@ -12,27 +12,17 @@
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<<<<<<< HEAD
|
||||
<version>3.7.0</version>
|
||||
<version>4.1.0</version>
|
||||
=======
|
||||
<version>3.7.0-SNAPSHOT</version>
|
||||
>>>>>>> 18c85900e500863b2b24080da9fe5e11c6d0a434
|
||||
<version>4.0.3</version>
|
||||
>>>>>>> master
|
||||
</parent>
|
||||
|
||||
<groupId>ca.uhn.hapi.fhir.demo</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-starter</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>HAPI FHIR JPA Server - Starter Project</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>oss-snapshots</id>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<prerequisites>
|
||||
<maven>3.5.0</maven>
|
||||
</prerequisites>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -48,9 +38,27 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>6.0.5</version>
|
||||
<version>8.0.11</version>
|
||||
</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 -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
@@ -58,24 +66,21 @@
|
||||
<version>${project.version}</version>
|
||||
</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 -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-elasticsearch</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jcl</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- This dependency is used for the "FHIR Tester" web app overlay -->
|
||||
@@ -115,17 +120,6 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 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. -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -136,21 +130,61 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-dbcp2</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</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>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- webjars -->
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<version>3.3.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbynet</artifactId>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>Eonasdan-bootstrap-datetimepicker</artifactId>
|
||||
<version>4.17.43</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbyclient</artifactId>
|
||||
<groupId>org.webjars</groupId>
|
||||
<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>
|
||||
|
||||
<!-- 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>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>ph-schematron</artifactId>
|
||||
@@ -194,6 +229,7 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!--
|
||||
For some reason JavaDoc crashed during site generation unless we have this dependency
|
||||
@@ -204,31 +240,49 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-test-utilities</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</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>
|
||||
|
||||
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver.war -->
|
||||
<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>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.4.8.v20180619</version>
|
||||
<configuration>
|
||||
<webApp>
|
||||
<contextPath>/hapi-fhir-jpaserver</contextPath>
|
||||
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<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>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.4.8.v20180619</version>
|
||||
<configuration>
|
||||
<webApp>
|
||||
<contextPath>/hapi-fhir-jpaserver</contextPath>
|
||||
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Tell Maven which Java source version you want to use -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -259,15 +313,6 @@
|
||||
</configuration>
|
||||
</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 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -285,6 +330,100 @@
|
||||
</executions>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -28,6 +28,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();
|
||||
@@ -82,6 +86,10 @@ public class FhirServerConfigCommon {
|
||||
public DaoConfig 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.setAllowMultipleDelete(this.allowMultipleDelete);
|
||||
retVal.setAllowExternalReferences(this.allowExternalReferences);
|
||||
|
||||
@@ -20,7 +20,11 @@ import java.util.stream.Collectors;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
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_MULTIPLE_DELETE = "allow_multiple_delete";
|
||||
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_RESTHOOK_ENABLED = "subscription.resthook.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 TESTER_CONFIG_REFUSE_TO_FETCH_THIRD_PARTY_URLS = "tester.config.refuse_to_fetch_third_party_urls";
|
||||
static final String CORS_ENABLED = "cors.enabled";
|
||||
@@ -114,19 +119,19 @@ public class HapiProperties {
|
||||
|
||||
@NotNull
|
||||
private static Properties loadProperties() {
|
||||
// Load the configurable properties file
|
||||
// Load the configurable properties file
|
||||
Properties properties;
|
||||
try (InputStream in = HapiProperties.class.getClassLoader().getResourceAsStream(HAPI_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);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException("Could not load HAPI properties", e);
|
||||
}
|
||||
|
||||
Properties overrideProps = loadOverrideProperties();
|
||||
if (overrideProps != null) {
|
||||
properties.putAll(overrideProps);
|
||||
}
|
||||
Properties overrideProps = loadOverrideProperties();
|
||||
if (overrideProps != null) {
|
||||
properties.putAll(overrideProps);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -321,6 +326,10 @@ public class HapiProperties {
|
||||
return HapiProperties.getProperty(CORS_ALLOWED_ORIGIN, "*");
|
||||
}
|
||||
|
||||
public static String getAllowedBundleTypes() {
|
||||
return HapiProperties.getProperty(ALLOWED_BUNDLE_TYPES, "");
|
||||
}
|
||||
|
||||
public static Set<String> getSupportedResourceTypes() {
|
||||
String[] types = defaultString(getProperty("supported_resource_types")).split(",");
|
||||
return Arrays.stream(types)
|
||||
@@ -407,9 +416,24 @@ public class HapiProperties {
|
||||
}
|
||||
|
||||
public static boolean getGraphqlEnabled() {
|
||||
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) {
|
||||
String value = getProperty(thePropertyName, Boolean.toString(theDefaultValue));
|
||||
return Boolean.parseBoolean(value);
|
||||
|
||||
@@ -36,7 +36,10 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
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.r4.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu3.model.Meta;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -49,263 +52,288 @@ import java.util.Set;
|
||||
|
||||
public class JpaRestfulServer extends RestfulServer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
|
||||
/*
|
||||
* 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<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
|
||||
if (!supportedResourceTypes.isEmpty()) {
|
||||
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
|
||||
daoRegistry.setSupportedResourceTypes(supportedResourceTypes);
|
||||
}
|
||||
/*
|
||||
* 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<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
|
||||
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();
|
||||
}
|
||||
/*
|
||||
* 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(appCtx.getBean(FhirContext.class));
|
||||
|
||||
registerProviders(resourceProviders.createProviders());
|
||||
registerProvider(systemProvider);
|
||||
registerProviders(resourceProviders.createProviders());
|
||||
registerProvider(systemProvider);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* is a nice addition.
|
||||
*
|
||||
* You can also create your own subclass of the conformance provider if you need to
|
||||
* provide further customization of your server's CapabilityStatement
|
||||
*/
|
||||
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
||||
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
||||
IFhirSystemDao<Bundle, Meta> systemDao = appCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.R4) {
|
||||
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx.getBean("mySystemDaoR4", IFhirSystemDao.class);
|
||||
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.R5) {
|
||||
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx.getBean("mySystemDaoR5", IFhirSystemDao.class);
|
||||
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
* is a nice addition.
|
||||
*
|
||||
* You can also create your own subclass of the conformance provider if you need to
|
||||
* provide further customization of your server's CapabilityStatement
|
||||
*/
|
||||
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
||||
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx
|
||||
.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao,
|
||||
appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
||||
IFhirSystemDao<Bundle, Meta> systemDao = appCtx
|
||||
.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao,
|
||||
appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.R4) {
|
||||
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx
|
||||
.getBean("mySystemDaoR4", IFhirSystemDao.class);
|
||||
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao,
|
||||
appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.R5) {
|
||||
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx
|
||||
.getBean("mySystemDaoR5", IFhirSystemDao.class);
|
||||
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao,
|
||||
appCtx.getBean(DaoConfig.class));
|
||||
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/*
|
||||
* ETag Support
|
||||
*/
|
||||
setETagSupport(HapiProperties.getEtagSupport());
|
||||
/*
|
||||
* ETag Support
|
||||
*/
|
||||
setETagSupport(HapiProperties.getEtagSupport());
|
||||
|
||||
/*
|
||||
* This server tries to dynamically generate narratives
|
||||
*/
|
||||
FhirContext ctx = getFhirContext();
|
||||
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||
/*
|
||||
* This server tries to dynamically generate narratives
|
||||
*/
|
||||
FhirContext ctx = getFhirContext();
|
||||
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||
|
||||
/*
|
||||
* Default to JSON and pretty printing
|
||||
*/
|
||||
setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
|
||||
/*
|
||||
* Default to JSON and pretty printing
|
||||
*/
|
||||
setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
|
||||
|
||||
/*
|
||||
* Default encoding
|
||||
*/
|
||||
setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
|
||||
/*
|
||||
* Default encoding
|
||||
*/
|
||||
setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
|
||||
|
||||
/*
|
||||
* This configures the server to page search results to and from
|
||||
* the database, instead of only paging them to memory. This may mean
|
||||
* a performance hit when performing searches that return lots of results,
|
||||
* but makes the server much more scalable.
|
||||
*/
|
||||
setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
|
||||
/*
|
||||
* This configures the server to page search results to and from
|
||||
* the database, instead of only paging them to memory. This may mean
|
||||
* a performance hit when performing searches that return lots of results,
|
||||
* but makes the server much more scalable.
|
||||
*/
|
||||
setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
|
||||
|
||||
/*
|
||||
* This interceptor formats the output using nice colourful
|
||||
* HTML output when the request is detected to come from a
|
||||
* browser.
|
||||
*/
|
||||
ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
|
||||
;
|
||||
this.registerInterceptor(responseHighlighterInterceptor);
|
||||
/*
|
||||
* This interceptor formats the output using nice colourful
|
||||
* HTML output when the request is detected to come from a
|
||||
* browser.
|
||||
*/
|
||||
ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
|
||||
;
|
||||
this.registerInterceptor(responseHighlighterInterceptor);
|
||||
|
||||
/*
|
||||
* 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());
|
||||
this.registerInterceptor(loggingInterceptor);
|
||||
/*
|
||||
* 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());
|
||||
this.registerInterceptor(loggingInterceptor);
|
||||
|
||||
/*
|
||||
* If you are hosting this server at a specific DNS name, the server will try to
|
||||
* figure out the FHIR base URL based on what the web container tells it, but
|
||||
* 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) {
|
||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
|
||||
}
|
||||
/*
|
||||
* If you are hosting this server at a specific DNS name, the server will try to
|
||||
* figure out the FHIR base URL based on what the web container tells it, but
|
||||
* 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) {
|
||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
|
||||
}
|
||||
|
||||
/*
|
||||
* If you are using DSTU3+, you may want to add a terminology uploader, which allows
|
||||
* uploading of external terminologies such as Snomed CT. Note that this uploader
|
||||
* does not have any security attached (any anonymous user may use it by default)
|
||||
* 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 you are using DSTU3+, you may want to add a terminology uploader, which allows
|
||||
* uploading of external terminologies such as Snomed CT. Note that this uploader
|
||||
* does not have any security attached (any anonymous user may use it by default)
|
||||
* 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 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 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);
|
||||
}
|
||||
|
||||
// Define your CORS configuration. This is an example
|
||||
// showing a typical setup. You should customize this
|
||||
// to your specific needs
|
||||
if (HapiProperties.getCorsEnabled()) {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedHeader(HttpHeaders.ORIGIN);
|
||||
config.addAllowedHeader(HttpHeaders.ACCEPT);
|
||||
config.addAllowedHeader(HttpHeaders.CONTENT_TYPE);
|
||||
config.addAllowedHeader(HttpHeaders.AUTHORIZATION);
|
||||
config.addAllowedHeader(HttpHeaders.CACHE_CONTROL);
|
||||
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());
|
||||
// Define your CORS configuration. This is an example
|
||||
// showing a typical setup. You should customize this
|
||||
// to your specific needs
|
||||
if (HapiProperties.getCorsEnabled()) {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedHeader(HttpHeaders.ORIGIN);
|
||||
config.addAllowedHeader(HttpHeaders.ACCEPT);
|
||||
config.addAllowedHeader(HttpHeaders.CONTENT_TYPE);
|
||||
config.addAllowedHeader(HttpHeaders.AUTHORIZATION);
|
||||
config.addAllowedHeader(HttpHeaders.CACHE_CONTROL);
|
||||
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());
|
||||
|
||||
config.addExposedHeader("Location");
|
||||
config.addExposedHeader("Content-Location");
|
||||
config.setAllowedMethods(
|
||||
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
|
||||
config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
|
||||
config.addExposedHeader("Location");
|
||||
config.addExposedHeader("Content-Location");
|
||||
config.setAllowedMethods(
|
||||
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
|
||||
config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
|
||||
|
||||
// Create the interceptor and register it
|
||||
CorsInterceptor interceptor = new CorsInterceptor(config);
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
// Create the interceptor and register it
|
||||
CorsInterceptor interceptor = new CorsInterceptor(config);
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
|
||||
// with activation of scheduled subscription
|
||||
SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx.getBean(SubscriptionInterceptorLoader.class);
|
||||
subscriptionInterceptorLoader.registerInterceptors();
|
||||
// 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()) {
|
||||
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
|
||||
// with activation of scheduled subscription
|
||||
SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx
|
||||
.getBean(SubscriptionInterceptorLoader.class);
|
||||
subscriptionInterceptorLoader.registerInterceptors();
|
||||
|
||||
// Subscription debug logging
|
||||
IInterceptorService interceptorService = appCtx.getBean(IInterceptorService.class);
|
||||
interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor());
|
||||
}
|
||||
// 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()) {
|
||||
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(daoRegistry, interceptorBroadcaster);
|
||||
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
|
||||
}
|
||||
// Cascading deletes
|
||||
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
|
||||
IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
|
||||
if (HapiProperties.getAllowCascadingDeletes()) {
|
||||
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(
|
||||
daoRegistry, interceptorBroadcaster);
|
||||
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
|
||||
}
|
||||
|
||||
// Binary Storage
|
||||
if (HapiProperties.isBinaryStorageEnabled()) {
|
||||
BinaryStorageInterceptor binaryStorageInterceptor = appCtx.getBean(BinaryStorageInterceptor.class);
|
||||
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
|
||||
}
|
||||
// Binary Storage
|
||||
if (HapiProperties.isBinaryStorageEnabled()) {
|
||||
BinaryStorageInterceptor binaryStorageInterceptor = appCtx
|
||||
.getBean(BinaryStorageInterceptor.class);
|
||||
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
|
||||
}
|
||||
|
||||
// Validation
|
||||
IValidatorModule validatorModule;
|
||||
switch (fhirVersion) {
|
||||
// Validation
|
||||
IValidatorModule validatorModule;
|
||||
switch (fhirVersion) {
|
||||
case DSTU2:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorDstu2", IValidatorModule.class);
|
||||
break;
|
||||
case DSTU3:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
|
||||
break;
|
||||
case R4:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
|
||||
break;
|
||||
case R5:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
|
||||
break;
|
||||
case DSTU3:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
|
||||
break;
|
||||
case R4:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
|
||||
break;
|
||||
case R5:
|
||||
validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
|
||||
break;
|
||||
// These versions are not supported by HAPI FHIR JPA
|
||||
case DSTU2_HL7ORG:
|
||||
case DSTU2_1:
|
||||
default:
|
||||
validatorModule = null;
|
||||
break;
|
||||
}
|
||||
if (validatorModule != null) {
|
||||
if (HapiProperties.getValidateRequestsEnabled()) {
|
||||
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
|
||||
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
if (HapiProperties.getValidateResponsesEnabled()) {
|
||||
ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
|
||||
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
}
|
||||
default:
|
||||
validatorModule = null;
|
||||
break;
|
||||
}
|
||||
if (validatorModule != null) {
|
||||
if (HapiProperties.getValidateRequestsEnabled()) {
|
||||
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
|
||||
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
if (HapiProperties.getValidateResponsesEnabled()) {
|
||||
ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
|
||||
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
|
||||
registerInterceptor(interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
// GraphQL
|
||||
if (HapiProperties.getGraphqlEnabled()) {
|
||||
if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
registerProvider(appCtx.getBean(GraphQLProvider.class));
|
||||
}
|
||||
}
|
||||
// GraphQL
|
||||
if (HapiProperties.getGraphqlEnabled()) {
|
||||
if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
registerProvider(appCtx.getBean(GraphQLProvider.class));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
if (HapiProperties.getBulkExportEnabled()) {
|
||||
|
||||
@@ -13,6 +13,10 @@ fhir_version=R4
|
||||
# accessible from the server itself.
|
||||
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
|
||||
etag_support=ENABLED
|
||||
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.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
|
||||
##################################################
|
||||
|
||||
Reference in New Issue
Block a user