Merge pull request #1 from hapifhir/master

update
This commit is contained in:
Jens Kristian Villadsen
2020-11-23 20:45:01 +01:00
committed by GitHub
15 changed files with 235 additions and 97 deletions

View File

@@ -2,12 +2,12 @@ FROM maven:3.6.3-jdk-11-slim as build-hapi
WORKDIR /tmp/hapi-fhir-jpaserver-starter WORKDIR /tmp/hapi-fhir-jpaserver-starter
COPY pom.xml . COPY pom.xml .
RUN mvn dependency:go-offline RUN mvn -ntp dependency:go-offline
COPY src/ /tmp/hapi-fhir-jpaserver-starter/src/ COPY src/ /tmp/hapi-fhir-jpaserver-starter/src/
RUN mvn clean install -DskipTests RUN mvn clean install -DskipTests
FROM tomcat:9.0.37-jdk11-openjdk-slim-buster FROM tomcat:9.0.38-jdk11-openjdk-slim-buster
RUN mkdir -p /data/hapi/lucenefiles && chmod 775 /data/hapi/lucenefiles RUN mkdir -p /data/hapi/lucenefiles && chmod 775 /data/hapi/lucenefiles
COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/tomcat/webapps/ COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/tomcat/webapps/

210
README.md
View File

