Auto-detect disabled hibernate search

This commit is contained in:
James Agnew 2016-07-18 16:56:41 -04:00
parent 94128e2e6d
commit 8f7a374a25
6 changed files with 405 additions and 12 deletions

View File

@ -189,6 +189,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode);
@Override
public DaoMethodOutcome delete(IIdType theId) {
return delete(theId, null);
}
@Override
public ResourceTable delete(IIdType theId, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
if (theId == null || !theId.hasIdPart()) {
@ -225,11 +230,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return savedEntity;
}
@Override
public DaoMethodOutcome delete(IIdType theId) {
return delete(theId, null);
}
@Override
public DaoMethodOutcome delete(IIdType theId, RequestDetails theRequestDetails) {
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
@ -299,6 +299,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return new DaoMethodOutcome();
}
@PostConstruct
public void detectSearchDaoDisabled() {
if (mySearchDao != null && mySearchDao.isDisabled()) {
mySearchDao = null;
}
}
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing, Date theUpdateTime, RequestDetails theRequestDetails) {
StopWatch w = new StopWatch();
@ -995,6 +1002,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return update(theResource, null, theRequestDetails);
}
@Override
public DaoMethodOutcome update(T theResource, String theMatchUrl) {
return update(theResource, theMatchUrl, null);
}
@Override
public DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing, RequestDetails theRequestDetails) {
StopWatch w = new StopWatch();
@ -1071,11 +1083,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return outcome;
}
@Override
public DaoMethodOutcome update(T theResource, String theMatchUrl) {
return update(theResource, theMatchUrl, null);
}
@Override
public DaoMethodOutcome update(T theResource, String theMatchUrl, RequestDetails theRequestDetails) {
return update(theResource, theMatchUrl, true, theRequestDetails);

View File

@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
@ -381,4 +382,17 @@ public class FulltextSearchSvcImpl extends BaseHapiFhirDao<IBaseResource> implem
}
@Override
public boolean isDisabled() {
try {
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
em.getSearchFactory().buildQueryBuilder().forEntity(ResourceTable.class).get();
} catch (Exception e) {
ourLog.trace("FullText test failed", e);
ourLog.debug("Hibernate Search (Lucene) appears to be disabled on this server, fulltext will be disabled");
return true;
}
return false;
}
}

View File

@ -32,4 +32,6 @@ public interface IFulltextSearchSvc {
List<Long> everything(String theResourceName, SearchParameterMap theParams);
boolean isDisabled();
}

View File

@ -0,0 +1,37 @@
package ca.uhn.fhir.jpa.config;
import java.util.Properties;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement()
public class TestDstu3WithoutLuceneConfig extends TestDstu3Config {
@Override
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = new LocalContainerEntityManagerFactoryBean();
retVal.setPersistenceUnitName("PU_HapiFhirJpaDstu3");
retVal.setDataSource(dataSource());
retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity");
retVal.setPersistenceProvider(new HibernatePersistenceProvider());
retVal.setJpaProperties(jpaProperties());
return retVal;
}
private Properties jpaProperties() {
Properties extraProperties = new Properties();
extraProperties.put("hibernate.format_sql", "false");
extraProperties.put("hibernate.show_sql", "false");
extraProperties.put("hibernate.hbm2ddl.auto", "update");
extraProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyTenSevenDialect");
extraProperties.put("hibernate.search.autoregister_listeners", "false");
return extraProperties;
}
}

View File

