Исходная ситуацияМожно ли настроить контекст приложения OpenSessionInViewFilter в Spring, чтобы контекст: свойство-placeholder можно использовать?
Моя веб-приложение состоит из модулей Maven MyApp-живучесть (.jar), MyApp-модели (.jar), MyApp-служба (.jar) и MyApp -web (.war), чтобы получить традиционную, слабо связанную многоуровневую архитектуру. Все модули объединены родительским модулем Maven, который содержит только родительский POM с общими определениями для всех подмодулей.
Особенно MyApp-служба (.jar) и MyApp-живучесть (.jar) имеет свою собственную конфигурируемую (!) Контекст приложения часть с необходимыми объектами. Обе банки должны быть развернуты с содержащими определениями переменных, другими словами, банки не должны иметь конкретных значений для переменных.
MyApp-сервис-context.xml объявляет solrServer боб с переменной URL сервера:
<bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg value="${solr.serverUrl}" />
<property name="connectionTimeout" value="60000"/>
<property name="defaultMaxConnectionsPerHost" value="40"/>
<property name="maxTotalConnections" value="40"/>
</bean>
MyApp-живучесть-context.xml определяет DATASOURCE с подключением переменные:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
...
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
...
</bean>
myapp-web (.war) ссылки myapp-service (.jar) и myapp-persistence (.jar). В myapp-servlet.xml он включает их части контекста приложения и предоставляет значения свойств для конфигурации объявленных beans файлом свойства. К context: property-placeholder Spring инициализирует все переменные конкретными значениями при создании контекста приложения в памяти.
<context:property-placeholder location="classpath*:myapp-configuration.properties" />
<import resource="classpath*:myapp-persistence-context.xml"/>
<import resource="classpath*:myapp-service-context.xml"/>
Для профиля развития конкретные myapp-configuration.properties может выглядеть как:
solr.serverUrl=http://localhost:8983/solr
jdbc.dialect=org.hibernate.dialect.HSQLDialect
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:myapp
jdbc.username=sa
jdbc.password=
Эта конфигурация имо прямо вперед и работает - без зрения. Проблема возникает, когда org.springframework.orm.hibernate3.support.OpenSessionInViewFilter вступает в игру.
Описание проблемы
OpenSessionInViewFilter гарантирует, что экземпляры в графе объектов, которые не загружены внутри открытой транзакции во время обработки контроллера могут быть загружены лениво, если представление пытается отобразить эти objects' содержания (см. [1]). Как часто описывается, этот фильтр объявляется в дескрипторе delpoyment .XML (см [2]):
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Если MyApp-сохранение-context.xml входит в MYAPP-servlet.xml как выше, так что контекст: свойство-заполнитель работы, OpenSessionInViewFilter не находит необходимого sessionFactory. Причина в том, что Spring сначала обрабатывает web.xml, а затем myapp-servlet.xml, который импортирует myapp-persistence-context.xml. К счастью, я не могу подтвердить это предположение ссылкой. После исключения:
GRAVE: Servlet.service() for servlet [myapp] in context with path [/myapp] threw exception org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory' is defined at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529) at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1097) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:242) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:227) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:171) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)
Различные контекстные приложения частей, как правило, включены в дескрипторе развертывания с ContextLoaderListener и не MYAPP-servlet.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:myapp-service-context.xml,
classpath*:myapp-persistence-context.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
При такой конфигурации unfourtunately , Spring's контекст: свойство-placeholder механизм, кажется, больше не работает.
Цель и вопрос
модули как MYAPP-настойчивость (.jar) и MyApp-служба (.jar) должен быть настраиваемым во время выполнения с файлом свойств контекста ссылающегося, например контекст приложения myapp-web (.war).
Возникает вопрос: можно ли настроить OpenSessionInViewFilter в контексте приложения Spring, так что контекста: свойство-заполнитель еще полезный?
Или альтернативно: как переменные в контекстах приложения инициализируются Spring во время выполнения, если части контекста приложения включены в дескриптор развертывания web.xml?
По существу: почему на самом деле OpenSessionInViewFilter необходимо настроить, почему Spring MVC не прозрачно поддерживает просмотр ленивой загрузки из коробки?
Предвидя Замечания
замена собственности во время компиляции не точка здесь. Файл с зависимым от профиля профиля уже создан с помощью Maven Filtering.
Перемещение Datasource и solrServer деклараций в MYAPP-servlet.xml Как уже было предложено (см [3], [4]) не является приемлемым решением, потому что она destroyes модульность и независимый тестируемости MYAPP-персистенции ( ,jar) и myapp-service (.jar) - на самом деле дух инъекции зависимостей!
Ваш друг показал вам правильный способ обработки сессий спящего режима в любом приложении. Я обычно предпочитаю путь Interceptor, потому что это более безопасный подход, чтобы иметь сложную архитектуру, и только некоторые весенние бобы настраиваются. В настоящее время используйте стиль конфигурации Java, он безопаснее, чем * любая * конфигурация XML. – ThierryB