@@ -4,57 +4,76 @@ This project is a complete starter project you can use to deploy a FHIR server u
Note that this project is specifically intended for end users of the HAPI FHIR JPA server module (in other words, it helps you implement HAPI FHIR, it is not the source of the library itself). If you are looking for the main HAPI FHIR project, see here: https://github.com/jamesagnew/hapi-fhir Note that this project is specifically intended for end users of the HAPI FHIR JPA server module (in other words, it helps you implement HAPI FHIR, it is not the source of the library itself). If you are looking for the main HAPI FHIR project, see here: https://github.com/jamesagnew/hapi-fhir
Need Help? Please see: https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help
## Prerequisites ## Prerequisites
In order to use this sample, you should have: In order to use this sample, you should have:
- [This project](https://github.com/hapifhir/hapi-fhir-jpaserver-starter) checked out. You may wish to create a GitHub Fork of the project and check that out instead so that you can customize the project and save the results to GitHub. - [This project](https://github.com/hapifhir/hapi-fhir-jpaserver-starter) checked out. You may wish to create a GitHub Fork of the project and check that out instead so that you can customize the project and save the results to GitHub.
### and either
- Oracle Java (JDK) installed: Minimum JDK8 or newer. - Oracle Java (JDK) installed: Minimum JDK8 or newer.
- Apache Maven build tool (newest version) - Apache Maven build tool (newest version)
### or
- Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) or used directly from [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi)
## Running via [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) ## Running via [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi)
Each tagged/released version of `hapi-fhir-jpaserver` is built as a Docker image and published to Docker hub. To run the published Docker image from DockerHub: Each tagged/released version of `hapi-fhir-jpaserver` is built as a Docker image and published to Docker hub. To run the published Docker image from DockerHub:
``` ```
docker pull hapiproject/hapi:latest docker pull hapiproject/hapi:latest
docker run -p 8080:8080 hapiproject/hapi:tagname docker run -p 8080:8080 hapiproject/hapi:latest
``` ```
This will run the docker image with the default configuration, mapping port 8080 from the container to port 8080 in the host. Once running, you can access `http://localhost:8080/hapi-fhir-jpaserver/fhir` in the browser to access the HAPI FHIR server's UI. This will run the docker image with the default configuration, mapping port 8080 from the container to port 8080 in the host. Once running, you can access `http://localhost:8080/` in the browser to access the HAPI FHIR server's UI or use `http://localhost:8080/fhir/` as the base URL for your REST requests.
If you change the mapped port, you need to change the configuration used by HAPI to have the correct `server_address` property/value. If you change the mapped port, you need to change the configuration used by HAPI to have the correct `hapi.fhir.tester` property/value.
### Configuration via environment variables ### Configuration via environment variables
You can customize HAPI directly from the `run` command using environment variables. For example: You can customize HAPI directly from the `run` command using environment variables. For example:
`docker run -p 8090:8080 -e server_address=http://localhost:8090/hapi-fhir-jpaserver/fhir hapiproject/hapi:tagname` ```
docker run -p 8080:8080 -e hapi.fhir.default_encoding=xml hapiproject/hapi:latest
```
HAPI looks in the environment variables for properties in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file. HAPI looks in the environment variables for properties in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file for defaults.
### Configuration via overridden hapi.properties file ### Configuration via overridden application.yaml file and using Docker
You can customize HAPI by telling HAPI to look for the `hapi.properties` file in a different location: You can customize HAPI by telling HAPI to look for the configuration file in a different location, eg.:
`docker run -p 8090:8080 -e hapi.properties=/some/directory/with/hapi.properties hapiproject/hapi:tagname` ```
docker run -p 8090:8080 -v $(pwd)/yourLocalFolder:/configs -e "--spring.config.location=file:///configs/another.application.yaml" hapiproject/hapi:latest
```
Here, the configuration file (*another.application.yaml*) is placed locally in the folder *yourLocalFolder*.
### Example docker-compose.yml
```
docker run -p 8090:8080 -e "--spring.config.location=classpath:/another.application.yaml" hapiproject/hapi:latest
```
Here, the configuration file (*another.application.yaml*) is part of the compiled set of resources.
### Example using docker-compose.yml for docker-compose
``` ```
version: '3.7' version: '3.7'
services: services:
web: web:
image: "hapiproject/hapi:tagname" image: "hapiproject/hapi:latest"
ports: ports:
- "8090:8080" - "8090:8080"
configs: configs:
- source: hapi - source: hapi
target: /data/hapi/hapi.properties target: /data/hapi/application.yaml
volumes: volumes:
- hapi-data:/data/hapi - hapi-data:/data/hapi
environment: environment:
JAVA_OPTS: '-Dhapi.properties=/data/hapi/hapi.properties' SPRING_CONFIG_LOCATION: 'file:///data/hapi/application.yaml'
configs: configs:
hapi: hapi:
external: true external: true
@@ -65,15 +84,13 @@ volumes:
## Running locally ## Running locally
The easiest way to run this server is to run it directly in Maven using a built-in Jetty server. To do this, change `src/main/resources/hapi.properties` `server_address` and `server.base` with the values commented out as _For Jetty, use this_ and then execute the following command: The easiest way to run this server entirely depends on your environment requirements. At least, the following 4 ways are supported:
### Using jetty
```bash ```bash
mvn jetty:run mvn jetty:run
``` ```
Then, browse to the following link to use the server:
[http://localhost:8080/hapi-fhir-jpaserver/](http://localhost:8080/hapi-fhir-jpaserver/)
If you need to run this server on a different port (using Maven), you can change the port in the run command as follows: If you need to run this server on a different port (using Maven), you can change the port in the run command as follows:
@@ -81,43 +98,112 @@ If you need to run this server on a different port (using Maven), you can change
mvn -Djetty.port=8888 jetty:run mvn -Djetty.port=8888 jetty:run
``` ```
And replacing 8888 with the port of your choice. Server will then be accessible at http://localhost:8888/ and eg. http://localhost:8888/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg.
```yaml
tester:
-
id: home
name: Local Tester
server_address: 'http://localhost:8888/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
```
### Using Spring Boot with :run
```bash
mvn clean spring-boot:run -Pboot
```
Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg.
```yaml
tester:
-
id: home
name: Local Tester
server_address: 'http://localhost:8080/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
```
### Using Spring Boot
```bash
mvn clean package spring-boot:repackage -Pboot && java -jar target/ROOT.war
```
Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg.
```yaml
tester:
-
id: home
name: Local Tester
server_address: 'http://localhost:8080/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
```
### Using Spring Boot and Google distroless
```bash
mvn clean package com.google.cloud.tools:jib-maven-plugin:dockerBuild -Dimage=distroless-hapi && docker run -p 8080:8080 distroless-hapi
```
Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg.
```yaml
tester:
-
id: home
name: Local Tester
server_address: 'http://localhost:8080/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
```
### Using the Dockerfile and multistage build
```bash
./build-docker-image.sh && docker run -p 8080:8080 hapi-fhir/hapi-fhir-jpaserver-starter:latest
```
Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg.
```yaml
tester:
-
id: home
name: Local Tester
server_address: 'http://localhost:8080/fhir'
refuse_to_fetch_third_party_urls: false
fhir_version: R4
```
## Configurations ## Configurations
Much of this HAPI starter project can be configured using the properties file in _src/main/resources/hapi.properties_. By default, this starter project is configured to use Derby as the database. Much of this HAPI starter project can be configured using the yaml file in _src/main/resources/application.yaml_. By default, this starter project is configured to use H2 as the database.
### MySql configuration ### MySql configuration
To configure the starter app to use MySQL, instead of the default Derby, update the hapi.properties file to have the following: To configure the starter app to use MySQL, instead of the default H2, update the application.yaml file to have the following:
- datasource.driver=com.mysql.jdbc.Driver ```yaml
- datasource.url=jdbc:mysql://localhost:3306/hapi_dstu3 spring:
- hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect datasource:
- datasource.username=admin url: 'jdbc:mysql://localhost:3306/hapi_dstu3'
- datasource.password=admin username: admin
password: admin
driverClassName: com.mysql.jdbc.Driver
```
### PostgreSQL configuration ### PostgreSQL configuration
To configure the starter app to use PostgreSQL, instead of the default Derby, update the hapi.properties file to have the following: To configure the starter app to use PostgreSQL, instead of the default H2, update the application.yaml file to have the following:
- datasource.driver=org.postgresql.Driver ```yaml
- datasource.url=jdbc:postgresql://localhost:5432/hapi_dstu3 spring:
- hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect datasource:
- datasource.username=admin url: 'jdbc:postgresql://localhost:5432/hapi_dstu3'
- datasource.password=admin username: admin
password: admin
driverClassName: org.postgresql.Driver
```
Because the integration tests within the project rely on the default Derby database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure.
It is important to use PostgreSQL95Dialect when using PostgreSQL version 10+.
## Overriding application properties
You can override the properties that are loaded into the compiled web app (.war file) making a copy of the hapi.properties file on the file system, making changes to it, and then setting the JAVA_OPTS environment variable on the tomcat server to tell hapi-jpaserver-starter where the overriding properties file is. For example:
`-Dhapi.properties=/some/custom/directory/hapi.properties`
Note: This property name and the path is case-sensitive. "-DHAPI.PROPERTIES=XXX" will not work.
## Customizing The Web Testpage UI ## Customizing The Web Testpage UI
@@ -127,7 +213,7 @@ The UI is customized using [Thymeleaf](https://www.thymeleaf.org/) template file
Several template files that can be customized are found in the following directory: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates) Several template files that can be customized are found in the following directory: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/tree/master/src/main/webapp/WEB-INF/templates)
## Deploying to a Container ## Deploying to an Application Server
Using the Maven-Embedded Jetty method above is convenient, but it is not a good solution if you want to leave the server running in the background. Using the Maven-Embedded Jetty method above is convenient, but it is not a good solution if you want to leave the server running in the background.
@@ -141,29 +227,37 @@ To deploy to a container, you should first build the project:
mvn clean install mvn clean install
``` ```
This will create a file called `hapi-fhir-jpaserver.war` in your `target` directory. This should be installed in your Web Container according to the instructions for your particular container. For example, if you are using Tomcat, you will want to copy this file to the `webapps/` directory. This will create a file called `ROOT.war` in your `target` directory. This should be installed in your Web Container according to the instructions for your particular container. For example, if you are using Tomcat, you will want to copy this file to the `webapps/` directory.
Again, browse to the following link to use the server (note that the port 8080 may not be correct depending on how your server is configured). Again, browse to the following link to use the server (note that the port 8080 may not be correct depending on how your server is configured).
[http://localhost:8080/hapi-fhir-jpaserver/](http://localhost:8080/hapi-fhir-jpaserver/) [http://localhost:8080/](http://localhost:8080/)
If you would like it to be hosted at eg. hapi-fhir-jpaserver, eg. http://localhost:8080/hapi-fhir-jpaserver/ - then rename the WAR file to ```hapi-fhir-jpaserver.war```.
## Deploy with docker compose ## 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 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 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/. reached at http://localhost:8080/.
In order to use another port, change the `ports` parameter 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. 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 The docker compose set also includes my MySQL database, if you choose to use MySQL instead of H2, change the following
properties in hapi.properties: properties in application.yaml:
- datasource.driver=com.mysql.jdbc.Driver ```yaml
- datasource.url=jdbc:mysql://hapi-fhir-mysql:3306/hapi spring:
- hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect datasource:
- datasource.username=admin url: 'jdbc:mysql://hapi-fhir-mysql:3306/hapi'
- datasource.password=admin username: admin
password: admin
driverClassName: com.mysql.jdbc.Driver
```
## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot
Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers.
## Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ ## Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ
@@ -201,21 +295,21 @@ It is important to use MySQL5Dialect when using MySQL version 5+.
## Enabling Subscriptions ## Enabling Subscriptions
The server may be configured with subscription support by enabling properties in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file: The server may be configured with subscription support by enabling properties in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file:
- `subscription.resthook.enabled` - Enables REST Hook subscriptions, where the server will make an outgoing connection to a remote REST server - `hapi.fhir.subscription.resthook.enabled` - Enables REST Hook subscriptions, where the server will make an outgoing connection to a remote REST server
- `subscription.email.enabled` - Enables email subscriptions. Note that you must also provide the connection details for a usable SMTP server. - `hapi.fhir.subscription.email.*` - Enables email subscriptions. Note that you must also provide the connection details for a usable SMTP server.
- `subscription.websocket.enabled` - Enables websocket subscriptions. With this enabled, your server will accept incoming websocket connections on the following URL (this example uses the default context path and port, you may need to tweak depending on your deployment environment): [ws://localhost:8080/hapi-fhir-jpaserver/websocket](ws://localhost:8080/hapi-fhir-jpaserver/websocket) - `hapi.fhir.subscription.websocket.enabled` - Enables websocket subscriptions. With this enabled, your server will accept incoming websocket connections on the following URL (this example uses the default context path and port, you may need to tweak depending on your deployment environment): [ws://localhost:8080/websocket](ws://localhost:8080/websocket)
## Enabling EMPI ## Enabling EMPI
Set `empi.enabled=true` in the [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) file to enable EMPI on this server. The EMPI matching rules are configured in [empi-rules.json](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/empi-rules.json). The rules in this example file should be replaced with actual matching rules appropriate to your data. Note that EMPI relies on subscriptions, so for EMPI to work, subscriptions must be enabled. Set `hapi.fhir.empi_enabled=true` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable EMPI on this server. The EMPI matching rules are configured in [empi-rules.json](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/empi-rules.json). The rules in this example file should be replaced with actual matching rules appropriate to your data. Note that EMPI relies on subscriptions, so for EMPI to work, subscriptions must be enabled.
## Using Elasticsearch ## Using Elasticsearch
By default, the server will use embedded lucene indexes for terminology and fulltext indexing purposes. You can switch this to using lucene by editing the properties in [hapi.properties](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/hapi.properties) By default, the server will use embedded lucene indexes for terminology and fulltext indexing purposes. You can switch this to using lucene by editing the properties in [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml)
For example: For example:

18
pom.xml
View File

@@ -14,18 +14,18 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.1.0</version> <version>5.2.0</version>
</parent> </parent>
<artifactId>hapi-fhir-jpaserver-starter</artifactId> <artifactId>hapi-fhir-jpaserver-starter</artifactId>
<properties> <properties>
<java.version>8</java.version> <java.version>8</java.version>
<spring.boot>2.3.3.RELEASE</spring.boot> <spring_boot_version>2.3.4.RELEASE</spring_boot_version>
</properties> </properties>
<prerequisites> <prerequisites>
<maven>3.6.0</maven> <maven>3.6.3</maven>
</prerequisites> </prerequisites>
<packaging>war</packaging> <packaging>war</packaging>
@@ -269,7 +269,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId> <artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring.boot}</version> <version>${spring_boot_version}</version>
</dependency> </dependency>
@@ -289,7 +289,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot}</version> <version>${spring_boot_version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@@ -298,8 +298,8 @@
<build> <build>
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver.war --> <!-- Tells Maven to name the generated WAR file as ROOT.war -->
<finalName>hapi-fhir-jpaserver</finalName> <finalName>ROOT</finalName>
<plugins> <plugins>
<plugin> <plugin>
@@ -495,7 +495,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>2.3.3.RELEASE</version> <version>${spring_boot_version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</profile> </profile>
@@ -508,7 +508,7 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>2.3.3.RELEASE</version> <version>${spring_boot_version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@@ -20,8 +20,8 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
@ServletComponentScan(basePackageClasses = { @ServletComponentScan(basePackageClasses = {
JpaRestfulServer.class}, basePackages = "ca.uhn.fhir.jpa.starter") JpaRestfulServer.class})
@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}, scanBasePackages = {"ca.uhn.fhir.jpa.starter"}) @SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class})
@Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, EmpiConfig.class}) @Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, EmpiConfig.class})
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer {
@@ -49,7 +49,7 @@ public class Application extends SpringBootServletInitializer {
JpaRestfulServer jpaRestfulServer = new JpaRestfulServer(); JpaRestfulServer jpaRestfulServer = new JpaRestfulServer();
beanFactory.autowireBean(jpaRestfulServer); beanFactory.autowireBean(jpaRestfulServer);
servletRegistrationBean.setServlet(jpaRestfulServer); servletRegistrationBean.setServlet(jpaRestfulServer);
servletRegistrationBean.addUrlMappings("/hapi-fhir-jpaserver/fhir/*"); servletRegistrationBean.addUrlMappings("/fhir/*");
servletRegistrationBean.setLoadOnStartup(1); servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean; return servletRegistrationBean;
@@ -68,7 +68,7 @@ public class Application extends SpringBootServletInitializer {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(); ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setServlet(dispatcherServlet); registrationBean.setServlet(dispatcherServlet);
registrationBean.addUrlMappings("/hapi-fhir-jpaserver/*", "/*"); registrationBean.addUrlMappings("/*");
registrationBean.setLoadOnStartup(1); registrationBean.setLoadOnStartup(1);
return registrationBean; return registrationBean;

View File

@@ -16,6 +16,8 @@ import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
import ca.uhn.fhir.jpa.provider.GraphQLProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.IJpaSystemProvider; import ca.uhn.fhir.jpa.provider.IJpaSystemProvider;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5; import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5;
@@ -35,6 +37,7 @@ import ca.uhn.fhir.validation.ResultSeverityEnum;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Bundle.BundleType; import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
@@ -95,6 +98,9 @@ public class BaseJpaRestfulServer extends RestfulServer {
@Autowired @Autowired
AppProperties appProperties; AppProperties appProperties;
@Autowired
ApplicationContext myApplicationContext;
public BaseJpaRestfulServer() { public BaseJpaRestfulServer() {
} }
@@ -236,16 +242,14 @@ public class BaseJpaRestfulServer extends RestfulServer {
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
* with this feature. * with this feature.
*/ */
if (false) { // <-- DISABLED RIGHT NOW if (ctx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW
//registerProvider(appCtx.getBean(TerminologyUploaderProvider.class)); registerProvider(myApplicationContext.getBean(TerminologyUploaderProvider.class));
} }
// 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 (true) { // <-- ENABLED RIGHT NOW
/* SubscriptionTriggeringProvider retriggeringProvider = appCtx registerProvider(myApplicationContext.getBean(SubscriptionTriggeringProvider.class));
.getBean(SubscriptionTriggeringProvider.class);
registerProvider(retriggeringProvider);*/
} }
// Define your CORS configuration. This is an example // Define your CORS configuration. This is an example

View File

@@ -14,8 +14,8 @@ public class EnvironmentHelper {
public static Properties getHibernateProperties(ConfigurableEnvironment environment) { public static Properties getHibernateProperties(ConfigurableEnvironment environment) {
Properties properties = new Properties(); Properties properties = new Properties();
if (environment.getProperty("spring.jpa.properties", String.class) == null) { if (environment.getProperty("spring.jpa.properties", String.class) == null) {
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.search.model_mapping", "ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory"); properties.put("hibernate.search.model_mapping", "ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory");
properties.put("hibernate.format_sql", "false"); properties.put("hibernate.format_sql", "false");
properties.put("hibernate.show_sql", "false"); properties.put("hibernate.show_sql", "false");

View File

@@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.starter;
import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.binstore.DatabaseBlobBinaryStorageSvcImpl; import ca.uhn.fhir.jpa.binstore.DatabaseBlobBinaryStorageSvcImpl;
import ca.uhn.fhir.jpa.binstore.IBinaryStorageSvc; import ca.uhn.fhir.jpa.binstore.IBinaryStorageSvc;
import ca.uhn.fhir.jpa.config.HibernateDialectProvider;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
@@ -10,9 +11,11 @@ import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender;
import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender; import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.hl7.fhir.dstu2.model.Subscription; import org.hl7.fhir.dstu2.model.Subscription;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.Optional; import java.util.Optional;
@@ -110,6 +113,11 @@ public class FhirServerConfigCommon {
return retVal; return retVal;
} }
@Bean
public YamlPropertySourceLoader yamlPropertySourceLoader() {
return new YamlPropertySourceLoader();
}
@Bean @Bean
public PartitionSettings partitionSettings(AppProperties appProperties) { public PartitionSettings partitionSettings(AppProperties appProperties) {
PartitionSettings retVal = new PartitionSettings(); PartitionSettings retVal = new PartitionSettings();
@@ -123,6 +131,12 @@ public class FhirServerConfigCommon {
} }
@Primary
@Bean
public HibernateDialectProvider jpaStarterDialectProvider() {
return new JpaHibernateDialectProvider();
}
@Bean @Bean
public ModelConfig modelConfig(AppProperties appProperties) { public ModelConfig modelConfig(AppProperties appProperties) {
ModelConfig modelConfig = new ModelConfig(); ModelConfig modelConfig = new ModelConfig();

View File

@@ -0,0 +1,22 @@
package ca.uhn.fhir.jpa.starter;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.jpa.config.HibernateDialectProvider;
import org.hibernate.dialect.Dialect;
import org.springframework.beans.factory.annotation.Value;
public class JpaHibernateDialectProvider extends HibernateDialectProvider {
@Value("${spring.jpa.properties.hibernate.dialect}")
public String myDialectClass;
@Override
public Dialect getDialect() {
try {
return (Dialect) Class.forName(myDialectClass).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new ConfigurationException("Can not load dialect: " + myDialectClass);
}
}
}

View File

@@ -24,6 +24,10 @@ spring:
hibernate.search.default.indexBase: target/lucenefiles hibernate.search.default.indexBase: target/lucenefiles
hibernate.search.lucene_version: LUCENE_CURRENT hibernate.search.lucene_version: LUCENE_CURRENT
batch:
job:
enabled: false
hapi: hapi:
fhir: fhir:
defer_indexing_for_codesystems_of_size: 101 defer_indexing_for_codesystems_of_size: 101
@@ -86,7 +90,7 @@ hapi:
- -
id: home id: home
name: Local Tester name: Local Tester
server_address: 'http://localhost:8080/hapi-fhir-jpaserver/fhir' server_address: 'http://localhost:8080/fhir'
refuse_to_fetch_third_party_urls: false refuse_to_fetch_third_party_urls: false
fhir_version: R4 fhir_version: R4
- -

View File

@@ -26,17 +26,17 @@
"name": "cosine-given-name", "name": "cosine-given-name",
"resourceType": "*", "resourceType": "*",
"resourcePath": "name.given", "resourcePath": "name.given",
"metric": "COSINE", "matcher": {
"matchThreshold": 0.8, "algorithm": "COLOGNE"
"exact": true }
}, },
{ {
"name": "jaro-last-name", "name": "jaro-last-name",
"resourceType": "*", "resourceType": "*",
"resourcePath": "name.family", "resourcePath": "name.family",
"metric": "JARO_WINKLER", "matcher": {
"matchThreshold": 0.8, "algorithm": "SOUNDEX"
"exact": true }
} }
], ],
"matchResultMap": { "matchResultMap": {

View File

@@ -50,7 +50,7 @@ public class ExampleServerDstu2IT {
ourCtx = FhirContext.forDstu2(); ourCtx = FhirContext.forDstu2();
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; String ourServerBase = "http://localhost:" + port + "/fhir/";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(new LoggingInterceptor(true));
} }

View File

@@ -92,7 +92,7 @@ public class ExampleServerDstu3IT {
SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON);
myWebSocketClient.start(); myWebSocketClient.start();
URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); URI echoUri = new URI("ws://localhost:" + port + "/websocket");
ClientUpgradeRequest request = new ClientUpgradeRequest(); ClientUpgradeRequest request = new ClientUpgradeRequest();
ourLog.info("Connecting to : {}", echoUri); ourLog.info("Connecting to : {}", echoUri);
Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request);
@@ -127,7 +127,7 @@ public class ExampleServerDstu3IT {
ourCtx = FhirContext.forDstu3(); ourCtx = FhirContext.forDstu3();
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; String ourServerBase = "http://localhost:" + port + "/fhir/";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(new LoggingInterceptor(true));
} }

View File

@@ -119,7 +119,7 @@ public class ExampleServerR4IT {
SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON);
myWebSocketClient.start(); myWebSocketClient.start();
URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); URI echoUri = new URI("ws://localhost:" + port + "/websocket");
ClientUpgradeRequest request = new ClientUpgradeRequest(); ClientUpgradeRequest request = new ClientUpgradeRequest();
ourLog.info("Connecting to : {}", echoUri); ourLog.info("Connecting to : {}", echoUri);
Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request);
@@ -159,7 +159,7 @@ public class ExampleServerR4IT {
ourCtx = FhirContext.forR4(); ourCtx = FhirContext.forR4();
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; String ourServerBase = "http://localhost:" + port + "/fhir/";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(new LoggingInterceptor(true));
} }

