Включение/отключение фильтра web.xml с использованием профиля Spring

У меня есть приложение Spring, которое может использовать два разных API сохранения:

  • Спринг-данные JPA
  • Весенние данные Neo4j

При использовании Spring Data JPA мне нужно объявить «OpenEntityManagerInViewFilter» в «web.xml» для ленивой загрузки:

<filter>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Проблема в том, что я не могу включить этот фильтр при использовании Spring Data Neo4j. Оставив его включенным, вы получите следующую ошибку времени выполнения:

No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined

Я хочу выбрать, какую базу данных использовать с профилем Spring (например, spring.profiles.active=relational-database или spring.profiles.active=graph-database).

Вопрос: как я могу включить "OpenEntityManagerInViewFilter", когда профиль является "реляционной базой данных", и отключить его, когда профиль является "графовой базой данных"?

Спасибо!

Связанные вопросы:


person Grégoire C    schedule 12.06.2015    source источник
comment
Вы не можете, так как web.xml не имеет ничего общего с Spring. Вы могли бы использовать решение из вопроса, на который вы ссылались, и в случае, если оно не нужно, используя фиктивный фильтр вместо фактического фильтра.   -  person M. Deinum    schedule 12.06.2015
comment
Идея заключалась бы в том, чтобы создать мою собственную неактивную реализацию org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter и загружать ее только тогда, когда профиль является графовой базой данных?   -  person Grégoire C    schedule 12.06.2015
comment
Нет, просто создайте noop-реализацию фильтра, которого достаточно, он не обязательно должен быть конкретным.   -  person M. Deinum    schedule 12.06.2015


Ответы (1)


Хорошо, я разобрался с этим. Мой новый "web.xml" использует DelegatingFilterProxy вместо org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter:

<filter>
    <filter-name>toggleOpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>toggleOpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Затем в своем ApplicationContext я создаю bean-компонент с именем toggleOpenEntityManagerInViewFilter (значение filter-name). Хитрость заключается в том, чтобы создать экземпляр другого класса в зависимости от профиля Spring:

<beans profile="graph-database">
    <bean id="toggleOpenEntityManagerInViewFilter" class="my.project.dal.utils.spring.DoNothingFilter"/>
</beans>
<beans profile="relational-database">
    <bean id="toggleOpenEntityManagerInViewFilter" class="org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter"/>
</beans>

my.project.dal.utils.spring.DoNothingFilter определяется как:

public class DoNothingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    }
}

Кажется, это работает.

person Grégoire C    schedule 12.06.2015
comment
Будущие читатели: если вы используете старую версию Spring, наличие двух элементов <beans>, вложенных в один корневой узел <beans>profiles в этом отношении), требует Spring 3.1, а в файле XML пространство имен http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd. - person orlade; 26.05.2016