I have the Web.xml as below:
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>/api/secure/*</url-pattern>
</filter-mapping>
[Edit]
After I added the spring security, then I get the error!
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
then I added
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
then it seems working fine, but then 1) The problem is the bean are created twice!
if I only remove that:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
but leave the <listener>
then the web application doesn't run at all
[Extra]
The full Web.xml is below:
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>/api/secure/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
here is my mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<mvc:annotation-driven/>
<context:annotation-config/>
<context:component-scan base-package="com.ge.wtracker"/>
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--Java Persistence API config-->
<jpa:repositories base-package="com.ge.wtracker.repository"/>
<!--JPA and Database Config-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="defaultPersistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<!--Spring Security-->
<security:http create-session="stateless" entry-point-ref="restAuthenticationEntryPoint" authentication-manager-ref="authenticationManager">
<security:intercept-url pattern="/api/secure/**" access="ROLE_USER" />
<security:custom-filter ref="customRestFilter" position="BASIC_AUTH_FILTER" />
</security:http>
<!-- Configures the authentication entry point that returns HTTP status code 401 -->
<bean id="restAuthenticationEntryPoint" class="com.ge.wtracker.web.security.RestAuthenticationEntryPoint">
<property name="realmName" value="Not Authorized" />
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="restAuthenticationProvider" />
</security:authentication-manager>
<!--The customRestFilter responsibles for retrieving and manipulating any request data to pass to the authentication
provider to authenticate.-->
<bean id="customRestFilter" class="com.ge.wtracker.web.security.RestSecurityFilter">
<constructor-arg name="authenticationManager" ref="authenticationManager" />
<constructor-arg name="authenticationEntryPoint" ref="restAuthenticationEntryPoint" />
</bean>
<bean id="restAuthenticationProvider" class="com.ge.wtracker.web.security.RestAuthenticationProvider" />
</beans>
During the servlet container lifecycle, the container first initializes the ServletContextListener
, then the Filter
and Servlet
instances.
A Spring Web application typically loads two contexts: the root context and the dispatcher servlet context. The ContextLoaderListener
class is a ServletContextListener
which loads the application (or root) context. It identifies the file to load either through the context-param
with the name contextConfigLocation
as given in the web.xml like below
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
or, by default, by looking for a file at /WEB-INF/applicationContext.xml
. Since you've specified /WEB-INF/mvc-dispatcher-servlet.xml
as the contextConfigLocation
, that context will be loaded.
Once this is done, the container initializes the DispatcherServlet
, which also loads a context. It identifies the file load either through an init-param
element with the name contextConfigLocation
as given in the web.xml below
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/some-random-location.xml</param-value>
</init-param>
</servlet>
or, by default, by looking for a file at /WEB-INF/name-of-your-servlet-servlet.xml
. In other words, it takes the value of the <servlet-name>
element and appends -servlet.xml
to it and looks for it in WEB-INF
.
Since you haven't specified an init-param
with name contextConfigLocation
, the DispatcherServlet
loads the context file at /WEB-INF/mvc-dispatcher-servlet.xml
, since its name is mvc-dispatcher
. The context loaded by the DispatcherServlet
has access to the beans loaded by the ContextLoaderListener
, that's why we call that the root context (and the others children).
All this to say that both your ContextLoaderListener
and your DispatcherServlet
are creating their own copy of an ApplicationContext
by each loading a XmlWebApplicationContext
from the same file at /WEB-INF/mvc-dispatcher-servlet.xml
.
Identify what beans or configuration you think should be available to the whole application and put them in the file that will be loaded by the ContextLoaderListener
. Identify the beans or configuration you think should be available to the DispatcherServlet
and put them in its context file.
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s02.html
The framework will, on initialization of a DispatcherServlet, look for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and create the beans defined there (overriding the definitions of any beans defined with the same name in the global scope).
So you can remove the context-param:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml
</param-value>
</context-param>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With