
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 myRequestPartitionHelperService); 156 } 157 158 @Bean 159 public ExceptionService exceptionService() { 160 return new ExceptionService(myContext); 161 } 162 163 @Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME) 164 @Scope("prototype") 165 public ISearchBuilder newSearchBuilder(String theResourceName, Class<? extends IBaseResource> theResourceType) { 166 return new SearchBuilder( 167 theResourceName, 168 myStorageSettings, 169 myEntityManagerFactory, 170 mySqlBuilderFactory, 171 myDialectProvider, 172 mySearchParamRegistry, 173 myPartitionSettings, 174 myInterceptorBroadcaster, 175 myResourceTagDao, 176 myDaoRegistry, 177 myContext, 178 myIdHelperService, 179 myResourceHistoryTableDao, 180 myJpaStorageResourceParser, 181 theResourceType); 182 } 183 184 @Bean(name = SEARCH_TASK) 185 @Scope("prototype") 186 public SearchTask createSearchTask(SearchTaskParameters theParams) { 187 return new SearchTask( 188 theParams, 189 myHapiTransactionService, 190 myContext, 191 myInterceptorBroadcaster, 192 mySearchBuilderFactory, 193 mySearchResultCacheSvc, 194 myStorageSettings, 195 mySearchCacheSvc, 196 myPagingProvider); 197 } 198 199 @Bean(name = CONTINUE_TASK) 200 @Scope("prototype") 201 public SearchContinuationTask createSearchContinuationTask(SearchTaskParameters theParams) { 202 return new SearchContinuationTask( 203 theParams, 204 myHapiTransactionService, 205 myContext, 206 myInterceptorBroadcaster, 207 mySearchBuilderFactory, 208 mySearchResultCacheSvc, 209 myStorageSettings, 210 mySearchCacheSvc, 211 myPagingProvider, 212 exceptionService() // singleton 213 ); 214 } 215 216 @PostConstruct 217 public void validateConfiguration() { 218 if (myStorageSettings.isIndexStorageOptimized() 219 && myPartitionSettings.isPartitioningEnabled() 220 && myPartitionSettings.isIncludePartitionInSearchHashes()) { 221 throw new ConfigurationException(Msg.code(2525) + "Incorrect configuration. " 222 + "StorageSettings#isIndexStorageOptimized and PartitionSettings.isIncludePartitionInSearchHashes " 223 + "cannot be enabled at the same time."); 224 } 225 } 226}