Work on multitenancy
This commit is contained in:
parent
b2d2346228
commit
f7ec41ffc5
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.interceptor.api;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface IInterceptorService extends IInterceptorBroadcaster {
|
||||
|
||||
|
@ -90,4 +91,8 @@ public interface IInterceptorService extends IInterceptorBroadcaster {
|
|||
|
||||
void registerInterceptors(@Nullable Collection<?> theInterceptors);
|
||||
|
||||
/**
|
||||
* Unregisters all interceptors that are indicated by the given callback function returning <code>true</code>
|
||||
*/
|
||||
void unregisterInterceptorsIf(Function<Object, Boolean> theShouldUnregisterFunction);
|
||||
}
|
||||
|
|
|
@ -1321,6 +1321,43 @@ public enum Pointcut {
|
|||
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"
|
||||
),
|
||||
|
||||
/**
|
||||
* <b>Storage Hook:</b>
|
||||
* Invoked before an <code>$expunge</code> operation on all data (expungeEverything) is called.
|
||||
* <p>
|
||||
* Hooks will be passed a reference to a counter containing the current number of records that have been deleted.
|
||||
* If the hook deletes any records, the hook is expected to increment this counter by the number of records deleted.
|
||||
* </p>
|
||||
* Hooks may accept the following parameters:
|
||||
* <ul>
|
||||
* org.hl7.fhir.instance.model.api.IBaseResource - The resource that will be created and needs a tenant ID assigned.
|
||||
* <li>
|
||||
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the servlet request. Note that the bean
|
||||
* properties are not all guaranteed to be populated, depending on how early during processing the
|
||||
* exception occurred.
|
||||
* </li>
|
||||
* <li>
|
||||
* ca.uhn.fhir.rest.server.servlet.ServletRequestDetails - A bean containing details about the request that is about to be processed, including details such as the
|
||||
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
|
||||
* pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will
|
||||
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Hooks should return an instance of <code>ca.uhn.fhir.jpa.model.entity.TenantId</code> or <code>null</code>.
|
||||
* </p>
|
||||
*/
|
||||
STORAGE_TENANT_IDENTIFY_CREATE (
|
||||
// Return type
|
||||
"ca.uhn.fhir.jpa.model.entity.TenantId",
|
||||
// Params
|
||||
"org.hl7.fhir.instance.model.api.IBaseResource",
|
||||
"ca.uhn.fhir.rest.api.server.RequestDetails",
|
||||
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"
|
||||
),
|
||||
|
||||
/**
|
||||
* <b>Performance Tracing Hook:</b>
|
||||
* This hook is invoked when any informational messages generated by the
|
||||
|
|
|
@ -41,6 +41,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class InterceptorService implements IInterceptorService, IInterceptorBroadcaster {
|
||||
|
@ -145,6 +146,22 @@ public class InterceptorService implements IInterceptorService, IInterceptorBroa
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInterceptorsIf(Function<Object, Boolean> theShouldUnregisterFunction) {
|
||||
unregisterInterceptorsIf(theShouldUnregisterFunction, myGlobalInvokers);
|
||||
unregisterInterceptorsIf(theShouldUnregisterFunction, myAnonymousInvokers);
|
||||
}
|
||||
|
||||
private void unregisterInterceptorsIf(Function<Object, Boolean> theShouldUnregisterFunction, ListMultimap<Pointcut, BaseInvoker> theGlobalInvokers) {
|
||||
for (Iterator<Map.Entry<Pointcut, BaseInvoker>> iter = theGlobalInvokers.entries().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry<Pointcut, BaseInvoker> next = iter.next();
|
||||
Object nextInterceptor = next.getValue().getInterceptor();
|
||||
if (theShouldUnregisterFunction.apply(nextInterceptor)) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerThreadLocalInterceptor(Object theInterceptor) {
|
||||
if (!myThreadlocalInvokersEnabled) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
title: "The version of a few dependencies have been bumped to the latest versions
|
||||
(dependent HAPI modules listed in brackets):
|
||||
<ul>
|
||||
<li>Hibernate ORM (JPA): 5.4.6 -> 5.4.10</li>
|
||||
<li>Hibernate ORM (JPA): 5.4.6.Final -> 5.4.11.Final</li>
|
||||
</ul>"
|
||||
- item:
|
||||
type: change
|
||||
|
|
|
@ -390,6 +390,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
ResourceTable entity = new ResourceTable();
|
||||
entity.setResourceType(toResourceName(theResource));
|
||||
|
||||
if (myDaoConfig.isMultiTenancyEnabled()) {
|
||||
// Interceptor call: STORAGE_TENANT_IDENTIFY_CREATE
|
||||
HookParams params = new HookParams()
|
||||
.add(IBaseResource.class, theResource)
|
||||
.add(RequestDetails.class, theRequest)
|
||||
.addIfMatchesType(ServletRequestDetails.class, theRequest);
|
||||
TenantId tenantId = (TenantId) doCallHooksAndReturnObject(theRequest, Pointcut.STORAGE_TENANT_IDENTIFY_CREATE, params);
|
||||
if (tenantId != null) {
|
||||
ourLog.debug("Resource has been assigned tenant ID: {}", tenantId);
|
||||
entity.setTenantId(tenantId);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotBlank(theIfNoneExist)) {
|
||||
Set<ResourcePersistentId> match = myMatchResourceUrlService.processMatchUrl(theIfNoneExist, myResourceType, theRequest);
|
||||
if (match.size() > 1) {
|
||||
|
@ -432,7 +445,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
||||
}
|
||||
|
||||
// Notify JPA interceptors
|
||||
// Interceptor call: STORAGE_PRESTORAGE_RESOURCE_CREATED
|
||||
HookParams hookParams = new HookParams()
|
||||
.add(IBaseResource.class, theResource)
|
||||
.add(RequestDetails.class, theRequest)
|
||||
|
|
|
@ -54,7 +54,6 @@ import java.util.Set;
|
|||
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.OO_SEVERITY_ERROR;
|
||||
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.OO_SEVERITY_INFO;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public abstract class BaseStorageDao {
|
||||
|
@ -161,6 +160,10 @@ public abstract class BaseStorageDao {
|
|||
JpaInterceptorBroadcaster.doCallHooks(getInterceptorBroadcaster(), theRequestDetails, thePointcut, theParams);
|
||||
}
|
||||
|
||||
protected Object doCallHooksAndReturnObject(RequestDetails theRequestDetails, Pointcut thePointcut, HookParams theParams) {
|
||||
return JpaInterceptorBroadcaster.doCallHooksAndReturnObject(getInterceptorBroadcaster(), theRequestDetails, thePointcut, theParams);
|
||||
}
|
||||
|
||||
protected abstract IInterceptorBroadcaster getInterceptorBroadcaster();
|
||||
|
||||
public IBaseOperationOutcome createErrorOperationOutcome(String theMessage, String theCode) {
|
||||
|
|
|
@ -183,6 +183,11 @@ public class DaoConfig {
|
|||
*/
|
||||
private boolean myPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets;
|
||||
|
||||
/**
|
||||
* @since 4.3.0
|
||||
*/
|
||||
private boolean myMultiTenancyEnabled;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -1907,6 +1912,24 @@ public class DaoConfig {
|
|||
setPreExpandValueSetsDefaultCount(Math.min(getPreExpandValueSetsDefaultCount(), getPreExpandValueSetsMaxCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled (default is <code>false</code>) the JPA server will support multitenant queries
|
||||
*
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public void setMultiTenancyEnabled(boolean theMultiTenancyEnabled) {
|
||||
myMultiTenancyEnabled = theMultiTenancyEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled (default is <code>false</code>) the JPA server will support multitenant queries
|
||||
*
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public boolean isMultiTenancyEnabled() {
|
||||
return myMultiTenancyEnabled;
|
||||
}
|
||||
|
||||
public enum StoreMetaSourceInformationEnum {
|
||||
NONE(false, false),
|
||||
SOURCE_URI(true, false),
|
||||
|
|
|
@ -70,6 +70,7 @@ public class DaoSearchParamSynchronizer {
|
|||
theEntity.getParamsQuantity().remove(next);
|
||||
}
|
||||
for (T next : quantitiesToAdd) {
|
||||
next.setTenantId(theEntity.getTenantId());
|
||||
myEntityManager.merge(next);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,84 +1,31 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.TenantId;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryResponseComponent;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
|
||||
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.ServletException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.emptyString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
||||
|
||||
|
@ -86,10 +33,17 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
|||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.setMultiTenancyEnabled(new DaoConfig().isMultiTenancyEnabled());
|
||||
|
||||
myInterceptorRegistry.unregisterInterceptorsIf(t -> t instanceof MyInterceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void beforeDisableResultReuse() {
|
||||
public void before() throws ServletException {
|
||||
super.before();
|
||||
|
||||
myDaoConfig.setMultiTenancyEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,28 +54,57 @@ public class MultitenantR4Test extends BaseJpaR4SystemTest {
|
|||
p.setBirthDate(new Date());
|
||||
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(() -> new IllegalArgumentException());
|
||||
runInTransaction(() -> {
|
||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||
assertNull(resourceTable.getTenantId());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResourceWithTenant() {
|
||||
int expectId = 3;
|
||||
LocalDate expectDate = LocalDate.of(2020, Month.JANUARY, 14);
|
||||
myInterceptorRegistry.registerInterceptor(new MyInterceptor(new TenantId(expectId, expectDate)));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setUserData(JpaConstants.USERDATA_TENANT_ID, 3);
|
||||
p.setUserData(JpaConstants.USERDATA_TENANT_DATE, LocalDate.of(2020, Month.JANUARY, 14));
|
||||
p.addName().setFamily("FAM");
|
||||
p.addIdentifier().setSystem("system").setValue("value");
|
||||
p.setBirthDate(new Date());
|
||||
Long patientId = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(() -> new IllegalArgumentException());
|
||||
assertNull(resourceTable.getTenantId());
|
||||
runInTransaction(() -> {
|
||||
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
|
||||
assertEquals(expectId, resourceTable.getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, resourceTable.getTenantId().getTenantDate());
|
||||
|
||||
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAll();
|
||||
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
|
||||
assertEquals(10, strings.size());
|
||||
assertEquals(expectId, strings.get(0).getTenantId().getTenantId().intValue());
|
||||
assertEquals(expectDate, strings.get(0).getTenantId().getTenantDate());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Interceptor
|
||||
public static class MyInterceptor {
|
||||
|
||||
private final List<TenantId> myTenantIds;
|
||||
|
||||
public MyInterceptor(TenantId theTenantId) {
|
||||
Validate.notNull(theTenantId);
|
||||
myTenantIds = Collections.singletonList(theTenantId);
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_TENANT_IDENTIFY_CREATE)
|
||||
public TenantId tenantIdentifyCreate() {
|
||||
TenantId retVal = myTenantIds.get(0);
|
||||
ourLog.info("Returning tenant ID: {}", retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -20,10 +20,24 @@ package ca.uhn.fhir.jpa.model.entity;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.io.Serializable;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseResourceIndex implements Serializable {
|
||||
|
||||
@Embedded
|
||||
private TenantId myTenantId;
|
||||
|
||||
public TenantId getTenantId() {
|
||||
return myTenantId;
|
||||
}
|
||||
|
||||
public void setTenantId(TenantId theTenantId) {
|
||||
myTenantId = theTenantId;
|
||||
}
|
||||
|
||||
public abstract Long getId();
|
||||
|
||||
public abstract void setId(Long theId);
|
||||
|
|
|
@ -80,17 +80,6 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
|
|||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date myUpdated;
|
||||
|
||||
@Embedded
|
||||
private TenantId myTenantId;
|
||||
|
||||
public TenantId getTenantId() {
|
||||
return myTenantId;
|
||||
}
|
||||
|
||||
public void setTenantId(TenantId theTenantId) {
|
||||
myTenantId = theTenantId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
|
|
|
@ -221,6 +221,13 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@Transient
|
||||
private transient ResourceHistoryTable myCurrentVersionEntity;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceTable() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTag addTag(TagDefinition theTag) {
|
||||
for (ResourceTag next : getTags()) {
|
||||
|
@ -423,6 +430,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceTag> getTags() {
|
||||
if (myTags == null) {
|
||||
myTags = new HashSet<>();
|
||||
|
@ -551,6 +559,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
retVal.setFhirVersion(getFhirVersion());
|
||||
retVal.setDeleted(getDeleted());
|
||||
retVal.setForcedId(getForcedId());
|
||||
retVal.setTenantId(getTenantId());
|
||||
|
||||
retVal.getTags().clear();
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.model.entity;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.time.LocalDate;
|
||||
|
@ -12,6 +15,21 @@ public class TenantId implements Cloneable {
|
|||
@Column(name = "TENANT_DATE", nullable = true)
|
||||
private LocalDate myTenantDate;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TenantId() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TenantId(int theTenantId, LocalDate theTenantDate) {
|
||||
setTenantId(theTenantId);
|
||||
setTenantDate(theTenantDate);
|
||||
}
|
||||
|
||||
public Integer getTenantId() {
|
||||
return myTenantId;
|
||||
}
|
||||
|
@ -36,4 +54,12 @@ public class TenantId implements Cloneable {
|
|||
.setTenantId(getTenantId())
|
||||
.setTenantDate(getTenantDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("id", myTenantId)
|
||||
.append("date", myTenantDate)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
|
||||
public class JpaConstants {
|
||||
|
||||
public static final String USERDATA_TENANT_ID = JpaConstants.class.getName() + "_USERDATA_TENANT_ID";
|
||||
public static final String USERDATA_TENANT_DATE = JpaConstants.class.getName() + "_USERDATA_TENANT_DATE";
|
||||
|
||||
/**
|
||||
* Operation name for the $apply-codesystem-delta-add operation
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
|||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.dialect.PostgreSQL94Dialect;
|
||||
import org.hl7.fhir.dstu2.model.Subscription;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
@ -94,6 +95,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
retVal.setUsername(myDbUsername);
|
||||
retVal.setPassword(myDbPassword);
|
||||
retVal.setDefaultQueryTimeout(20);
|
||||
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
|||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.dialect.PostgreSQL94Dialect;
|
||||
import org.hl7.fhir.dstu2.model.Subscription;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
|
@ -101,6 +102,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
retVal.setUsername(myDbUsername);
|
||||
retVal.setPassword(myDbPassword);
|
||||
retVal.setDefaultQueryTimeout(20);
|
||||
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
|||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.dialect.PostgreSQL94Dialect;
|
||||
import org.hl7.fhir.dstu2.model.Subscription;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
|
@ -86,6 +87,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
retVal.setUsername(myDbUsername);
|
||||
retVal.setPassword(myDbPassword);
|
||||
retVal.setDefaultQueryTimeout(20);
|
||||
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
|||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.dialect.PostgreSQL94Dialect;
|
||||
import org.hl7.fhir.dstu2.model.Subscription;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
|
@ -86,6 +87,7 @@ public class TestR5Config extends BaseJavaConfigR5 {
|
|||
retVal.setUsername(myDbUsername);
|
||||
retVal.setPassword(myDbPassword);
|
||||
retVal.setDefaultQueryTimeout(20);
|
||||
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -645,7 +645,7 @@
|
|||
<jsr305_version>3.0.2</jsr305_version>
|
||||
<flyway_version>6.1.0</flyway_version>
|
||||
<!--<hibernate_version>5.2.10.Final</hibernate_version>-->
|
||||
<hibernate_version>5.4.10.Final</hibernate_version>
|
||||
<hibernate_version>5.4.11.Final</hibernate_version>
|
||||
<!-- Update lucene version when you update hibernate-search version -->
|
||||
<hibernate_search_version>5.11.3.Final</hibernate_search_version>
|
||||
<lucene_version>5.5.5</lucene_version>
|
||||
|
@ -1326,7 +1326,7 @@
|
|||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.9</version>
|
||||
<version>42.2.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
|
|
Loading…
Reference in New Issue