Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ local.properties
.factorypath
.project
.settings
.springBeans
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate of line 121

.sts4-cache

# Code Recommenders
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ HAPI looks in the environment variables for properties in the [application.yaml]

### Configuration via overridden application.yaml file and using Docker

You can customize HAPI by telling HAPI to look for the configuration file in a different location, eg.:
You can customize HAPI by telling HAPI to look for the configuration file in a different location, e.g.:

```
docker run -p 8090:8080 -v $(pwd)/yourLocalFolder:/configs -e "--spring.config.location=file:///configs/another.application.yaml" hapiproject/hapi:latest
Expand Down Expand Up @@ -237,7 +237,7 @@ The Server will then be accessible at http://localhost:8888/fhir and the Capabil
```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 the following:
Server will then be accessible at http://localhost:8080/ and e.g. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to the following:

```yaml
tester:
Expand All @@ -253,7 +253,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos
```bash
mvn clean package spring-boot:repackage -DskipTests=true -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 your overlay configuration in the application.yaml to the following:
Server will then be accessible at http://localhost:8080/ and e.g. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to the following:

```yaml
tester:
Expand All @@ -268,7 +268,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos
```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 your overlay configuration in the application.yaml to the following:
Server will then be accessible at http://localhost:8080/ and e.g. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to the following:

```yaml
tester:
Expand All @@ -284,7 +284,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos
```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 your overlay configuration in the application.yaml to the following:
Server will then be accessible at http://localhost:8080/ and e.g. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to the following:

```yaml
tester:
Expand Down Expand Up @@ -384,7 +384,7 @@ Several template files that can be customized are found in the following directo

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.

Most people who are using HAPI FHIR JPA as a server that is accessible to other people (whether internally on your network or publically hosted) will do so using an Application Server, such as [Apache Tomcat](http://tomcat.apache.org/) or [Jetty](https://www.eclipse.org/jetty/). Note that any Servlet 3.0+ compatible Web Container will work (e.g Wildfly, Websphere, etc.).
Most people who are using HAPI FHIR JPA as a server that is accessible to other people (whether internally on your network or publicly hosted) will do so using an Application Server, such as [Apache Tomcat](http://tomcat.apache.org/) or [Jetty](https://www.eclipse.org/jetty/). Note that any Servlet 3.0+ compatible Web Container will work (e.g. Wildfly, Websphere, etc.).

Tomcat is very popular, so it is a good choice simply because you will be able to find many tutorials online. Jetty is a great alternative due to its fast startup time and good overall performance.

Expand All @@ -402,7 +402,7 @@ Again, browse to the following link to use the server (note that the port 8080 m

You will then be able to access the JPA server e.g. using http://localhost:8080/fhir/metadata.

If you would like it to be hosted at eg. hapi-fhir-jpaserver, eg. http://localhost:8080/hapi-fhir-jpaserver/ or http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata - then rename the WAR file to ```hapi-fhir-jpaserver.war``` and adjust the overlay configuration accordingly e.g.
If you would like it to be hosted at e.g. hapi-fhir-jpaserver, e.g. http://localhost:8080/hapi-fhir-jpaserver/ or http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata - then rename the WAR file to ```hapi-fhir-jpaserver.war``` and adjust the overlay configuration accordingly e.g.

```yaml
tester:
Expand Down Expand Up @@ -525,7 +525,7 @@ Set `hapi.fhir.store_resource_in_lucene_index_enabled` in the [application.yaml]

## Changing cached search results time

It is possible to change the cached search results time. The option `reuse_cached_search_results_millis` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) is 6000 miliseconds by default.
It is possible to change the cached search results time. The option `reuse_cached_search_results_millis` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) is 6000 milliseconds by default.
Set `reuse_cached_search_results_millis: -1` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to ignore the cache time every search.

## Build the distroless variant of the image (for lower footprint and improved security)
Expand Down
8 changes: 4 additions & 4 deletions charts/hapi-fhir-jpaserver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver

## Requirements

| Repository | Name | Version |
|------------|------|---------|
| oci://registry-1.docker.io/bitnamicharts | common | 2.31.3 |
| Repository | Name | Version |
|------------------------------------------|------------|---------|
| oci://registry-1.docker.io/bitnamicharts | common | 2.31.3 |
| oci://registry-1.docker.io/bitnamicharts | postgresql | 16.7.11 |

## Values
Expand Down Expand Up @@ -98,7 +98,7 @@ INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver]
INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver
```

## Enable Distributed Tracing based on the OpenTelemtry Java Agent
## Enable Distributed Tracing based on the OpenTelemetry Java Agent

The container image includes the [OpenTelemetry Java agent JAR](https://github.com/open-telemetry/opentelemetry-java-instrumentation)
which can be used to enable distributed tracing. It can be configured entirely using environment variables,
Expand Down
2 changes: 1 addition & 1 deletion charts/hapi-fhir-jpaserver/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver]
INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver
```

## Enable Distributed Tracing based on the OpenTelemtry Java Agent
## Enable Distributed Tracing based on the OpenTelemetry Java Agent

The container image includes the [OpenTelemetry Java agent JAR](https://github.com/open-telemetry/opentelemetry-java-instrumentation)
which can be used to enable distributed tracing. It can be configured entirely using environment variables,
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
<scope>provided</scope>
</dependency>

<!-- If you are using HAPI narrative generation, you will need to include Thymeleaf as well. Otherwise the following can be omitted. -->
<!-- If you are using HAPI narrative generation, you will need to include Thymeleaf as well. Otherwise, the following can be omitted. -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ca/uhn/fhir/jpa/starter/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static void main(String[] args) {

SpringApplication.run(Application.class, args);

// Server is now accessible at eg. http://localhost:8080/fhir/metadata
// Server is now accessible at e.g. http://localhost:8080/fhir/metadata
// UI is now accessible at http://localhost:8080/
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@
import org.springframework.beans.factory.annotation.Qualifier;

import java.io.IOException;
import java.io.Serial;
import java.util.stream.Collectors;

import static org.opencds.cqf.fhir.cr.hapi.config.test.TestCdsHooksConfig.CDS_HOOKS_OBJECT_MAPPER_FACTORY;

@Configurable
public class CdsHooksServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(CdsHooksServlet.class);

@Serial
private static final long serialVersionUID = 1L;

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,8 @@ private boolean resourceExists(IBaseResource resource) {
return true;
}
if (resource instanceof IBaseBundle) {
return BundleUtil.toListOfEntries(fhirContext, (IBaseBundle) resource)
.size()
> 0;
return !BundleUtil.toListOfEntries(fhirContext, (IBaseBundle) resource)
.isEmpty();
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,43 @@ public class FhirServerConfigCommon {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class);

public FhirServerConfigCommon(AppProperties appProperties) {
ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny")
+ " contains searches");
ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny")
+ " multiple deletes");
ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny")
+ " external references");
ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable")
+ " DAO scheduling");
ourLog.info("Server configured to " + (appProperties.getDelete_expunge_enabled() ? "enable" : "disable")
+ " delete expunges");
ourLog.info(
"Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges");
"Server configured to {} contains searches",
appProperties.getAllow_contains_searches() ? "allow" : "deny");
ourLog.info(
"Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny")
+ " overriding default search params");
ourLog.info("Server configured to "
+ (appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable")
+ " auto-creating placeholder references");
"Server configured to {} multiple deletes",
appProperties.getAllow_multiple_delete() ? "allow" : "deny");
ourLog.info(
"Server configured to {} external references",
appProperties.getAllow_external_references() ? "allow" : "deny");
ourLog.info(
"Server configured to {} DAO scheduling",
appProperties.getDao_scheduling_enabled() ? "enable" : "disable");
ourLog.info(
"Server configured to {} delete expunges",
appProperties.getDelete_expunge_enabled() ? "enable" : "disable");
ourLog.info("Server configured to {} expunges", appProperties.getExpunge_enabled() ? "enable" : "disable");
ourLog.info(
"Server configured to {} overriding default search params",
appProperties.getAllow_override_default_search_params() ? "allow" : "deny");
ourLog.info(
"Server configured to {} auto-creating placeholder references",
appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable");
ourLog.info(
"Server configured to auto-version references at paths {}",
appProperties.getAuto_version_reference_at_paths());

if (appProperties.getSubscription().getEmail() != null) {
AppProperties.Subscription.Email email =
appProperties.getSubscription().getEmail();
ourLog.info("Server is configured to enable email with host '" + email.getHost() + "' and port "
+ email.getPort());
ourLog.info("Server will use '" + email.getFrom() + "' as the from email address");
ourLog.info(
"Server is configured to enable email with host '{}' and port {}",
email.getHost(),
email.getPort());
ourLog.info("Server will use '{}' as the from email address", email.getFrom());

if (!Strings.isNullOrEmpty(email.getUsername())) {
ourLog.info("Server is configured to use username '" + email.getUsername() + "' for email");
ourLog.info("Server is configured to use username '{}' for email", email.getUsername());
}

if (!Strings.isNullOrEmpty(email.getPassword())) {
Expand All @@ -89,17 +95,19 @@ public FhirServerConfigCommon(AppProperties appProperties) {
ourLog.info("Indexed on contained resource enabled");
}

ourLog.info("Server configured to " + (appProperties.getPre_expand_value_sets() ? "enable" : "disable")
+ " value set pre-expansion");
ourLog.info(
"Server configured to " + (appProperties.getEnable_task_pre_expand_value_sets() ? "enable" : "disable")
+ " value set pre-expansion task");
ourLog.info("Server configured for pre-expand value set default count of "
+ (appProperties.getPre_expand_value_sets_default_count().toString()));
ourLog.info("Server configured for pre-expand value set max count of "
+ (appProperties.getPre_expand_value_sets_max_count().toString()));
ourLog.info("Server configured for maximum expansion size of "
+ (appProperties.getMaximum_expansion_size().toString()));
"Server configured to {} value set pre-expansion",
appProperties.getPre_expand_value_sets() ? "enable" : "disable");
ourLog.info(
"Server configured to {} value set pre-expansion task",
appProperties.getEnable_task_pre_expand_value_sets() ? "enable" : "disable");
ourLog.info(
"Server configured for pre-expand value set default count of {}",
appProperties.getPre_expand_value_sets_default_count());
ourLog.info(
"Server configured for pre-expand value set max count of {}",
appProperties.getPre_expand_value_sets_max_count());
ourLog.info("Server configured for maximum expansion size of {}", appProperties.getMaximum_expansion_size());
}

@Bean
Expand Down Expand Up @@ -189,8 +197,9 @@ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {

Integer maxFetchSize = appProperties.getMax_page_size();
jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize);
ourLog.info("Server configured to have a maximum fetch size of "
+ (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize));
ourLog.info(
"Server configured to have a maximum fetch size of {}",
maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize);

Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis();
jpaStorageSettings.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
Expand Down Expand Up @@ -232,19 +241,21 @@ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
// Set and/or recommend default Server ID Strategy of UUID when using the ANY Client ID Strategy
if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) {
if (appProperties.getServer_id_strategy() == null) {
ourLog.info("Defaulting server to use '" + JpaStorageSettings.IdStrategyEnum.UUID
+ "' Server ID Strategy when using the '" + JpaStorageSettings.ClientIdStrategyEnum.ANY
+ "' Client ID Strategy");
ourLog.info(
"Defaulting server to use '{}' Server ID Strategy when using the '{}' Client ID Strategy",
JpaStorageSettings.IdStrategyEnum.UUID,
JpaStorageSettings.ClientIdStrategyEnum.ANY);
appProperties.setServer_id_strategy(JpaStorageSettings.IdStrategyEnum.UUID);
} else if (appProperties.getServer_id_strategy() != JpaStorageSettings.IdStrategyEnum.UUID) {
ourLog.warn("WARNING: '" + JpaStorageSettings.IdStrategyEnum.UUID
+ "' Server ID Strategy is highly recommended when using the '"
+ JpaStorageSettings.ClientIdStrategyEnum.ANY + "' Client ID Strategy");
ourLog.warn(
"WARNING: '{}' Server ID Strategy is highly recommended when using the '{}' Client ID Strategy",
JpaStorageSettings.IdStrategyEnum.UUID,
JpaStorageSettings.ClientIdStrategyEnum.ANY);
}
}
if (appProperties.getServer_id_strategy() != null) {
jpaStorageSettings.setResourceServerIdStrategy(appProperties.getServer_id_strategy());
ourLog.info("Server configured to use '" + appProperties.getServer_id_strategy() + "' Server ID Strategy");
ourLog.info("Server configured to use '{}' Server ID Strategy", appProperties.getServer_id_strategy());
}

