Improve indexing on JPA server in anticipation of a new indexing
strategy in HAPI FHIR 3.5.0
This commit is contained in:
parent
e58779d484
commit
2f2900e837
|
@ -58,6 +58,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -70,6 +70,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
|
|||
return FhirServerConfigCommon.getDataSource(env);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource(), fhirContextDstu3());
|
||||
|
|
|
@ -73,6 +73,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
|
|||
return FhirServerConfigCommon.getDataSource(env);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource(), fhirContextDstu2());
|
||||
|
|
|
@ -188,6 +188,7 @@ public class Constants {
|
|||
public static final String PARAM_GRAPHQL_QUERY = "query";
|
||||
public static final String HEADER_X_CACHE = "X-Cache";
|
||||
public static final String HEADER_X_SECURITY_CONTEXT = "X-Security-Context";
|
||||
public static final String POWERED_BY_HEADER = "X-Powered-By";
|
||||
|
||||
static {
|
||||
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);
|
||||
|
|
|
@ -63,6 +63,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 {
|
|||
@Qualifier("jpaProperties")
|
||||
private Properties myJpaProperties;
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -66,6 +66,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -66,6 +66,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.config;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -28,6 +28,8 @@ import ca.uhn.fhir.jpa.sp.SearchParamPresenceSvcImpl;
|
|||
import ca.uhn.fhir.jpa.subscription.email.SubscriptionEmailInterceptor;
|
||||
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
||||
import ca.uhn.fhir.jpa.subscription.websocket.SubscriptionWebsocketInterceptor;
|
||||
import ca.uhn.fhir.jpa.util.IReindexController;
|
||||
import ca.uhn.fhir.jpa.util.ReindexController;
|
||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -48,6 +50,7 @@ import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
|
|||
import org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Configuration
|
||||
|
@ -63,14 +66,13 @@ public abstract class BaseConfig implements SchedulingConfigurer {
|
|||
private ApplicationContext myAppCtx;
|
||||
|
||||
@Override
|
||||
public void configureTasks(ScheduledTaskRegistrar theTaskRegistrar) {
|
||||
public void configureTasks(@Nonnull ScheduledTaskRegistrar theTaskRegistrar) {
|
||||
theTaskRegistrar.setTaskScheduler(taskScheduler());
|
||||
}
|
||||
|
||||
@Bean(autowire = Autowire.BY_TYPE)
|
||||
public DatabaseBackedPagingProvider databaseBackedPagingProvider() {
|
||||
DatabaseBackedPagingProvider retVal = new DatabaseBackedPagingProvider();
|
||||
return retVal;
|
||||
return new DatabaseBackedPagingProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,6 +98,11 @@ public abstract class BaseConfig implements SchedulingConfigurer {
|
|||
return new HibernateJpaDialect();
|
||||
}
|
||||
|
||||
@Bean
|
||||
private IReindexController reindexController() {
|
||||
return new ReindexController();
|
||||
}
|
||||
|
||||
@Bean()
|
||||
public ScheduledExecutorFactoryBean scheduledExecutorService() {
|
||||
ScheduledExecutorFactoryBean b = new ScheduledExecutorFactoryBean();
|
||||
|
@ -167,5 +174,4 @@ public abstract class BaseConfig implements SchedulingConfigurer {
|
|||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
|
|||
import ca.uhn.fhir.jpa.util.DeleteConflict;
|
||||
import ca.uhn.fhir.jpa.util.ExpungeOptions;
|
||||
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
||||
import ca.uhn.fhir.jpa.util.ReindexController;
|
||||
import ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils;
|
||||
import ca.uhn.fhir.jpa.util.xmlpatch.XmlPatchUtils;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
|
@ -46,7 +47,6 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||
import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.*;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
@ -61,6 +61,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
@ -88,6 +89,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
private String mySecondaryPrimaryKeyParamName;
|
||||
@Autowired
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
@Autowired
|
||||
private ReindexController myReindexController;
|
||||
|
||||
@Override
|
||||
public void addTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||
|
@ -97,7 +100,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
for (BaseTag next : new ArrayList<>(entity.getTags())) {
|
||||
if (ObjectUtil.equals(next.getTag().getTagType(), theTagType) &&
|
||||
ObjectUtil.equals(next.getTag().getSystem(), theScheme) &&
|
||||
|
@ -105,7 +107,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return;
|
||||
}
|
||||
}
|
||||
//@formatter:on
|
||||
|
||||
entity.setHasTags(true);
|
||||
|
||||
|
@ -459,7 +460,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return outcome;
|
||||
}
|
||||
|
||||
|
||||
private <MT extends IBaseMetaType> void doMetaAdd(MT theMetaAdd, BaseHasResource entity) {
|
||||
List<TagDefinition> tags = toTagList(theMetaAdd);
|
||||
|
||||
|
@ -538,7 +538,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return doExpunge(getResourceName(), null, null, theExpungeOptions);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TagList getAllResourceTags(RequestDetails theRequestDetails) {
|
||||
// Notify interceptors
|
||||
|
@ -630,7 +629,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
Integer updatedCount = txTemplate.execute(new TransactionCallback<Integer>() {
|
||||
@Override
|
||||
public @NonNull
|
||||
Integer doInTransaction(TransactionStatus theStatus) {
|
||||
Integer doInTransaction(@Nonnull TransactionStatus theStatus) {
|
||||
return myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
}
|
||||
});
|
||||
|
@ -640,6 +639,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
mySearchParamRegistry.requestRefresh();
|
||||
myReindexController.requestReindex();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,32 +52,6 @@ public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<Se
|
|||
markResourcesMatchingExpressionAsNeedingReindexing(reindex, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called once per minute to perform any required re-indexing. During most passes this will
|
||||
* just check and find that there are no resources requiring re-indexing. In that case the method just returns
|
||||
* immediately. If the search finds that some resources require reindexing, the system will do a bunch of
|
||||
* reindexing and then return.
|
||||
*/
|
||||
@Override
|
||||
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void performReindexingPass() {
|
||||
if (getConfig().isSchedulingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Integer count = mySystemDao.performReindexingPass(100);
|
||||
for (int i = 0; i < 50 && count != null && count != 0; i++) {
|
||||
count = mySystemDao.performReindexingPass(100);
|
||||
try {
|
||||
Thread.sleep(DateUtils.MILLIS_PER_SECOND);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
|
||||
super.postPersist(theEntity, theResource);
|
||||
|
|
|
@ -24,6 +24,4 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
|
||||
public interface IFhirResourceDaoSearchParameter<T extends IBaseResource> extends IFhirResourceDao<T> {
|
||||
|
||||
void performReindexingPass();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,26 +1,16 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
|
@ -30,9 +20,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -43,8 +33,6 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
|
||||
public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoSearchParameterDstu3.class);
|
||||
|
||||
@Autowired
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
|
||||
|
@ -57,31 +45,6 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
markResourcesMatchingExpressionAsNeedingReindexing(reindex, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called once per minute to perform any required re-indexing. During most passes this will
|
||||
* just check and find that there are no resources requiring re-indexing. In that case the method just returns
|
||||
* immediately. If the search finds that some resources require reindexing, the system will do multiple
|
||||
* reindexing passes and then return.
|
||||
*/
|
||||
@Override
|
||||
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void performReindexingPass() {
|
||||
if (getConfig().isSchedulingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Integer count = mySystemDao.performReindexingPass(100);
|
||||
for (int i = 0; i < 50 && count != null && count != 0; i++) {
|
||||
count = mySystemDao.performReindexingPass(100);
|
||||
try {
|
||||
Thread.sleep(DateUtils.MILLIS_PER_SECOND);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
|
||||
|
|
|
@ -8,13 +8,9 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -29,9 +25,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -51,31 +47,6 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchPa
|
|||
markResourcesMatchingExpressionAsNeedingReindexing(reindex, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called once per minute to perform any required re-indexing. During most passes this will
|
||||
* just check and find that there are no resources requiring re-indexing. In that case the method just returns
|
||||
* immediately. If the search finds that some resources require reindexing, the system will do multiple
|
||||
* reindexing passes and then return.
|
||||
*/
|
||||
@Override
|
||||
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void performReindexingPass() {
|
||||
if (getConfig().isSchedulingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Integer count = mySystemDao.performReindexingPass(100);
|
||||
for (int i = 0; i < 50 && count != null && count != 0; i++) {
|
||||
count = mySystemDao.performReindexingPass(100);
|
||||
try {
|
||||
Thread.sleep(DateUtils.MILLIS_PER_SECOND);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
|
||||
|
@ -104,7 +75,7 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchPa
|
|||
String expression = theResource.getExpression();
|
||||
FhirContext context = getContext();
|
||||
Enum<?> type = theResource.getType();
|
||||
|
||||
|
||||
FhirResourceDaoSearchParameterR4.validateSearchParam(type, status, base, expression, context);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@ package ca.uhn.fhir.jpa.entity;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.hash.HashFunction;
|
||||
import com.google.common.hash.Hasher;
|
||||
import com.google.common.hash.Hashing;
|
||||
import org.hibernate.search.annotations.ContainedIn;
|
||||
import org.hibernate.search.annotations.Field;
|
||||
|
||||
|
@ -30,6 +36,10 @@ import java.util.Date;
|
|||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
||||
/** Don't change this without careful consideration. You will break existing hashes! */
|
||||
private static final HashFunction HASH_FUNCTION = Hashing.murmur3_128(0);
|
||||
/** Don't make this public 'cause nobody better touch it! */
|
||||
private static final byte[] DELIMITER_BYTES = "|".getBytes(Charsets.UTF_8);
|
||||
|
||||
static final int MAX_SP_NAME = 100;
|
||||
|
||||
|
@ -68,14 +78,23 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
}
|
||||
|
||||
public void setParamName(String theName) {
|
||||
clearHashes();
|
||||
myParamName = theName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
protected void clearHashes() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public BaseResourceIndexedSearchParam setResource(ResourceTable theResource) {
|
||||
clearHashes();
|
||||
myResource = theResource;
|
||||
myResourceType = theResource.getResourceType();
|
||||
return this;
|
||||
|
@ -107,4 +126,23 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
}
|
||||
|
||||
public abstract IQueryParameterType toQueryParameterType();
|
||||
|
||||
/**
|
||||
* Applies a fast and consistent hashing algorithm to a set of strings
|
||||
*/
|
||||
static long hash(String... theValues) {
|
||||
Hasher hasher = HASH_FUNCTION.newHasher();
|
||||
|
||||
for (String next : theValues) {
|
||||
next = UrlUtil.escapeUrlParam(next);
|
||||
byte[] bytes = next.getBytes(Charsets.UTF_8);
|
||||
hasher.putBytes(bytes);
|
||||
hasher.putBytes(DELIMITER_BYTES);
|
||||
}
|
||||
|
||||
HashCode hashCode = hasher.hash();
|
||||
return hashCode.asLong();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ public class ResourceIndexedCompositeStringUnique implements Comparable<Resource
|
|||
@Id
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_IDXCMPSTRUNIQ_RES_ID"))
|
||||
private ResourceTable myResource;
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.hibernate.search.annotations.Field;
|
|||
|
||||
import javax.persistence.*;
|
||||
|
||||
//@formatter:off
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_COORDS", indexes = {
|
||||
|
@ -37,7 +36,6 @@ import javax.persistence.*;
|
|||
@Index(name = "IDX_SP_COORDS_UPDATED", columnList = "SP_UPDATED"),
|
||||
@Index(name = "IDX_SP_COORDS_RESID", columnList = "RES_ID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 100;
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -33,6 +33,7 @@ import org.hibernate.search.annotations.NumericField;
|
|||
|
||||
import javax.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
//@formatter:off
|
||||
@Embeddable
|
||||
|
@ -64,6 +65,16 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_QUANTITY")
|
||||
@Column(name = "SP_ID")
|
||||
private Long myId;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_UNITS_AND_VALPREFIX", nullable = true)
|
||||
private Long myHashUnitsAndValPrefix;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_VALPREFIX", nullable = true)
|
||||
private Long myHashValPrefix;
|
||||
|
||||
public ResourceIndexedSearchParamQuantity() {
|
||||
// nothing
|
||||
|
@ -76,6 +87,20 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
setUnits(theUnits);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void calculateHashes() {
|
||||
if (myHashUnitsAndValPrefix == null) {
|
||||
setHashUnitsAndValPrefix(hash(getResourceType(), getParamName(), getSystem(), getUnits(), toTruncatedString(getValue())));
|
||||
setHashValPrefix(hash(getResourceType(), getParamName(), toTruncatedString(getValue())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearHashes() {
|
||||
myHashUnitsAndValPrefix = null;
|
||||
myHashValPrefix = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theObj) {
|
||||
if (this == theObj) {
|
||||
|
@ -94,9 +119,29 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
b.append(getSystem(), obj.getSystem());
|
||||
b.append(getUnits(), obj.getUnits());
|
||||
b.append(getValue(), obj.getValue());
|
||||
b.append(getHashUnitsAndValPrefix(), obj.getHashUnitsAndValPrefix());
|
||||
b.append(getHashValPrefix(), obj.getHashValPrefix());
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
public Long getHashUnitsAndValPrefix() {
|
||||
calculateHashes();
|
||||
return myHashUnitsAndValPrefix;
|
||||
}
|
||||
|
||||
public void setHashUnitsAndValPrefix(Long theHashUnitsAndValPrefix) {
|
||||
myHashUnitsAndValPrefix = theHashUnitsAndValPrefix;
|
||||
}
|
||||
|
||||
public Long getHashValPrefix() {
|
||||
calculateHashes();
|
||||
return myHashValPrefix;
|
||||
}
|
||||
|
||||
public void setHashValPrefix(Long theHashValPrefix) {
|
||||
myHashValPrefix = theHashValPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getId() {
|
||||
return myId;
|
||||
|
@ -107,6 +152,7 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
}
|
||||
|
||||
public void setSystem(String theSystem) {
|
||||
clearHashes();
|
||||
mySystem = theSystem;
|
||||
}
|
||||
|
||||
|
@ -115,6 +161,7 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
}
|
||||
|
||||
public void setUnits(String theUnits) {
|
||||
clearHashes();
|
||||
myUnits = theUnits;
|
||||
}
|
||||
|
||||
|
@ -123,6 +170,7 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
}
|
||||
|
||||
public void setValue(BigDecimal theValue) {
|
||||
clearHashes();
|
||||
myValue = theValue;
|
||||
}
|
||||
|
||||
|
@ -134,6 +182,8 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
b.append(getSystem());
|
||||
b.append(getUnits());
|
||||
b.append(getValue());
|
||||
b.append(getHashUnitsAndValPrefix());
|
||||
b.append(getHashValPrefix());
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
|
@ -153,4 +203,8 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc
|
|||
return b.build();
|
||||
}
|
||||
|
||||
private static String toTruncatedString(BigDecimal theValue) {
|
||||
return theValue.setScale(0, RoundingMode.FLOOR).toPlainString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -32,6 +32,8 @@ import org.hibernate.search.annotations.*;
|
|||
import javax.persistence.*;
|
||||
import javax.persistence.Index;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.left;
|
||||
|
||||
//@formatter:off
|
||||
@Embeddable
|
||||
@Entity
|
||||
|
@ -88,12 +90,11 @@ import javax.persistence.Index;
|
|||
public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchParam {
|
||||
|
||||
/*
|
||||
* Note that MYSQL chokes on unique indexes for lengths > 255 so be careful here
|
||||
* Note that MYSQL chokes on unique indexes for lengths > 255 so be careful here
|
||||
*/
|
||||
public static final int MAX_LENGTH = 200;
|
||||
|
||||
public static final int HASH_PREFIX_LENGTH = 1;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_SPIDX_STRING", sequenceName = "SEQ_SPIDX_STRING")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_STRING")
|
||||
|
@ -116,6 +117,16 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
|
||||
@Column(name = "SP_VALUE_NORMALIZED", length = MAX_LENGTH, nullable = true)
|
||||
private String myValueNormalized;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_NORM_PREFIX", nullable = true)
|
||||
private Long myHashNormalizedPrefix;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_EXACT", nullable = true)
|
||||
private Long myHashExact;
|
||||
|
||||
public ResourceIndexedSearchParamString() {
|
||||
super();
|
||||
|
@ -128,6 +139,20 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
setValueExact(theValueExact);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void calculateHashes() {
|
||||
if (myHashNormalizedPrefix == null) {
|
||||
setHashNormalizedPrefix(hash(getResourceType(), getParamName(), left(getValueNormalized(), HASH_PREFIX_LENGTH)));
|
||||
setHashExact(hash(getResourceType(), getParamName(), getValueExact()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearHashes() {
|
||||
myHashNormalizedPrefix = null;
|
||||
myHashExact = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theObj) {
|
||||
if (this == theObj) {
|
||||
|
@ -144,9 +169,29 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
b.append(getParamName(), obj.getParamName());
|
||||
b.append(getResource(), obj.getResource());
|
||||
b.append(getValueExact(), obj.getValueExact());
|
||||
b.append(getHashNormalizedPrefix(), obj.getHashNormalizedPrefix());
|
||||
b.append(getHashExact(), obj.getHashExact());
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
public Long getHashExact() {
|
||||
calculateHashes();
|
||||
return myHashExact;
|
||||
}
|
||||
|
||||
public void setHashExact(Long theHashExact) {
|
||||
myHashExact = theHashExact;
|
||||
}
|
||||
|
||||
public Long getHashNormalizedPrefix() {
|
||||
calculateHashes();
|
||||
return myHashNormalizedPrefix;
|
||||
}
|
||||
|
||||
public void setHashNormalizedPrefix(Long theHashNormalizedPrefix) {
|
||||
myHashNormalizedPrefix = theHashNormalizedPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getId() {
|
||||
return myId;
|
||||
|
@ -180,6 +225,8 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
b.append(getParamName());
|
||||
b.append(getResource());
|
||||
b.append(getValueExact());
|
||||
b.append(getHashNormalizedPrefix());
|
||||
b.append(getHashExact());
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -31,7 +31,6 @@ import org.hibernate.search.annotations.Field;
|
|||
|
||||
import javax.persistence.*;
|
||||
|
||||
//@formatter:off
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_TOKEN", indexes = {
|
||||
|
@ -40,12 +39,12 @@ import javax.persistence.*;
|
|||
@Index(name = "IDX_SP_TOKEN_UPDATED", columnList = "SP_UPDATED"),
|
||||
@Index(name = "IDX_SP_TOKEN_RESID", columnList = "RES_ID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 200;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Field()
|
||||
@Column(name = "SP_SYSTEM", nullable = true, length = MAX_LENGTH)
|
||||
public String mySystem;
|
||||
|
@ -57,16 +56,58 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_TOKEN")
|
||||
@Column(name = "SP_ID")
|
||||
private Long myId;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_SYS", nullable = true)
|
||||
private Long myHashSystem;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_SYS_AND_VALUE", nullable = true)
|
||||
private Long myHashSystemAndValue;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_VALUE", nullable = true)
|
||||
private Long myHashValue;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamToken() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamToken(String theName, String theSystem, String theValue) {
|
||||
super();
|
||||
setParamName(theName);
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
|
||||
@PrePersist
|
||||
public void calculateHashes() {
|
||||
if (myHashSystem == null) {
|
||||
setHashSystem(hash(getResourceType(), getParamName(), getSystem()));
|
||||
setHashSystemAndValue(hash(getResourceType(), getParamName(), getSystem(), getValue()));
|
||||
setHashValue(hash(getResourceType(), getParamName(), getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void clearHashes() {
|
||||
myHashSystem = null;
|
||||
myHashSystemAndValue = null;
|
||||
myHashValue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theObj) {
|
||||
if (this == theObj) {
|
||||
|
@ -84,9 +125,40 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
b.append(getResource(), obj.getResource());
|
||||
b.append(getSystem(), obj.getSystem());
|
||||
b.append(getValue(), obj.getValue());
|
||||
b.append(getHashSystem(), obj.getHashSystem());
|
||||
b.append(getHashSystemAndValue(), obj.getHashSystemAndValue());
|
||||
b.append(getHashValue(), obj.getHashValue());
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
public Long getHashSystem() {
|
||||
calculateHashes();
|
||||
return myHashSystem;
|
||||
}
|
||||
|
||||
public void setHashSystem(Long theHashSystem) {
|
||||
myHashSystem = theHashSystem;
|
||||
}
|
||||
|
||||
public Long getHashSystemAndValue() {
|
||||
calculateHashes();
|
||||
return myHashSystemAndValue;
|
||||
}
|
||||
|
||||
public void setHashSystemAndValue(Long theHashSystemAndValue) {
|
||||
calculateHashes();
|
||||
myHashSystemAndValue = theHashSystemAndValue;
|
||||
}
|
||||
|
||||
public Long getHashValue() {
|
||||
calculateHashes();
|
||||
return myHashValue;
|
||||
}
|
||||
|
||||
public void setHashValue(Long theHashValue) {
|
||||
myHashValue = theHashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getId() {
|
||||
return myId;
|
||||
|
@ -97,6 +169,7 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
}
|
||||
|
||||
public void setSystem(String theSystem) {
|
||||
clearHashes();
|
||||
mySystem = StringUtils.defaultIfBlank(theSystem, null);
|
||||
}
|
||||
|
||||
|
@ -105,6 +178,7 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
}
|
||||
|
||||
public void setValue(String theValue) {
|
||||
clearHashes();
|
||||
myValue = StringUtils.defaultIfBlank(theValue, null);
|
||||
}
|
||||
|
||||
|
@ -115,9 +189,13 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
b.append(getResource());
|
||||
b.append(getSystem());
|
||||
b.append(getValue());
|
||||
b.append(getHashSystem());
|
||||
b.append(getHashSystemAndValue());
|
||||
b.append(getHashValue());
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IQueryParameterType toQueryParameterType() {
|
||||
return new TokenParam(getSystem(), getValue());
|
||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -30,7 +30,6 @@ import org.hibernate.search.annotations.Field;
|
|||
|
||||
import javax.persistence.*;
|
||||
|
||||
//@formatter:off
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_URI", indexes = {
|
||||
|
@ -39,11 +38,10 @@ import javax.persistence.*;
|
|||
@Index(name = "IDX_SP_URI_UPDATED", columnList = "SP_UPDATED"),
|
||||
@Index(name = "IDX_SP_URI_COORDS", columnList = "RES_ID")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchParam {
|
||||
|
||||
/*
|
||||
* Note that MYSQL chokes on unique indexes for lengths > 255 so be careful here
|
||||
* Note that MYSQL chokes on unique indexes for lengths > 255 so be careful here
|
||||
*/
|
||||
public static final int MAX_LENGTH = 255;
|
||||
|
||||
|
@ -56,15 +54,38 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
|
|||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_URI")
|
||||
@Column(name = "SP_ID")
|
||||
private Long myId;
|
||||
/**
|
||||
* @since 3.4.0 - At some point this should be made not-null
|
||||
*/
|
||||
@Column(name = "HASH_URI", nullable = true)
|
||||
private Long myHashUri;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamUri() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamUri(String theName, String theUri) {
|
||||
setParamName(theName);
|
||||
setUri(theUri);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void calculateHashes() {
|
||||
if (myHashUri == null) {
|
||||
setHashUri(hash(getResourceType(), getParamName(), getUri()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearHashes() {
|
||||
myHashUri = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theObj) {
|
||||
if (this == theObj) {
|
||||
|
@ -81,9 +102,19 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
|
|||
b.append(getParamName(), obj.getParamName());
|
||||
b.append(getResource(), obj.getResource());
|
||||
b.append(getUri(), obj.getUri());
|
||||
b.append(getHashUri(), obj.getHashUri());
|
||||
return b.isEquals();
|
||||
}
|
||||
|
||||
public Long getHashUri() {
|
||||
calculateHashes();
|
||||
return myHashUri;
|
||||
}
|
||||
|
||||
public void setHashUri(Long theHashUri) {
|
||||
myHashUri = theHashUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getId() {
|
||||
return myId;
|
||||
|
@ -103,6 +134,7 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
|
|||
b.append(getParamName());
|
||||
b.append(getResource());
|
||||
b.append(getUri());
|
||||
b.append(getHashUri());
|
||||
return b.toHashCode();
|
||||
}
|
||||
|
||||
|
|
|
@ -434,8 +434,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
public ResourceTable setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
public interface IReindexController {
|
||||
void requestReindex();
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class ReindexController implements IReindexController {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(ReindexController.class);
|
||||
private final Semaphore myReindexingLock = new Semaphore(1);
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
private IFhirSystemDao<?, ?> mySystemDao;
|
||||
private Long myDontReindexUntil;
|
||||
|
||||
/**
|
||||
* This method is called once per minute to perform any required re-indexing.
|
||||
* <p>
|
||||
* If nothing if found that requires reindexing, the query will not fire again for
|
||||
* a longer amount of time.
|
||||
* <p>
|
||||
* During most passes this will just check and find that there are no resources
|
||||
* requiring re-indexing. In that case the method just returns immediately.
|
||||
* If the search finds that some resources require reindexing, the system will
|
||||
* do a bunch of reindexing and then return.
|
||||
*/
|
||||
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void performReindexingPass() {
|
||||
if (myDaoConfig.isSchedulingDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (myDontReindexUntil == null && myDontReindexUntil > System.currentTimeMillis()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!myReindexingLock.tryAcquire()) {
|
||||
ourLog.trace("Not going to reindex in parallel threads");
|
||||
return;
|
||||
}
|
||||
Integer count;
|
||||
try {
|
||||
count = mySystemDao.performReindexingPass(100);
|
||||
|
||||
for (int i = 0; i < 50 && count != null && count != 0; i++) {
|
||||
count = mySystemDao.performReindexingPass(100);
|
||||
try {
|
||||
Thread.sleep(DateUtils.MILLIS_PER_SECOND);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
myReindexingLock.release();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (count == null) {
|
||||
myDontReindexUntil = System.currentTimeMillis() + DateUtils.MILLIS_PER_HOUR;
|
||||
} else {
|
||||
myDontReindexUntil = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this will cause a reindex loop to be triggered sooner that it would otherwise
|
||||
*/
|
||||
@Override
|
||||
public void requestReindex() {
|
||||
synchronized (this) {
|
||||
myDontReindexUntil = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -133,6 +133,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -115,6 +115,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
return dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ResourceIndexedSearchParamQuantityTest {
|
||||
|
||||
private ResourceIndexedSearchParamQuantity createParam(String theParamName, String theValue, String theSystem, String theUnits) {
|
||||
ResourceIndexedSearchParamQuantity token = new ResourceIndexedSearchParamQuantity(theParamName, new BigDecimal(theValue), theSystem, theUnits);
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
return token;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashFunctions() {
|
||||
ResourceIndexedSearchParamQuantity token = createParam("NAME", "123.001", "value", "VALUE");
|
||||
|
||||
// Make sure our hashing function gives consistent results
|
||||
assertEquals(945335027461836896L, token.getHashUnitsAndValPrefix().longValue());
|
||||
assertEquals(5549105497508660145L, token.getHashValPrefix().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValueTrimming() {
|
||||
assertEquals(7265149425397186226L, createParam("NAME", "401.001", "value", "VALUE").getHashUnitsAndValPrefix().longValue());
|
||||
assertEquals(7265149425397186226L, createParam("NAME", "401.99999", "value", "VALUE").getHashUnitsAndValPrefix().longValue());
|
||||
assertEquals(7265149425397186226L, createParam("NAME", "401", "value", "VALUE").getHashUnitsAndValPrefix().longValue());
|
||||
// Should be different
|
||||
assertEquals(-8387917096585386046L, createParam("NAME", "400.9999999", "value", "VALUE").getHashUnitsAndValPrefix().longValue());
|
||||
// Should be different
|
||||
assertEquals(8819656626732693650L, createParam("NAME", "402.000000", "value", "VALUE").getHashUnitsAndValPrefix().longValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ResourceIndexedSearchParamStringTest {
|
||||
|
||||
@Test
|
||||
public void testHashFunctions() {
|
||||
ResourceIndexedSearchParamString token = new ResourceIndexedSearchParamString("NAME", "value", "VALUE");
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
|
||||
// Make sure our hashing function gives consistent results
|
||||
assertEquals(6598082761639188617L, token.getHashNormalizedPrefix().longValue());
|
||||
assertEquals(-1970227166134682431L, token.getHashExact().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashFunctionsPrefixOnly() {
|
||||
ResourceIndexedSearchParamString token = new ResourceIndexedSearchParamString("NAME", "vZZZZZZZZZZZZZZZZ", "VZZZZZZzzzZzzzZ");
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
|
||||
// Should be the same as in testHashFunctions()
|
||||
assertEquals(6598082761639188617L, token.getHashNormalizedPrefix().longValue());
|
||||
|
||||
// Should be different from testHashFunctions()
|
||||
assertEquals(-1970227166134682431L, token.getHashExact().longValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ResourceIndexedSearchParamTokenTest {
|
||||
|
||||
@Test
|
||||
public void testHashFunctions() {
|
||||
ResourceIndexedSearchParamToken token = new ResourceIndexedSearchParamToken("NAME", "SYSTEM", "VALUE");
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
|
||||
// Make sure our hashing function gives consistent results
|
||||
assertEquals(-8558989679010582575L, token.getHashSystem().longValue());
|
||||
assertEquals(-8644532105141886455L, token.getHashSystemAndValue().longValue());
|
||||
assertEquals(-1970227166134682431L, token.getHashValue().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashFunctionsWithOverlapNames() {
|
||||
ResourceIndexedSearchParamToken token = new ResourceIndexedSearchParamToken("NAME", "SYSTEM", "VALUE");
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
|
||||
// Make sure our hashing function gives consistent results
|
||||
assertEquals(-8558989679010582575L, token.getHashSystem().longValue());
|
||||
assertEquals(-8644532105141886455L, token.getHashSystemAndValue().longValue());
|
||||
assertEquals(-1970227166134682431L, token.getHashValue().longValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ResourceIndexedSearchParamUriTest {
|
||||
|
||||
@Test
|
||||
public void testHashFunctions() {
|
||||
ResourceIndexedSearchParamUri token = new ResourceIndexedSearchParamUri("NAME", "http://example.com");
|
||||
token.setResource(new ResourceTable().setResourceType("Patient"));
|
||||
|
||||
// Make sure our hashing function gives consistent results
|
||||
assertEquals(-6132951326739875838L, token.getHashUri().longValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -57,6 +57,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -58,6 +58,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -53,6 +53,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -90,6 +90,7 @@ public class TdlDstu2Config extends BaseJavaConfigDstu2 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -70,6 +70,7 @@ public class TdlDstu3Config extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -92,6 +92,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -91,6 +91,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -86,6 +86,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean()
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
|
||||
|
|
|
@ -119,7 +119,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
/**
|
||||
* This is configurable but by default we just use HAPI version
|
||||
*/
|
||||
private String myServerVersion = VersionUtil.getVersion();
|
||||
private String myServerVersion = createPoweredByHeaderProductVersion();
|
||||
private boolean myStarted;
|
||||
private Map<String, IResourceProvider> myTypeToProvider = new HashMap<>();
|
||||
private boolean myUncompressIncomingContents = true;
|
||||
|
@ -159,7 +159,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*/
|
||||
public void addHeadersToResponse(HttpServletResponse theHttpResponse) {
|
||||
String b = createPoweredByHeader();
|
||||
theHttpResponse.addHeader("X-Powered-By", b);
|
||||
theHttpResponse.addHeader(Constants.POWERED_BY_HEADER, b);
|
||||
}
|
||||
|
||||
private void addLocationHeader(RequestDetails theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation, String resourceName) {
|
||||
|
@ -213,12 +213,21 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
return Lists.newArrayList("FHIR Server", "FHIR " + myFhirContext.getVersion().getVersion().getFhirVersionString() + "/" + myFhirContext.getVersion().getVersion().name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override to provide their own powered by
|
||||
* header. Note that if you want to be nice and still credit HAPI
|
||||
* FHIR you could consider overriding
|
||||
* {@link #createPoweredByAttributes()} instead and adding your own
|
||||
* fragments to the list.
|
||||
*/
|
||||
protected String createPoweredByHeader() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(createPoweredByHeaderProductName());
|
||||
b.append(" ");
|
||||
b.append(VersionUtil.getVersion());
|
||||
b.append(" REST Server (");
|
||||
b.append(createPoweredByHeaderProductVersion());
|
||||
b.append(" ");
|
||||
b.append(createPoweredByHeaderComponentName());
|
||||
b.append(" (");
|
||||
|
||||
List<String> poweredByAttributes = createPoweredByAttributes();
|
||||
for (ListIterator<String> iter = poweredByAttributes.listIterator(); iter.hasNext(); ) {
|
||||
|
@ -232,10 +241,33 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses my override
|
||||
*
|
||||
* @see #createPoweredByHeader()
|
||||
*/
|
||||
protected String createPoweredByHeaderComponentName() {
|
||||
return "REST Server";
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses my override
|
||||
*
|
||||
* @see #createPoweredByHeader()
|
||||
*/
|
||||
protected String createPoweredByHeaderProductName() {
|
||||
return "HAPI FHIR";
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses my override
|
||||
*
|
||||
* @see #createPoweredByHeader()
|
||||
*/
|
||||
protected String createPoweredByHeaderProductVersion() {
|
||||
return VersionUtil.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (getResourceProviders() != null) {
|
||||
|
@ -539,10 +571,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*
|
||||
* @param theList The list of interceptors (may be null)
|
||||
*/
|
||||
public void setInterceptors(IServerInterceptor... theList) {
|
||||
public void setInterceptors(List<IServerInterceptor> theList) {
|
||||
myInterceptors.clear();
|
||||
if (theList != null) {
|
||||
myInterceptors.addAll(Arrays.asList(theList));
|
||||
myInterceptors.addAll(theList);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,11 +604,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*
|
||||
* @see #setResourceProviders(Collection)
|
||||
*/
|
||||
public void setPlainProviders(Collection<Object> theProviders) {
|
||||
myPlainProviders.clear();
|
||||
if (theProviders != null) {
|
||||
myPlainProviders.addAll(theProviders);
|
||||
}
|
||||
public void setPlainProviders(Object... theProv) {
|
||||
setPlainProviders(Arrays.asList(theProv));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -606,10 +635,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
/**
|
||||
* Sets the resource providers for this server
|
||||
*/
|
||||
public void setResourceProviders(Collection<IResourceProvider> theResourceProviders) {
|
||||
public void setResourceProviders(IResourceProvider... theResourceProviders) {
|
||||
myResourceProviders.clear();
|
||||
if (theResourceProviders != null) {
|
||||
myResourceProviders.addAll(theResourceProviders);
|
||||
myResourceProviders.addAll(Arrays.asList(theResourceProviders));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,8 +661,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
|
||||
/**
|
||||
* Returns the server base URL (with no trailing '/') for a given request
|
||||
*
|
||||
* @param theRequest
|
||||
*/
|
||||
public String getServerBaseForRequest(ServletRequestDetails theRequest) {
|
||||
String fhirServerBase;
|
||||
|
@ -694,9 +721,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
// passing the server into the constructor. Having that sort
|
||||
// of cross linkage causes reference cycles in Spring wiring
|
||||
try {
|
||||
Method setRestfulServer = theServerConformanceProvider.getClass().getMethod("setRestfulServer", new Class[] {RestfulServer.class});
|
||||
Method setRestfulServer = theServerConformanceProvider.getClass().getMethod("setRestfulServer", RestfulServer.class);
|
||||
if (setRestfulServer != null) {
|
||||
setRestfulServer.invoke(theServerConformanceProvider, new Object[] {this});
|
||||
setRestfulServer.invoke(theServerConformanceProvider, this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.warn("Error calling IServerConformanceProvider.setRestfulServer", e);
|
||||
|
@ -1011,9 +1038,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
invokeInitialize(iResourceProvider);
|
||||
}
|
||||
}
|
||||
if (confProvider != null) {
|
||||
invokeInitialize(confProvider);
|
||||
}
|
||||
|
||||
invokeInitialize(confProvider);
|
||||
if (getPlainProviders() != null) {
|
||||
for (Object next : getPlainProviders()) {
|
||||
invokeInitialize(next);
|
||||
|
@ -1300,7 +1326,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*
|
||||
* @param providers a {@code Collection} of providers. The parameter could be null or an empty {@code Collection}
|
||||
*/
|
||||
public void registerProviders(Collection<? extends Object> providers) {
|
||||
public void registerProviders(Collection<?> providers) {
|
||||
myProviderRegistrationMutex.lock();
|
||||
try {
|
||||
if (!myStarted) {
|
||||
|
@ -1323,9 +1349,9 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
/*
|
||||
* Inner method to actually register providers
|
||||
*/
|
||||
protected void registerProviders(Collection<? extends Object> providers, boolean inInit) {
|
||||
List<IResourceProvider> newResourceProviders = new ArrayList<IResourceProvider>();
|
||||
List<Object> newPlainProviders = new ArrayList<Object>();
|
||||
protected void registerProviders(Collection<?> providers, boolean inInit) {
|
||||
List<IResourceProvider> newResourceProviders = new ArrayList<>();
|
||||
List<Object> newPlainProviders = new ArrayList<>();
|
||||
ProvidedResourceScanner providedResourceScanner = new ProvidedResourceScanner(getFhirContext());
|
||||
|
||||
if (providers != null) {
|
||||
|
@ -1392,7 +1418,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
ourLog.info("Removing RESTful methods for: {}", theProvider.getClass());
|
||||
Class<?> clazz = theProvider.getClass();
|
||||
Class<?> supertype = clazz.getSuperclass();
|
||||
Collection<String> resourceNames = new ArrayList<String>();
|
||||
Collection<String> resourceNames = new ArrayList<>();
|
||||
while (!Object.class.equals(supertype)) {
|
||||
removeResourceMethods(theProvider, supertype, resourceNames);
|
||||
supertype = supertype.getSuperclass();
|
||||
|
@ -1468,12 +1494,18 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
case OPTIONS:
|
||||
doOptions(theReq, theResp);
|
||||
break;
|
||||
case PATCH:
|
||||
break;
|
||||
case POST:
|
||||
doPost(theReq, theResp);
|
||||
break;
|
||||
case PUT:
|
||||
doPut(theReq, theResp);
|
||||
break;
|
||||
case TRACE:
|
||||
case TRACK:
|
||||
case HEAD:
|
||||
case CONNECT:
|
||||
default:
|
||||
handleRequest(method, theReq, theResp);
|
||||
break;
|
||||
|
@ -1485,10 +1517,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*
|
||||
* @param theList The list of interceptors (may be null)
|
||||
*/
|
||||
public void setInterceptors(List<IServerInterceptor> theList) {
|
||||
public void setInterceptors(IServerInterceptor... theList) {
|
||||
myInterceptors.clear();
|
||||
if (theList != null) {
|
||||
myInterceptors.addAll(theList);
|
||||
myInterceptors.addAll(Arrays.asList(theList));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1497,8 +1529,11 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
*
|
||||
* @see #setResourceProviders(Collection)
|
||||
*/
|
||||
public void setPlainProviders(Object... theProv) {
|
||||
setPlainProviders(Arrays.asList(theProv));
|
||||
public void setPlainProviders(Collection<Object> theProviders) {
|
||||
myPlainProviders.clear();
|
||||
if (theProviders != null) {
|
||||
myPlainProviders.addAll(theProviders);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1516,10 +1551,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
/**
|
||||
* Sets the resource providers for this server
|
||||
*/
|
||||
public void setResourceProviders(IResourceProvider... theResourceProviders) {
|
||||
public void setResourceProviders(Collection<IResourceProvider> theResourceProviders) {
|
||||
myResourceProviders.clear();
|
||||
if (theResourceProviders != null) {
|
||||
myResourceProviders.addAll(Arrays.asList(theResourceProviders));
|
||||
myResourceProviders.addAll(theResourceProviders);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1539,13 +1574,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
|
||||
/**
|
||||
* Unregister one provider (either a Resource provider or a plain provider)
|
||||
*
|
||||
* @param provider
|
||||
* @throws Exception
|
||||
*/
|
||||
public void unregisterProvider(Object provider) throws Exception {
|
||||
public void unregisterProvider(Object provider) {
|
||||
if (provider != null) {
|
||||
Collection<Object> providerList = new ArrayList<Object>(1);
|
||||
Collection<Object> providerList = new ArrayList<>(1);
|
||||
providerList.add(provider);
|
||||
unregisterProviders(providerList);
|
||||
}
|
||||
|
@ -1553,11 +1585,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||
|
||||
/**
|
||||
* Unregister a {@code Collection} of providers
|
||||
*
|
||||
* @param providers
|
||||
* @throws Exception
|
||||
*/
|
||||
public void unregisterProviders(Collection<? extends Object> providers) throws Exception {
|
||||
public void unregisterProviders(Collection<?> providers) {
|
||||
ProvidedResourceScanner providedResourceScanner = new ProvidedResourceScanner(getFhirContext());
|
||||
if (providers != null) {
|
||||
for (Object provider : providers) {
|
||||
|
|
|
@ -128,9 +128,7 @@ public class SearchR4Test {
|
|||
@Test
|
||||
public void testIncludeSingleParameter() throws Exception {
|
||||
HttpGet httpGet;
|
||||
String linkNext;
|
||||
Bundle bundle;
|
||||
String linkSelf;
|
||||
|
||||
// No include specified
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationRequest");
|
||||
|
|
|
@ -17,6 +17,20 @@
|
|||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
<action type="add">
|
||||
Several enhancements have been made to the JPA server index
|
||||
tables. These enhancements consist of new colums that will be
|
||||
used in a future version of HAPI FHIR to significantly decrease
|
||||
the amount of space required for indexes on token and string index
|
||||
types.
|
||||
<![CDATA[<br/><br/>]]>
|
||||
These new columns are not yet used in HAPI FHIR 3.4.0 but will be
|
||||
enabled in HAPI FHIR 3.5.0. Anyone upgrading to HAPI FHIR 3.4.0 (or above)
|
||||
is recommended to invoke the following SQL statement on their
|
||||
database in order to reindex all data in a background job:
|
||||
<![CDATA[<br/>]]>
|
||||
<![CDATA[<code>update HFJ_RESOURCE set SP_INDEX_STATUS = null;</code>]]>
|
||||
</action>
|
||||
<action type="add">
|
||||
R4 structures have been updated to the latest definitions
|
||||
(SVN 13732)
|
||||
|
@ -226,6 +240,11 @@
|
|||
An issue in the narrative generator template for the CodeableConcept
|
||||
datatype was corrected. Thanks to @RuthAlk for the pull request!
|
||||
</action>
|
||||
<action type="add">
|
||||
The JPA server automatic reindexing process has been tweaked so that it no
|
||||
longer runs once per minute (this was a heavy strain on large databases)
|
||||
but will instead run once an hour unless triggered for some reason.
|
||||
</action>
|
||||
</release>
|
||||
<release version="3.3.0" date="2018-03-29">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue