Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All Spring Framework beans get duplicated, becase of doubled context (servlet+ContextLoaderListener)

  • If I create spring context by dispatcher servlet, I got an error inDelegatingFilterProxy filter:

    java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.apache.logging.log4j.core.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:66)
    
  • If I create spring context by ContextLoaderListener I just have 404 error beacuse of no servlet

  • If I create spring context by both servlet & listener I have duplicated context, so all beans are duplicated, including controllers with request mappings, double-executing @Scheduled methods etc.

How to create advanced spring application (including lot of filters etc.) without duplicating context?

My web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        id="WebApp_ID" version="3.0">

        <display-name>MyWebApplication</display-name>

        <servlet>
                <servlet-name>springDispatcher</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>

        <servlet-mapping>
                <servlet-name>springDispatcher</servlet-name>
                <url-pattern>/</url-pattern>
        </servlet-mapping>

        <listener>
                <listener-class>
                  org.springframework.web.context.ContextLoaderListener
             </listener-class>
        </listener>

        <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
                        /WEB-INF/spring.xml
                </param-value>
        </context-param>

        <!-- UTF-8 -->
        <filter>
             <filter-name>encoding-filter</filter-name>
             <filter-class>
                 org.springframework.web.filter.CharacterEncodingFilter
             </filter-class>
             <init-param>
                 <param-name>encoding</param-name>
                 <param-value>UTF-8</param-value>
             </init-param>
             <init-param>
             <param-name>forceEncoding</param-name>
             <param-value>true</param-value>
             </init-param>
         </filter>

    <filter-mapping>
        <filter-name>encoding-filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

         <!-- Spring Security -->
        <filter>
                <filter-name>springSecurityFilterChain</filter-name>
                <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>

        <filter-mapping>
                <filter-name>springSecurityFilterChain</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>

</web-app>
like image 707
Kinga Odecka Avatar asked Mar 20 '23 05:03

Kinga Odecka


1 Answers

if you use spring related servlet filters and also use mvc controllers, then you need both:

  • ContextLoaderListener AND
  • DispatcherServlet-spring-configuration

(See ContextLoaderListener or not?)

Both create their own servlet context. The ContextLoaderListener create the parent-context (sometimes called the inner-context). And the DispatcherServlet create a child-context (of the parent context) (sometimes called the outer-context). The beans of the child-context can access the beans of the parent-context, but not the other way around.

In a not too simple web application you need both contexts, because the there are many servlet filters that requires an already created spring context. On the other hand, all the controller stuff needs a ServletContext, and this is only created by the Dispatcher Servlet.

Another point is, that you should not have every bean created twice (sometimes this is no problem, other times it is). So you need to have two spring configurations, one for the inner context, one for the other context. And you need to decide for every bean whether it belongs to the inner or to the outer context.

The rule of thumb is: put every thing in the inner context, except that stuff that requires a Servlet context or is heavily tied to the Web-frontend, like MVC-Controllers, Tiles configuration, ....

like image 166
Ralph Avatar answered Apr 26 '23 00:04

Ralph