Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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