I am attempting to install a filter into a Spring web app using DelegatingFilterProxy. The app is a black box to me. I have no control over it, but I know it uses Spring. I control only my filter.
The app itself is configured in web.xml (tomcat 7) in the usual way, with <listener>...ContextLoaderListener...</listener>
with the Spring config specified via <context-param>
.
My first attempt was to share the app's context. I added my own spring config XML to context-param. My filter loads just fine, but I broke the app. I'm not sure exactly how it's broken, but it looks like it can no longer make database connections. I checked the obvious things. There are no bean name conflicts or property name conflicts.
What I would really like to do is have 2 completely separate contexts so that, presumably, there would be no way for my filter to affect the black box application. Is there a way I can configure web.xml to cause Spring to create a new context just for my filter?
There are several similar questions on stackoverflow, but the details differ considerably.
I'm posting my web.xml as requested, but bear in mind that this is not what I'm trying to do. What you see here is my filter and the web app sharing the same context, which is not what I want. I am asking if it's possible to have two completely separate contexts so that the filter and the web app are completely insulated from each other (at least at the Spring level).
My parts below are the filter declaration and the filter mapping and the second line of spring xml context configuration (classpath:...)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>xxx</display-name>
<description>xxx</description>
<filter>
<filter-name>myAccessFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myAccessFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml
classpath:my-access-spring.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
<servlet>
<servlet-name>spring-flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>xxx-rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all /messagbroker requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>spring-flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>xxx-rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<error-page>
<error-code>401</error-code>
<location>/error-401.html</location>
</error-page>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Time passes: I have more information as to why a shared context in this situation is a bad idea. It turns out that I DID have bean conflicts. In particular, both my filter and the underlying application used a bean named "dataSource" (of course).
Once I renamed my bean, I got a very clear message from Spring:
No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: dataSource,deoDataSource
Presumably the app is using wiring by type, not by name, so I have an obvious conflict.
So! The original question still stands: Is it possible to configure Spring to create a separate context just for my filter?
Thanks, Fred
autowire-candidate="false"
on the data source bean. Alternatively you can use different context viasetContextAttribute
loaded by differentContextLoaderListener
. – Pavel HoralServletContext
attribute. All relevant components (DispatcherServlet
,DelegatingFilterProxy
,ContextLoaderListener
) take the name of the attribute as an argument. I'll try to write a proper answer as soon as I am free from work :). – Pavel Horal