-
Notifications
You must be signed in to change notification settings - Fork 979
/
FhirServerConfigCommon.java
300 lines (255 loc) · 13.7 KB
/
FhirServerConfigCommon.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
package ca.uhn.fhir.jpa.starter.common;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc;
import ca.uhn.fhir.jpa.binstore.DatabaseBinaryContentStorageSvcImpl;
import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode;
import ca.uhn.fhir.jpa.model.entity.StorageSettings;
import ca.uhn.fhir.jpa.starter.AppProperties;
import ca.uhn.fhir.jpa.starter.util.JpaHibernatePropertiesProvider;
import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl;
import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender;
import ca.uhn.fhir.rest.server.mail.MailConfig;
import ca.uhn.fhir.rest.server.mail.MailSvc;
import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.HashSet;
import java.util.stream.Collectors;
/**
* This is the primary configuration file for the example server
*/
@Configuration
@EnableTransactionManagement
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");
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");
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");
if (!Strings.isNullOrEmpty(email.getUsername())) {
ourLog.info("Server is configured to use username '" + email.getUsername() + "' for email");
}
if (!Strings.isNullOrEmpty(email.getPassword())) {
ourLog.info("Server is configured to use a password for email");
}
}
if (appProperties.getSubscription().getResthook_enabled()) {
ourLog.info("REST-hook subscriptions enabled");
}
if (appProperties.getSubscription().getEmail() != null) {
ourLog.info("Email subscriptions enabled");
}
if (appProperties.getEnable_index_contained_resource() == Boolean.TRUE) {
ourLog.info("Indexed on contained resource enabled");
}
}
/**
* Configure FHIR properties around the JPA server via this bean
*/
@Bean
public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
JpaStorageSettings jpaStorageSettings = new JpaStorageSettings();
jpaStorageSettings.setIndexMissingFields(
appProperties.getEnable_index_missing_fields()
? StorageSettings.IndexEnabledEnum.ENABLED
: StorageSettings.IndexEnabledEnum.DISABLED);
jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(
appProperties.getAuto_create_placeholder_reference_targets());
jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths());
jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(
appProperties.getEnforce_referential_integrity_on_write());
jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(
appProperties.getEnforce_referential_integrity_on_delete());
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
jpaStorageSettings.setAllowMultipleDelete(appProperties.getAllow_multiple_delete());
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
jpaStorageSettings.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled());
jpaStorageSettings.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled());
jpaStorageSettings.setExpungeEnabled(appProperties.getExpunge_enabled());
jpaStorageSettings.setLanguageSearchParameterEnabled(appProperties.getLanguage_search_parameter_enabled());
if (appProperties.getSubscription() != null
&& appProperties.getSubscription().getEmail() != null)
jpaStorageSettings.setEmailFromAddress(
appProperties.getSubscription().getEmail().getFrom());
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));
Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis();
jpaStorageSettings.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis);
Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins();
jpaStorageSettings.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000);
if (appProperties.getSubscription() != null) {
// Subscriptions are enabled by channel type
if (appProperties.getSubscription().getResthook_enabled()) {
ourLog.info("Enabling REST-hook subscriptions");
jpaStorageSettings.addSupportedSubscriptionType(
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
}
if (appProperties.getSubscription().getEmail() != null) {
ourLog.info("Enabling email subscriptions");
jpaStorageSettings.addSupportedSubscriptionType(
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
}
if (appProperties.getSubscription().getWebsocket_enabled()) {
ourLog.info("Enabling websocket subscriptions");
jpaStorageSettings.addSupportedSubscriptionType(
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
}
}
jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls()));
jpaStorageSettings.setTreatReferencesAsLogical(new HashSet<>(appProperties.getLogical_urls()));
if (appProperties.getLastn_enabled()) {
jpaStorageSettings.setLastNEnabled(true);
}
if (appProperties.getInline_resource_storage_below_size() != 0) {
jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
}
jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
if (appProperties.getAllowed_bundle_types() != null) {
jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream()
.map(BundleType::toCode)
.collect(Collectors.toSet()));
}
jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(
appProperties.getDefer_indexing_for_codesystems_of_size());
jpaStorageSettings.setResourceClientIdStrategy(appProperties.getClient_id_strategy());
ourLog.info("Server configured to use '" + appProperties.getClient_id_strategy() + "' Client ID Strategy");
// 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");
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");
}
}
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");
}
//to Disable the Resource History
jpaStorageSettings.setResourceDbHistoryEnabled(appProperties.getResource_dbhistory_enabled());
// Parallel Batch GET execution settings
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size());
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size());
if (appProperties.getMdm_enabled()) {
// MDM requires the subscription of type message
ourLog.info("Enabling message subscriptions");
jpaStorageSettings.addSupportedSubscriptionType(
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.MESSAGE);
}
storageSettings(appProperties, jpaStorageSettings);
return jpaStorageSettings;
}
@Bean
public YamlPropertySourceLoader yamlPropertySourceLoader() {
return new YamlPropertySourceLoader();
}
@Bean
public PartitionSettings partitionSettings(AppProperties appProperties) {
PartitionSettings retVal = new PartitionSettings();
// Partitioning
if (appProperties.getPartitioning() != null) {
retVal.setPartitioningEnabled(true);
retVal.setIncludePartitionInSearchHashes(
appProperties.getPartitioning().getPartitioning_include_in_search_hashes());
if (appProperties.getPartitioning().getAllow_references_across_partitions()) {
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED);
} else {
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED);
}
}
return retVal;
}
@Primary
@Bean
public HibernatePropertiesProvider jpaStarterDialectProvider(
LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
}
protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) {
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
jpaStorageSettings.setDefaultSearchParamsCanBeOverridden(
appProperties.getAllow_override_default_search_params());
if (appProperties.getSubscription() != null
&& appProperties.getSubscription().getEmail() != null)
jpaStorageSettings.setEmailFromAddress(
appProperties.getSubscription().getEmail().getFrom());
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
return jpaStorageSettings;
}
@Lazy
@Bean
public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
DatabaseBinaryContentStorageSvcImpl binaryStorageSvc = new DatabaseBinaryContentStorageSvcImpl();
if (appProperties.getMax_binary_size() != null) {
binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
}
return binaryStorageSvc;
}
@Bean
public IEmailSender emailSender(AppProperties appProperties) {
if (appProperties.getSubscription() != null
&& appProperties.getSubscription().getEmail() != null) {
return buildEmailSender(appProperties.getSubscription().getEmail());
}
// Return a dummy anonymous function instead of null. Spring does not like null beans.
// TODO Get the signature of
// ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory
// changed so it does not require an instance of an IEmailSender
return theDetails -> {};
}
private static IEmailSender buildEmailSender(AppProperties.Subscription.Email email) {
return new EmailSenderImpl(new MailSvc(new MailConfig()
.setSmtpHostname(email.getHost())
.setSmtpPort(email.getPort())
.setSmtpUsername(email.getUsername())
.setSmtpPassword(email.getPassword())
.setSmtpUseStartTLS(email.getStartTlsEnable())));
}
}