
001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 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.svc.IIdHelperService; 029import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc; 030import ca.uhn.fhir.jpa.dao.IJpaStorageResourceParser; 031import ca.uhn.fhir.jpa.dao.ISearchBuilder; 032import ca.uhn.fhir.jpa.dao.SearchBuilderFactory; 033import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao; 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 ca.uhn.fhir.svcs.ISearchLimiterSvc; 053import jakarta.annotation.PostConstruct; 054import org.hl7.fhir.instance.model.api.IBaseResource; 055import org.springframework.beans.factory.BeanFactory; 056import org.springframework.beans.factory.annotation.Autowired; 057import org.springframework.context.annotation.Bean; 058import org.springframework.context.annotation.Configuration; 059import org.springframework.context.annotation.Scope; 060import org.springframework.transaction.PlatformTransactionManager; 061 062@Configuration 063public class SearchConfig { 064 public static final String SEARCH_TASK = "searchTask"; 065 public static final String CONTINUE_TASK = "continueTask"; 066 067 @Autowired 068 private JpaStorageSettings myStorageSettings; 069 070 @Autowired 071 private HapiFhirLocalContainerEntityManagerFactoryBean myEntityManagerFactory; 072 073 @Autowired 074 private SqlObjectFactory mySqlBuilderFactory; 075 076 @Autowired 077 private HibernatePropertiesProvider myDialectProvider; 078 079 @Autowired 080 private ISearchParamRegistry mySearchParamRegistry; 081 082 @Autowired 083 private PartitionSettings myPartitionSettings; 084 085 @Autowired 086 protected IInterceptorBroadcaster myInterceptorBroadcaster; 087 088 @Autowired 089 protected IResourceTagDao myResourceTagDao; 090 091 @Autowired 092 private DaoRegistry myDaoRegistry; 093 094 @Autowired 095 private FhirContext myContext; 096 097 @Autowired 098 private IIdHelperService myIdHelperService; 099 100 @Autowired 101 private PlatformTransactionManager myManagedTxManager; 102 103 @Autowired 104 private SearchStrategyFactory mySearchStrategyFactory; 105 106 @Autowired 107 private SearchBuilderFactory mySearchBuilderFactory; 108 109 @Autowired 110 private ISearchResultCacheSvc mySearchResultCacheSvc; 111 112 @Autowired 113 private ISearchCacheSvc mySearchCacheSvc; 114 115 @Autowired 116 private IPagingProvider myPagingProvider; 117 118 @Autowired 119 private BeanFactory myBeanFactory; 120 121 @Autowired 122 private ISynchronousSearchSvc mySynchronousSearchSvc; 123 124 @Autowired 125 private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory; 126 127 @Autowired 128 private IRequestPartitionHelperSvc myRequestPartitionHelperService; 129 130 @Autowired 131 private HapiTransactionService myHapiTransactionService; 132 133 @Autowired 134 private IResourceHistoryTableDao myResourceHistoryTableDao; 135 136 @Autowired 137 private IJpaStorageResourceParser myJpaStorageResourceParser; 138 139 @Autowired 140 private ISearchLimiterSvc mySearchLimiterSvc; 141 142 @Bean 143 public ISearchCoordinatorSvc searchCoordinatorSvc() { 144 return new SearchCoordinatorSvcImpl( 145 myContext, 146 myStorageSettings, 147 myInterceptorBroadcaster, 148 myHapiTransactionService, 149 mySearchCacheSvc, 150 mySearchResultCacheSvc, 151 myDaoRegistry, 152 mySearchBuilderFactory, 153 mySynchronousSearchSvc, 154 myPersistedJpaBundleProviderFactory, 155 mySearchParamRegistry, 156 mySearchStrategyFactory, 157 exceptionService(), 158 myBeanFactory); 159 } 160 161 @Bean 162 public ExceptionService exceptionService() { 163 return new ExceptionService(myContext); 164 } 165 166 @Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME) 167 @Scope("prototype") 168 public ISearchBuilder newSearchBuilder(String theResourceName, Class<? extends IBaseResource> theResourceType) { 169 return new SearchBuilder( 170 theResourceName, 171 myStorageSettings, 172 myEntityManagerFactory, 173 mySqlBuilderFactory, 174 myDialectProvider, 175 mySearchParamRegistry, 176 myPartitionSettings, 177 myInterceptorBroadcaster, 178 myResourceTagDao, 179 myDaoRegistry, 180 myContext, 181 myIdHelperService, 182 myResourceHistoryTableDao, 183 myJpaStorageResourceParser, 184 mySearchLimiterSvc, 185 theResourceType); 186 } 187 188 @Bean(name = SEARCH_TASK) 189 @Scope("prototype") 190 public SearchTask createSearchTask(SearchTaskParameters theParams) { 191 return new SearchTask( 192 theParams, 193 myHapiTransactionService, 194 myContext, 195 myInterceptorBroadcaster, 196 mySearchBuilderFactory, 197 mySearchResultCacheSvc, 198 myStorageSettings, 199 mySearchCacheSvc, 200 myPagingProvider); 201 } 202 203 @Bean(name = CONTINUE_TASK) 204 @Scope("prototype") 205 public SearchContinuationTask createSearchContinuationTask(SearchTaskParameters theParams) { 206 return new SearchContinuationTask( 207 theParams, 208 myHapiTransactionService, 209 myContext, 210 myInterceptorBroadcaster, 211 mySearchBuilderFactory, 212 mySearchResultCacheSvc, 213 myStorageSettings, 214 mySearchCacheSvc, 215 myPagingProvider, 216 exceptionService() // singleton 217 ); 218 } 219 220 @PostConstruct 221 public void validateConfiguration() { 222 if (myStorageSettings.isIndexStorageOptimized() 223 && myPartitionSettings.isPartitioningEnabled() 224 && myPartitionSettings.isIncludePartitionInSearchHashes()) { 225 throw new ConfigurationException(Msg.code(2525) + "Incorrect configuration. " 226 + "StorageSettings#isIndexStorageOptimized and PartitionSettings.isIncludePartitionInSearchHashes " 227 + "cannot be enabled at the same time."); 228 } 229 } 230}