001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.config; 021 022import ca.uhn.fhir.context.ConfigurationException; 023import ca.uhn.fhir.context.FhirContext; 024import ca.uhn.fhir.i18n.Msg; 025import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; 026import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; 027import ca.uhn.fhir.jpa.api.dao.DaoRegistry; 028import ca.uhn.fhir.jpa.api.dao.IDao; 029import ca.uhn.fhir.jpa.api.svc.IIdHelperService; 030import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc; 031import ca.uhn.fhir.jpa.dao.ISearchBuilder; 032import ca.uhn.fhir.jpa.dao.SearchBuilderFactory; 033import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao; 034import ca.uhn.fhir.jpa.dao.data.IResourceTagDao; 035import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; 036import ca.uhn.fhir.jpa.model.config.PartitionSettings; 037import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc; 038import ca.uhn.fhir.jpa.search.ExceptionService; 039import ca.uhn.fhir.jpa.search.ISynchronousSearchSvc; 040import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory; 041import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; 042import ca.uhn.fhir.jpa.search.SearchStrategyFactory; 043import ca.uhn.fhir.jpa.search.builder.SearchBuilder; 044import ca.uhn.fhir.jpa.search.builder.sql.SqlObjectFactory; 045import ca.uhn.fhir.jpa.search.builder.tasks.SearchContinuationTask; 046import ca.uhn.fhir.jpa.search.builder.tasks.SearchTask; 047import ca.uhn.fhir.jpa.search.builder.tasks.SearchTaskParameters; 048import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; 049import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; 050import ca.uhn.fhir.rest.server.IPagingProvider; 051import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; 052import jakarta.annotation.PostConstruct; 053import org.hl7.fhir.instance.model.api.IBaseResource; 054import org.springframework.beans.factory.BeanFactory; 055import org.springframework.beans.factory.annotation.Autowired; 056import org.springframework.context.annotation.Bean; 057import org.springframework.context.annotation.Configuration; 058import org.springframework.context.annotation.Scope; 059import org.springframework.transaction.PlatformTransactionManager; 060 061@Configuration 062public class SearchConfig { 063 public static final String SEARCH_TASK = "searchTask"; 064 public static final String CONTINUE_TASK = "continueTask"; 065 066 @Autowired 067 private JpaStorageSettings myStorageSettings; 068 069 @Autowired 070 private HapiFhirLocalContainerEntityManagerFactoryBean myEntityManagerFactory; 071 072 @Autowired 073 private SqlObjectFactory mySqlBuilderFactory; 074 075 @Autowired 076 private HibernatePropertiesProvider myDialectProvider; 077 078 @Autowired 079 private ISearchParamRegistry mySearchParamRegistry; 080 081 @Autowired 082 private PartitionSettings myPartitionSettings; 083 084 @Autowired 085 protected IInterceptorBroadcaster myInterceptorBroadcaster; 086 087 @Autowired 088 protected IResourceTagDao myResourceTagDao; 089 090 @Autowired 091 private DaoRegistry myDaoRegistry; 092 093 @Autowired 094 private IResourceSearchViewDao myResourceSearchViewDao; 095 096 @Autowired 097 private FhirContext myContext; 098 099 @Autowired 100 private IIdHelperService myIdHelperService; 101 102 @Autowired 103 private PlatformTransactionManager myManagedTxManager; 104 105 @Autowired 106 private SearchStrategyFactory mySearchStrategyFactory; 107 108 @Autowired 109 private SearchBuilderFactory mySearchBuilderFactory; 110 111 @Autowired 112 private ISearchResultCacheSvc mySearchResultCacheSvc; 113 114 @Autowired 115 private ISearchCacheSvc mySearchCacheSvc; 116 117 @Autowired 118 private IPagingProvider myPagingProvider; 119 120 @Autowired 121 private BeanFactory myBeanFactory; 122 123 @Autowired 124 private ISynchronousSearchSvc mySynchronousSearchSvc; 125 126 @Autowired 127 private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory; 128 129 @Autowired 130 private IRequestPartitionHelperSvc myRequestPartitionHelperService; 131 132 @Autowired 133 private HapiTransactionService myHapiTransactionService; 134 135 @Bean 136 public ISearchCoordinatorSvc searchCoordinatorSvc() { 137 return new SearchCoordinatorSvcImpl( 138 myContext, 139 myStorageSettings, 140 myInterceptorBroadcaster, 141 myHapiTransactionService, 142 mySearchCacheSvc, 143 mySearchResultCacheSvc, 144 myDaoRegistry, 145 mySearchBuilderFactory, 146 mySynchronousSearchSvc, 147 myPersistedJpaBundleProviderFactory, 148 mySearchParamRegistry, 149 mySearchStrategyFactory, 150 exceptionService(), 151 myBeanFactory); 152 } 153 154 @Bean 155 public ExceptionService exceptionService() { 156 return new ExceptionService(myContext); 157 } 158 159 @Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME) 160 @Scope("prototype") 161 public ISearchBuilder newSearchBuilder( 162 IDao theDao, String theResourceName, Class<? extends IBaseResource> theResourceType) { 163 return new SearchBuilder( 164 theDao, 165 theResourceName, 166 myStorageSettings, 167 myEntityManagerFactory, 168 mySqlBuilderFactory, 169 myDialectProvider, 170 mySearchParamRegistry, 171 myPartitionSettings, 172 myInterceptorBroadcaster, 173 myResourceTagDao, 174 myDaoRegistry, 175 myResourceSearchViewDao, 176 myContext, 177 myIdHelperService, 178 theResourceType); 179 } 180 181 @Bean(name = SEARCH_TASK) 182 @Scope("prototype") 183 public SearchTask createSearchTask(SearchTaskParameters theParams) { 184 return new SearchTask( 185 theParams, 186 myHapiTransactionService, 187 myContext, 188 myInterceptorBroadcaster, 189 mySearchBuilderFactory, 190 mySearchResultCacheSvc, 191 myStorageSettings, 192 mySearchCacheSvc, 193 myPagingProvider); 194 } 195 196 @Bean(name = CONTINUE_TASK) 197 @Scope("prototype") 198 public SearchContinuationTask createSearchContinuationTask(SearchTaskParameters theParams) { 199 return new SearchContinuationTask( 200 theParams, 201 myHapiTransactionService, 202 myContext, 203 myInterceptorBroadcaster, 204 mySearchBuilderFactory, 205 mySearchResultCacheSvc, 206 myStorageSettings, 207 mySearchCacheSvc, 208 myPagingProvider, 209 exceptionService() // singleton 210 ); 211 } 212 213 @PostConstruct 214 public void validateConfiguration() { 215 if (myStorageSettings.isIndexStorageOptimized() 216 && myPartitionSettings.isPartitioningEnabled() 217 && myPartitionSettings.isIncludePartitionInSearchHashes()) { 218 throw new ConfigurationException(Msg.code(2525) + "Incorrect configuration. " 219 + "StorageSettings#isIndexStorageOptimized and PartitionSettings.isIncludePartitionInSearchHashes " 220 + "cannot be enabled at the same time."); 221 } 222 } 223}