Servlet Web Application Context from filter - spring

I try to get the spring web application context from a filter.
I was previously getting it through:
WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext())
It was ok, because I was getting what is called I think the ROOT web application context.
Now, I wanted to move all my spring definition like that in web.xml :
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of default XmlWebApplicationContext. -->
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<!-- Custom web configuration annotated class. -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>foo.bar.WebConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
I removed the "old" definition from web.xml :
<!-- <context-param> -->
<!-- <param-name>contextConfigLocation</param-name> -->
<!-- <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> -->
<!-- </context-param> -->
<!-- <listener> -->
<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -->
<!-- </listener> -->
Now, I have no more "ROOT" web application context, and the filter cannot get the another web application context.
I saw that there is another call :
WebApplicationContextUtils.getWebApplicationContext(sc, attrName)
it allows to specify as second argument the "attribute", it is in fact the web application context you want.By default, it is "org.springframework.web.context.WebApplicationContext.ROOT".
I think I have to call this method but I don't know what to put as second parameter.
PS : I also tried to use org.springframework.web.filter.DelegatingFilterProxy, but tomcat throwed the error that he dont find the classic (ROOT) web application context :
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
BUT THERE IS ANOTHER CONTEXT, it is just defined in another way. It is not possible I am the only one trying to get another context that the ROOT.
Thanks to have read so far.

I just read your answer, and yes I figured it out yesterday night ;-)
I added the ROOT context, defining it like that:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>foo.bar.WebConfiguration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
And its working, the filter can acces to the service directly with Autowiring.
I still have the feeling that my architecture is dirty because the ROOT and "dispatcher" context are the same, I think it's not a good practice.
Maybe I'll try later to split the "WebConfiguration" in two.
Thank you anyway!

Related

Understanding spring dispatcher servlet initialization

Here is how spring documentation recomends to initialize dispatcherServlet:
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</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-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
My question is about providing an empty param-value inside the init-param tag. Despite defining that param as context-param we still provide the empty value. Therefore contextConfigLocation should be null when passes to servlet's init() method. What's wrong, correct me please.
In Spring Web Applications, there are two types of container, each of which is configured and initialized differently.
Application Context
Web Application Context
Application context is inialised by config file's that you specified in as context-params and picked up by ContextLoaderListener. This is purely i would consider as business logic related beans.
Web application context is child of application context which may or may not be present. Each DispatcherServlet will have associated WebApplicationContext and which takes spring beans from your init-params to create context.
Whatever beans are available in the ApplicationContext can be referred to from each WebApplicationContext.
Reason why we have two different bean configurations is to keep a clear separation between middle-tier services such as business logic components and data access classes (that are typically defined in the ApplicationContext) and web- related components such as controllers and view resolvers (that are defined in the WebApplicationContext per Dispatcher Servlet).

application-config.xml vs mvc-config.xml in spring

Im a newbie to Spring and trying to understand the web.xml file.
I have created a new SPring MVC Maven project using STS,
I'm little bit confused between the application-config.xml vs mvc-config.xml file...
mvc-config.xml contains the servlet mappings but what information does the application-config file contains..
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Servlet that dispatches request to registered handlers (Controller implementations).
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Usually the mvc configuration(/WEB-INF/mvc-config.xml) contains the the beans that are needed by the controller layer (e.g. the controllers, view resolvers ...) The application configuration(classpath:spring/application-config.xml) is for the model layer (here you can define daos, services...)

spring 3 mvc multiple application context instances