View File

@@ -97,7 +97,7 @@ public class ExampleServerR5IT {
SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON);
myWebSocketClient.start(); myWebSocketClient.start();
URI echoUri = new URI("ws://localhost:" + port + "/hapi-fhir-jpaserver/websocket"); URI echoUri = new URI("ws://localhost:" + port + "/websocket");
ClientUpgradeRequest request = new ClientUpgradeRequest(); ClientUpgradeRequest request = new ClientUpgradeRequest();
ourLog.info("Connecting to : {}", echoUri); ourLog.info("Connecting to : {}", echoUri);
Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request);
@@ -129,7 +129,7 @@ public class ExampleServerR5IT {
ourCtx = FhirContext.forR5(); ourCtx = FhirContext.forR5();
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; String ourServerBase = "http://localhost:" + port + "/fhir/";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(new LoggingInterceptor(true));
} }

View File

@@ -99,7 +99,7 @@ public class MultitenantServerR4IT {
ourCtx = FhirContext.forR4(); ourCtx = FhirContext.forR4();
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
String ourServerBase = "http://localhost:" + port + "/hapi-fhir-jpaserver/fhir/"; String ourServerBase = "http://localhost:" + port + "/fhir/";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true)); ourClient.registerInterceptor(new LoggingInterceptor(true));
ourClient.registerInterceptor(ourClientTenantInterceptor); ourClient.registerInterceptor(ourClientTenantInterceptor);