// to Disable the Resource History
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) {

List<String> allAllowedCORSOrigins = appProperties.getCors().getAllowed_origin();
allAllowedCORSOrigins.forEach(config::addAllowedOriginPattern);
ourLog.info("CORS allows the following origins: " + String.join(", ", allAllowedCORSOrigins));
ourLog.info("CORS allows the following origins: {}", String.join(", ", allAllowedCORSOrigins));

config.addExposedHeader("Location");
config.addExposedHeader("Content-Location");
Expand Down Expand Up @@ -467,9 +467,7 @@ public RestfulServer restfulServer(
registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses());

// register the IPS Provider
if (!theIpsOperationProvider.isEmpty()) {
fhirServer.registerProvider(theIpsOperationProvider.get());
}
theIpsOperationProvider.ifPresent(fhirServer::registerProvider);

if (appProperties.getUserRequestRetryVersionConflictsInterceptorEnabled()) {
fhirServer.registerInterceptor(new UserRequestRetryVersionConflictsInterceptor());
Expand Down Expand Up @@ -500,7 +498,7 @@ private void registerCustomInterceptors(
throw new ConfigurationException("Interceptor class was not found on classpath: " + className, e);
}

// first check if the class a Bean in the app context
// first check if the class is a Bean in the app context
Object interceptor = null;
try {
interceptor = theAppContext.getBean(clazz);
Expand Down Expand Up @@ -541,7 +539,7 @@ private void registerCustomProviders(
throw new ConfigurationException("Provider class was not found on classpath: " + className, e);
}

// first check if the class a Bean in the app context
// first check if the class is a Bean in the app context
Object provider = null;
try {
provider = theAppContext.getBean(clazz);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap()
.setLoadSynchronous(true)
.add(StructureDefinition.SP_KIND, new TokenParam("resource")));
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size()).stream()
.map(StructureDefinition.class::cast)
.collect(Collectors.groupingBy(StructureDefinition::getType));

structureDefintions.forEach((key, value) -> {
structureDefinitions.forEach((key, value) -> {
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
repositoryValidatingRuleBuilder
.forResourcesOfType(key)
Expand Down
Loading
Loading