here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Enables clean URLs with JSP views e.g. /welcome instead of /app/welcome -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>
<!-- Handles all requests into the application -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Maps all /app requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Why there are two instances of application context created?
When I add a scheduled method with #Scheduled it is invoked twice, because of those two application contexts.
You are loading twice times the same spring config files. Of course you have two separate application contexts. At first I would rename the servlet name for the DispatcherServerlet to "spring3mvc". The servlet definition should look like this:
<servlet>
<servlet-name>spring3Mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
If you have it in this way, you should have a spring config file "spring3Mvc-servlet.xml" in your "WEB-INF" directory. Spring will find this file automatically because of the right naming convention. In this file you should just have the beans who are important for springMVC. It could look like this:
<context:component-scan base-package="org.company.gui.controller"/>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".view.jsp"/>
</bean>
This should fix your problem.
I noticed that you have
<load-on-startup>1</load-on-startup>
in the following block
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
try removing that... it worked for me
Do you have any other spring filters or jsp pages in your web.xml not shown in your code snippet?
I ask, to answer your question, because I believe this quote from Spring documentation could explain what might be happening...
"In the web MVC framework, each
DispatcherServlet has its own
WebApplicationContext, which inherits
all the beans already defined in the
root WebApplicationContext. These
inherited beans defined can be
overridden in the servlet-specific
scope, and new scope-specific beans
can be defined local to a given
servlet instance."
If you answered "yes" to my web.xml question, then my guess is that Spring instantiates a root WebApplicationContext when a spring filter is created (via ContextLoaderListener). So, this would happen BEFORE...
Then, when the DispatcherServlet is created, the "contextConfigLocation" refers to the same files (that is, the same bean names), so a new WebApplicationContext gets overridden bean names local to that servlet!
I wonder, even if you answered "no", whether this might still happen anyway. Since you set "contextConfigLocation" (used by the ContextLoaderListener) and "override" it in DispatcherServlet configuration; I assume Spring is not checking whether those configurations are using the same file set.
You can run these scenarios through a debugger and put breakpoints on WebApplicationContext methods to find out for sure.
Workaround:
To solve the problem, either:
1) make sure your 2 contextConfigLocations don't overlap in files they use
Or:
2) break out the Scheduling bean in its own xml file and make sure it's referred to by only one of the 2 contextConfigLocations

How to add a Filter in Spring (with BlazeDS)

I want to add a filter to map a specific path in URL.
My server side used Spring 2.5.x, BlazeDS (servlet) with TomCat server.
So, my web.xml file is composed like that :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-main-config.xml
</param-value>
</context-param>
<filter>
<filter-name>FacebookOAuthFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>FacebookOAuthFilter</filter-name>
<url-pattern>/fbauth</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC Servlet (that will route HTTP requests to BlazeDS) -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-main-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
When I start my TomCat server, an exception is catched :
[BlazeDS][ERROR] [Configuration] MessageBroker failed to start: Exception: flex.messaging.config.ConfigurationException: MessageBroker already defined from MessageBrokerServlet with init parameter messageBrokerId = '_messageBroker'
at flex.messaging.MessageBroker.registerMessageBroker(MessageBroker.java:1916)
COuld you help me please ?
Thank you very much,
Anthony
I believe you are loading the incorrect configuration file here...
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-main-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
you have alreaded loaded /WEB-INF/spring-main-config.xml in the first few lines of the file
http://www.springbyexample.org/examples/simple-flex-webapp.html
This isn't really a Flex or BlazeDS issue, it's a more basic mis-configuration of Spring.
You're configured two separate Spring app-contexts, both with the same set of bean definitions (/WEB-INF/spring-main-config.xml).
The app-context defined by the <context-param> is the app-context associated with the webapp. The app-context defined by the ` is associated with the servlet.
Since you've given the same beans file to both, it'll instantiate and initialize the same set of beans twice, and the second time seems to be failing because the MessageBroker has already been defined.
You either need to break up your bean definitions into two sets, or just remove the first one, and just use the servlet context.

Multiple config files for Spring Security

I'm quite new to all things Spring, and right now I'm developing an application that uses Spring, Spring MVC and Spring Security.
My problem is that I'm using two dispatcher Servlets, one for /csm/*.html and another one for *.html and I'd like to have one Spring Security configuration file per servlet.
Is this possible at all?, if so, could you point me to an example?.
This answer relates to springframework 2.5.6, it might have changed in later versions.
use the pattern /WEB-INF/[servlet-name]-servlet.xml or specify it in the web.xml like this:
<servlet>
<servlet-name>handler</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- override default name {servlet-name}-servlet.xml -->
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-myconfig.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
If you do not set the contextConfigLocation it defaults to handler-servlet.xml (at least in this example).
application wide stuff belongs into /WEB-INF/applicationContext.xml.
But you also can change the default and even add multiple files:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/spring-dao-hibernate.xml,
WEB-INF/spring-services.xml,
WEB-INF/spring-security.xml
</param-value>
</context-param>
you can find a more specific answer on the spring website, the documentation is quite good.

Resources