Skip to content

Commit

Permalink
Add MSSql Support, fix multiple versions dialects of Postgres being u…
Browse files Browse the repository at this point in the history
…sed (#637)

* Add MSSql Support, fix multiple versions dialects of Postgres being used

* Fix JPA Hibernate Properties provider
  • Loading branch information
JPercival authored Oct 14, 2022
1 parent f4c4d6a commit 7f02947
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 70 deletions.
73 changes: 5 additions & 68 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@
"-Dhapi.fhir.bulk_export_enabled=false",
"-Dspring.batch.job.enabled=false"
],
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
}
},
{
"type": "java",
Expand All @@ -42,17 +31,6 @@
"-Dhapi.fhir.bulk_export_enabled=false",
"-Dspring.batch.job.enabled=false"
],
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
},
"classPaths": [
"$Auto",
"$Runtime"
Expand All @@ -65,25 +43,17 @@
"mainClass": "org.opencds.cqf.ruler.Application",
"projectName": "cqf-ruler-server",
"vmArgs": [
"-XX:TieredStopAtLevel=1",
"-Ddebug=true",
"-Dloader.debug=true",
"-Dspring.datasource.url=jdbc:postgresql://localhost:5432/postgres",
"-Dspring.datasource.username=postgres",
"-Dspring.datasource.password=",
"-Dspring.datasource.driverClassName=org.postgresql.Driver",
"-Dspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect",
"-Dspring.jpa.properties.hibernate.dialect=ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect",
"-Dhapi.fhir.bulk_export_enabled=false",
"-Dspring.batch.job.enabled=false"
],
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
},
"classPaths": [
"$Auto",
"$Runtime"
Expand All @@ -103,17 +73,6 @@
"-Dhapi.fhir.bulk_export_enabled=false",
"-Dspring.batch.job.enabled=false"
],
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
},
"classPaths": [
"$Auto",
"$Runtime"
Expand All @@ -124,35 +83,13 @@
"name": "Attach",
"request": "attach",
"hostName": "localhost",
"port": "5005",
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
}
"port": "5005"
},
{
"type": "java",
"name": "Launch Current File",
"request": "launch",
"mainClass": "${file}",
"stepFilters": {
"classNameFilters": [
"java.*",
"javax.*",
"com.sun.*",
"sun.*",
"sunw.*",
"org.omg.*",
"org.springframework.aop.*"
]
}
}
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.debug.settings.stepping.skipClasses": [
"$JDK",
"java.lang.ClassLoader",
"org.springframework.aop.*"
],
"java.errors.incompleteClasspath.severity": "ignore",
"java.test.config": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package org.opencds.cqf.ruler.config;

import java.util.HashSet;
import java.util.Optional;

import org.hl7.fhir.dstu2.model.Subscription;
import org.opencds.cqf.external.AppProperties;
import org.opencds.cqf.ruler.provider.PatchedJpaHibernatePropertiesProvider;
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 com.google.common.base.Strings;

import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc;
import ca.uhn.fhir.jpa.binstore.DatabaseBlobBinaryStorageSvcImpl;
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.ModelConfig;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
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.IMailSvc;
import ca.uhn.fhir.rest.server.mail.MailConfig;
import ca.uhn.fhir.rest.server.mail.MailSvc;

@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");

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 the JPA server via this bean
*/
@Bean
public DaoConfig daoConfig(AppProperties appProperties) {
DaoConfig retVal = new DaoConfig();

retVal.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? DaoConfig.IndexEnabledEnum.ENABLED
: DaoConfig.IndexEnabledEnum.DISABLED);
retVal.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets());
retVal.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write());
retVal.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete());
retVal.setAllowContainsSearches(appProperties.getAllow_contains_searches());
retVal.setAllowMultipleDelete(appProperties.getAllow_multiple_delete());
retVal.setAllowExternalReferences(appProperties.getAllow_external_references());
retVal.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled());
retVal.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled());
retVal.setExpungeEnabled(appProperties.getExpunge_enabled());
if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
retVal.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());

Integer maxFetchSize = appProperties.getMax_page_size();
retVal.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();
retVal.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis);

Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins();
retVal.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");
retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
}
if (appProperties.getSubscription().getEmail() != null) {
ourLog.info("Enabling email subscriptions");
retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
}
if (appProperties.getSubscription().getWebsocket_enabled()) {
ourLog.info("Enabling websocket subscriptions");
retVal.addSupportedSubscriptionType(
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
}
}

retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
retVal.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
retVal.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls()));

return retVal;
}

@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 PatchedJpaHibernatePropertiesProvider(myEntityManagerFactory);
}

@Bean
public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) {
ModelConfig modelConfig = daoConfig.getModelConfig();
modelConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches());
modelConfig.setAllowExternalReferences(appProperties.getAllow_external_references());
modelConfig.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params());
if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
modelConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());

// You can enable these if you want to support Subscriptions from your server
if (appProperties.getSubscription() != null && appProperties.getSubscription().getResthook_enabled() != null) {
modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.RESTHOOK);
}

if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.EMAIL);
}

modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());

modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
modelConfig.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
return modelConfig;
}

/**
* The following bean configures the database connection. The 'url' property
* value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates
* that the server should save resources in a
* directory called "jpaserver_derby_files".
* <p>
* A URL to a remote database could also be placed here, along with login
* credentials and other properties supported by BasicDataSource.
*/
/*
* @Bean(destroyMethod = "close")
* public BasicDataSource dataSource() throws ClassNotFoundException,
* NoSuchMethodException, IllegalAccessException, InvocationTargetException,
* InstantiationException {
* BasicDataSource retVal = new BasicDataSource();
* Driver driver = (Driver)
* Class.forName(HapiProperties.getDataSourceDriver()).getConstructor().
* newInstance();
* retVal.setDriver(driver);
* retVal.setUrl(HapiProperties.getDataSourceUrl());
* retVal.setUsername(HapiProperties.getDataSourceUsername());
* retVal.setPassword(HapiProperties.getDataSourcePassword());
* retVal.setMaxTotal(HapiProperties.getDataSourceMaxPoolSize());
* return retVal;
* }
*/

@Lazy
@Bean
public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();

if (appProperties.getMax_binary_size() != null) {
binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
}

return binaryStorageSvc;
}

@Bean
public IEmailSender emailSender(AppProperties appProperties,
Optional<SubscriptionDeliveryHandlerFactory> subscriptionDeliveryHandlerFactory) {
if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
MailConfig mailConfig = new MailConfig();

AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
mailConfig.setSmtpHostname(email.getHost());
mailConfig.setSmtpPort(email.getPort());
mailConfig.setSmtpUsername(email.getUsername());
mailConfig.setSmtpPassword(email.getPassword());
mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable());

IMailSvc mailSvc = new MailSvc(mailConfig);
IEmailSender emailSender = new EmailSenderImpl(mailSvc);

subscriptionDeliveryHandlerFactory
.ifPresent(theSubscriptionDeliveryHandlerFactory -> theSubscriptionDeliveryHandlerFactory
.setEmailSender(emailSender));

return emailSender;
}

return null;
}
}
Loading

0 comments on commit 7f02947

Please sign in to comment.