
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 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 FhirContext myContext; 095 096 @Autowired 097 private IIdHelperService myIdHelperService; 098 099 @Autowired 100 private PlatformTransactionManager myManagedTxManager; 101 102 @Autowired 103 private SearchStrategyFactory mySearchStrategyFactory; 104 105 @Autowired 106 private SearchBuilderFactory mySearchBuilderFactory; 107 108 @Autowired 109 private ISearchResultCacheSvc mySearchResultCacheSvc; 110 111 @Autowired 112 private ISearchCacheSvc mySearchCacheSvc; 113 114 @Autowired 115 private IPagingProvider myPagingProvider; 116 117 @Autowired 118 private BeanFactory myBeanFactory; 119 120 @Autowired 121 private ISynchronousSearchSvc mySynchronousSearchSvc; 122 123 @Autowired 124 private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory; 125 126 @Autowired 127 private IRequestPartitionHelperSvc myRequestPartitionHelperService; 128 129 @Autowired 130 private HapiTransactionService myHapiTransactionService; 131 132 @Autowired 133 private IResourceHistoryTableDao myResourceHistoryTableDao; 134 135 @Autowired 136 private IJpaStorageResourceParser myJpaStorageResourceParser; 137 138 @Bean 139 public ISearchCoordinatorSvc searchCoordinatorSvc() { 140 return new SearchCoordinatorSvcImpl( 141 myContext, 142 myStorageSettings, 143 myInterceptorBroadcaster, 144 myHapiTransactionService, 145 mySearchCacheSvc, 146 mySearchResultCacheSvc, 147 myDaoRegistry, 148 mySearchBuilderFactory, 149 mySynchronousSearchSvc, 150 myPersistedJpaBundleProviderFactory, 151 mySearchParamRegistry, 152 mySearchStrategyFactory, 153 exceptionService(), 154 myBeanFactory); 155 } 156 157 @Bean 158 public ExceptionService exceptionService() { 159 return new ExceptionService(myContext); 160 } 161 162 @Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME) 163 @Scope("prototype") 164 public ISearchBuilder newSearchBuilder(String theResourceName, Class<? extends IBaseResource> theResourceType) { 165 return new SearchBuilder( 166 theResourceName, 167 myStorageSettings, 168 myEntityManagerFactory, 169 mySqlBuilderFactory, 170 myDialectProvider, 171 mySearchParamRegistry, 172 myPartitionSettings, 173 myInterceptorBroadcaster, 174 myResourceTagDao, 175 myDaoRegistry, 176 myContext, 177 myIdHelperService, 178 myResourceHistoryTableDao, 179 myJpaStorageResourceParser, 180 theResourceType); 181 } 182 183 @Bean(name = SEARCH_TASK) 184 @Scope("prototype") 185 public SearchTask createSearchTask(SearchTaskParameters theParams) { 186 return new SearchTask( 187 theParams, 188 myHapiTransactionService, 189 myContext, 190 myInterceptorBroadcaster, 191 mySearchBuilderFactory, 192 mySearchResultCacheSvc, 193 myStorageSettings, 194 mySearchCacheSvc, 195 myPagingProvider); 196 } 197 198 @Bean(name = CONTINUE_TASK) 199 @Scope("prototype") 200 public SearchContinuationTask createSearchContinuationTask(SearchTaskParameters theParams) { 201 return new SearchContinuationTask( 202 theParams, 203 myHapiTransactionService, 204 myContext, 205 myInterceptorBroadcaster, 206 mySearchBuilderFactory, 207 mySearchResultCacheSvc, 208 myStorageSettings, 209 mySearchCacheSvc, 210 myPagingProvider, 211 exceptionService() // singleton 212 ); 213 } 214 215 @PostConstruct 216 public void validateConfiguration() { 217 if (myStorageSettings.isIndexStorageOptimized() 218 && myPartitionSettings.isPartitioningEnabled() 219 && myPartitionSettings.isIncludePartitionInSearchHashes()) { 220 throw new ConfigurationException(Msg.code(2525) + "Incorrect configuration. " 221 + "StorageSettings#isIndexStorageOptimized and PartitionSettings.isIncludePartitionInSearchHashes " 222 + "cannot be enabled at the same time."); 223 } 224 } 225}