@ -0,0 +1,327 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.model.AllergyIntolerance;
import org.hl7.fhir.dstu3.model.Appointment;
import org.hl7.fhir.dstu3.model.AuditEvent;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.CarePlan;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.CompartmentDefinition;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.Condition;
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.Device;
import org.hl7.fhir.dstu3.model.DiagnosticOrder;
import org.hl7.fhir.dstu3.model.DiagnosticReport;
import org.hl7.fhir.dstu3.model.Encounter;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Immunization;
import org.hl7.fhir.dstu3.model.Location;
import org.hl7.fhir.dstu3.model.Media;
import org.hl7.fhir.dstu3.model.Medication;
import org.hl7.fhir.dstu3.model.MedicationOrder;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.dstu3.model.NamingSystem;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.OperationDefinition;
import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Period;
import org.hl7.fhir.dstu3.model.Practitioner;
import org.hl7.fhir.dstu3.model.Quantity;
import org.hl7.fhir.dstu3.model.Questionnaire;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.Subscription;
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
import org.hl7.fhir.dstu3.model.Substance;
import org.hl7.fhir.dstu3.model.TemporalPrecisionEnum;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestDstu3Config;
import ca.uhn.fhir.jpa.config.TestDstu3WithoutLuceneConfig;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.entity.ResourceLink;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.TestUtil;
// @RunWith(SpringJUnit4ClassRunner.class)
// @ContextConfiguration(classes= {TestDstu3WithoutLuceneConfig.class})
// @SuppressWarnings("unchecked")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestDstu3WithoutLuceneConfig.class })
public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3SearchWithLuceneDisabledTest.class);
@Autowired
@Qualifier("myAllergyIntoleranceDaoDstu3")
private IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
@Autowired
@Qualifier("myAppointmentDaoDstu3")
private IFhirResourceDao<Appointment> myAppointmentDao;
@Autowired
@Qualifier("myAuditEventDaoDstu3")
private IFhirResourceDao<AuditEvent> myAuditEventDao;
@Autowired
@Qualifier("myBundleDaoDstu3")
private IFhirResourceDao<Bundle> myBundleDao;
@Autowired
@Qualifier("myCarePlanDaoDstu3")
private IFhirResourceDao<CarePlan> myCarePlanDao;
@Autowired
@Qualifier("myCodeSystemDaoDstu3")
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
@Autowired
@Qualifier("myCompartmentDefinitionDaoDstu3")
private IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao;
@Autowired
@Qualifier("myConceptMapDaoDstu3")
private IFhirResourceDao<ConceptMap> myConceptMapDao;
@Autowired
@Qualifier("myConditionDaoDstu3")
private IFhirResourceDao<Condition> myConditionDao;
@Autowired
protected DaoConfig myDaoConfig;
@Autowired
@Qualifier("myDeviceDaoDstu3")
private IFhirResourceDao<Device> myDeviceDao;
@Autowired
@Qualifier("myDiagnosticOrderDaoDstu3")
private IFhirResourceDao<DiagnosticOrder> myDiagnosticOrderDao;
@Autowired
@Qualifier("myDiagnosticReportDaoDstu3")
private IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
@Autowired
@Qualifier("myEncounterDaoDstu3")
private IFhirResourceDao<Encounter> myEncounterDao;
// @PersistenceContext()
@Autowired
private EntityManager myEntityManager;
@Autowired
@Qualifier("myFhirContextDstu3")
private FhirContext myFhirCtx;
@Autowired
@Qualifier("myImmunizationDaoDstu3")
private IFhirResourceDao<Immunization> myImmunizationDao;
@Autowired
@Qualifier("myLocationDaoDstu3")
private IFhirResourceDao<Location> myLocationDao;
@Autowired
@Qualifier("myMediaDaoDstu3")
private IFhirResourceDao<Media> myMediaDao;
@Autowired
@Qualifier("myMedicationDaoDstu3")
private IFhirResourceDao<Medication> myMedicationDao;
@Autowired
@Qualifier("myMedicationOrderDaoDstu3")
private IFhirResourceDao<MedicationOrder> myMedicationOrderDao;
@Autowired
@Qualifier("myNamingSystemDaoDstu3")
private IFhirResourceDao<NamingSystem> myNamingSystemDao;
@Autowired
@Qualifier("myObservationDaoDstu3")
private IFhirResourceDao<Observation> myObservationDao;
@Autowired
@Qualifier("myOperationDefinitionDaoDstu3")
private IFhirResourceDao<OperationDefinition> myOperationDefinitionDao;
@Autowired
@Qualifier("myOrganizationDaoDstu3")
private IFhirResourceDao<Organization> myOrganizationDao;
@Autowired
@Qualifier("myPatientDaoDstu3")
private IFhirResourceDaoPatient<Patient> myPatientDao;
@Autowired
@Qualifier("myPractitionerDaoDstu3")
private IFhirResourceDao<Practitioner> myPractitionerDao;
@Autowired
@Qualifier("myQuestionnaireDaoDstu3")
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
@Autowired
@Qualifier("myQuestionnaireResponseDaoDstu3")
private IFhirResourceDao<QuestionnaireResponse> myQuestionnaireResponseDao;
@Autowired
@Qualifier("myResourceProvidersDstu3")
private Object myResourceProviders;
@Autowired
@Qualifier("myStructureDefinitionDaoDstu3")
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
@Autowired
@Qualifier("mySubscriptionDaoDstu3")
private IFhirResourceDaoSubscription<Subscription> mySubscriptionDao;
@Autowired
@Qualifier("mySubstanceDaoDstu3")
private IFhirResourceDao<Substance> mySubstanceDao;
@Autowired
@Qualifier("mySystemDaoDstu3")
private IFhirSystemDao<Bundle, Meta> mySystemDao;
@Autowired
@Qualifier("mySystemProviderDstu3")
private JpaSystemProviderDstu3 mySystemProvider;
@Autowired
protected PlatformTransactionManager myTxManager;
@Autowired
@Qualifier("myJpaValidationSupportChainDstu3")
private IValidationSupport myValidationSupport;
@Before
@Transactional()
public void beforePurgeDatabase() {
final EntityManager entityManager = this.myEntityManager;
purgeDatabase(entityManager, myTxManager);
}
@Before
public void beforeResetConfig() {
myDaoConfig.setHardSearchLimit(1000);
myDaoConfig.setHardTagListLimit(1000);
myDaoConfig.setIncludeLimit(2000);
}
@Override
protected FhirContext getContext() {
return myFhirCtx;
}
@Test
public void testSearchWithRegularParam() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
Organization org = new Organization();
org.setName(methodName);
IIdType orgId = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add(Organization.SP_NAME, new StringParam(methodName));
myOrganizationDao.search(map);
}
@Test
public void testSearchWithContent() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
Organization org = new Organization();
org.setName(methodName);
IIdType orgId = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam(methodName));
try {
myOrganizationDao.search(map);
fail();
} catch (InvalidRequestException e) {
assertEquals("Fulltext search is not enabled on this service, can not process parameter: _content", e.getMessage());
}
}
@Test
public void testSearchWithText() throws Exception {
String methodName = "testEverythingIncludesBackReferences";
Organization org = new Organization();
org.setName(methodName);
IIdType orgId = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_TEXT, new StringParam(methodName));
try {
myOrganizationDao.search(map);
fail();
} catch (InvalidRequestException e) {
assertEquals("Fulltext search is not enabled on this service, can not process parameter: _text", e.getMessage());
}
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
}

View File

@ -62,6 +62,12 @@
When using <![CDATA[<code>_elements</code>]]> parameter on server, the server was not
automatically adding the <![CDATA[<code>SUBSETTED</code>]]> tag as it should
</action>
<action type="fix">
JPA server should now automatically detect
if Hibernate Search (Lucene) is configured to be
disabled and will not attempt to use it. This
prevents a crash for some operations.
</action>
</release>
<release version="1.6" date="2016-07-07">
<action type="fix">