Merge branch 'master' into rel_5_1_0
This commit is contained in:
@@ -134,7 +134,14 @@ public class FhirServerConfigCommon {
|
||||
|
||||
@Bean
|
||||
public PartitionSettings partitionSettings() {
|
||||
return new PartitionSettings();
|
||||
PartitionSettings retVal = new PartitionSettings();
|
||||
|
||||
// Partitioning
|
||||
if (HapiProperties.getPartitioningMultitenancyEnabled()) {
|
||||
retVal.setPartitioningEnabled(true);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ public class HapiProperties {
|
||||
static final String BULK_EXPORT_ENABLED = "bulk.export.enabled";
|
||||
static final String EXPIRE_SEARCH_RESULTS_AFTER_MINS = "retain_cached_searches_mins";
|
||||
static final String MAX_BINARY_SIZE = "max_binary_size";
|
||||
static final String PARTITIONING_MULTITENANCY_ENABLED = "partitioning.multitenancy.enabled";
|
||||
|
||||
private static Properties ourProperties;
|
||||
|
||||
public static boolean isElasticSearchEnabled() {
|
||||
@@ -510,5 +512,9 @@ public class HapiProperties {
|
||||
public static boolean isFhirPathFilterInterceptorEnabled() {
|
||||
return HapiProperties.getBooleanProperty("fhirpath_interceptor.enabled", false);
|
||||
}
|
||||
|
||||
public static boolean getPartitioningMultitenancyEnabled() {
|
||||
return HapiProperties.getBooleanProperty(PARTITIONING_MULTITENANCY_ENABLED, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
||||
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
|
||||
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
@@ -327,6 +329,12 @@ public class JpaRestfulServer extends RestfulServer {
|
||||
partitionSettings.setAllowReferencesAcrossPartitions(mode);
|
||||
partitionSettings.setIncludePartitionInSearchHashes(HapiProperties.getIncludePartitionInSearchHashes());
|
||||
registerProvider(appCtx.getBean(PartitionManagementProvider.class));
|
||||
}
|
||||
|
||||
if (HapiProperties.getPartitioningMultitenancyEnabled()) {
|
||||
registerInterceptor(new RequestTenantPartitionInterceptor());
|
||||
setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy());
|
||||
registerProviders(appCtx.getBean(PartitionManagementProvider.class));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,10 +150,16 @@ email.password=
|
||||
# Enable Websocket Subscription Channel
|
||||
subscription.websocket.enabled=false
|
||||
|
||||
###################################################
|
||||
# EMPI
|
||||
###################################################
|
||||
empi.enabled=false
|
||||
|
||||
# Partitioning
|
||||
###################################################
|
||||
# Partitioning And Multitenancy
|
||||
###################################################
|
||||
partitioning.enabled=false
|
||||
partitioning.cross_partition_reference_mode=NOT_ALLOWED
|
||||
partitioning.partitioning_include_in_search_hashes=true
|
||||
partitioning.multitenancy.enabled=false
|
||||
|
||||
|
||||
140
src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java
Normal file
140
src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java
Normal file
@@ -0,0 +1,140 @@
|
||||
package ca.uhn.fhir.jpa.starter;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.model.util.ProviderConstants;
|
||||
import ca.uhn.fhir.rest.api.CacheControlDirective;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.client.interceptor.UrlTenantSelectionInterceptor;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.CodeType;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.Parameters;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MultitenantServerR4IT {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MultitenantServerR4IT.class);
|
||||
private static IGenericClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static UrlTenantSelectionInterceptor ourClientTenantInterceptor;
|
||||
|
||||
static {
|
||||
HapiProperties.forceReload();
|
||||
HapiProperties.setProperty(HapiProperties.DATASOURCE_URL, "jdbc:h2:mem:dbr4-mt");
|
||||
HapiProperties.setProperty(HapiProperties.FHIR_VERSION, "R4");
|
||||
HapiProperties.setProperty(HapiProperties.SUBSCRIPTION_WEBSOCKET_ENABLED, "true");
|
||||
HapiProperties.setProperty(HapiProperties.PARTITIONING_MULTITENANCY_ENABLED, "true");
|
||||
ourCtx = FhirContext.forR4();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadInTenantA() {
|
||||
ourLog.info("Base URL is: " + HapiProperties.getServerAddress());
|
||||
|
||||
// Create tenant A
|
||||
ourClientTenantInterceptor.setTenantId("DEFAULT");
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.named(ProviderConstants.PARTITION_MANAGEMENT_CREATE_PARTITION)
|
||||
.withParameter(Parameters.class, ProviderConstants.PARTITION_MANAGEMENT_PARTITION_ID, new IntegerType(1))
|
||||
.andParameter(ProviderConstants.PARTITION_MANAGEMENT_PARTITION_NAME, new CodeType("TENANT-A"))
|
||||
.execute();
|
||||
|
||||
|
||||
ourClientTenantInterceptor.setTenantId("TENANT-A");
|
||||
Patient pt = new Patient();
|
||||
pt.addName().setFamily("Family A");
|
||||
ourClient.create().resource(pt).execute().getId();
|
||||
|
||||
Bundle searchResult = ourClient.search().forResource(Patient.class).returnBundle(Bundle.class).cacheControl(new CacheControlDirective().setNoCache(true)).execute();
|
||||
assertEquals(1, searchResult.getEntry().size());
|
||||
Patient pt2 = (Patient) searchResult.getEntry().get(0).getResource();
|
||||
assertEquals("Family A", pt2.getName().get(0).getFamily());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCreateAndReadInTenantB() {
|
||||
ourLog.info("Base URL is: " + HapiProperties.getServerAddress());
|
||||
|
||||
// Create tenant A
|
||||
ourClientTenantInterceptor.setTenantId("DEFAULT");
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.named(ProviderConstants.PARTITION_MANAGEMENT_CREATE_PARTITION)
|
||||
.withParameter(Parameters.class, ProviderConstants.PARTITION_MANAGEMENT_PARTITION_ID, new IntegerType(1))
|
||||
.andParameter(ProviderConstants.PARTITION_MANAGEMENT_PARTITION_NAME, new CodeType("TENANT-B"))
|
||||
.execute();
|
||||
|
||||
|
||||
ourClientTenantInterceptor.setTenantId("TENANT-B");
|
||||
Patient pt = new Patient();
|
||||
pt.addName().setFamily("Family B");
|
||||
ourClient.create().resource(pt).execute().getId();
|
||||
|
||||
Bundle searchResult = ourClient.search().forResource(Patient.class).returnBundle(Bundle.class).cacheControl(new CacheControlDirective().setNoCache(true)).execute();
|
||||
assertEquals(1, searchResult.getEntry().size());
|
||||
Patient pt2 = (Patient) searchResult.getEntry().get(0).getResource();
|
||||
assertEquals("Family B", pt2.getName().get(0).getFamily());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
String path = Paths.get("").toAbsolutePath().toString();
|
||||
|
||||
ourLog.info("Project base path is: {}", path);
|
||||
|
||||
ourServer = new Server(0);
|
||||
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setContextPath("/hapi-fhir-jpaserver");
|
||||
webAppContext.setDisplayName("HAPI FHIR");
|
||||
webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml");
|
||||
webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-starter");
|
||||
webAppContext.setParentLoaderPriority(true);
|
||||
|
||||
ourServer.setHandler(webAppContext);
|
||||
ourServer.start();
|
||||
|
||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
String ourServerBase = HapiProperties.getServerAddress();
|
||||
ourServerBase = "http://localhost:" + ourPort + "/hapi-fhir-jpaserver/fhir/";
|
||||
|
||||
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
|
||||
ourClient.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
ourClientTenantInterceptor = new UrlTenantSelectionInterceptor();
|
||||
ourClient.registerInterceptor(ourClientTenantInterceptor);
|
||||
}
|
||||
|
||||
public static void main(String[] theArgs) throws Exception {
|
||||
ourPort = 8080;
|
||||
beforeClass();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user