Update (after providing complete example)
It seems you have multiple issues.
web.xml vs AbstractAnnotationConfigDispatcherServletInitializer
The application you created had a web.xml that configures a DispatcherServlet named mvc-dispatcher
. The mvc-dispatcher
had a configuration of mvc-dispatcher-servlet.xml
which loaded all beans within the package com.springapp.sectest
. This means that mvc-dispatcher
can find your UserDetailsService
.
The application also had a AbstractAnnotationConfigDispatcherServletInitializer which created a DispatcherServlet
that loaded your WebConfig
java configuration. This DispatcherServlet
could not see any Beans created by mvc-dispatcher
.
In short, you should either configure a DispatcherServlet
using web.xml or AbstractAnnotationConfigDispatcherServletInitializer
and NOT both.
getRootConfigClasses vs getServletConfigClasses
Any configuration within getRootConfigClasses is typically called the root or parent configuration and cannot view beans defined in getServletConfigClasses. Spring Security protects your application defined in the getRootConfigClasses with a Filter named springSecurityFilterChain that is created by the @EnableWebSecurity
annotation. This means it is generally best to place Spring Security's configuration in the getRootConfigClasses. There are some exceptions to this, like if you want to do method security on your Spring MVC Controllers.
Any configuration within getServletConfigClasses is typically called the child configuration and can view beans defined in the getRootConfigClasses. The getServletConfigClasses configures the DispatcherServlet
and must contain beans for Spring MVC (i.e. Controllers, ViewResovlers, etc). Any Spring MVC beans defined in getRootConfigClasses are visible but not used.
This setup, while a bit confusing, allows you to have multiple DispatcherServlet
instances with isolated configurations. In practice, it is VERY rare to have multiple DispatcherServlet
instances though.
Given the information above, you should move the UserDetailsService
declaration along with all of its dependent beans to the getRootConfigClasses. This will ensure the SecurityConfig.java can find the UserDetailsService
.
Pull Request for fixes
I have submitted a PR to get your application so that it starts with no errors https://github.com/worldcombined/AnnotateFailed/pull/1 . A few notes
- the test does not use a parent and child context so it is not reflecting running the application
- I had to move the resources folder so that was picked up properly
- I did not make it so you can actually authenticate. There was no login.jsp and the UserDetailsService you provided always returns null Instead I attempted to demonstrate that the error on here was answered.
Original Answer
Based upon this comment:
@ComponentScan is undertaken in my mvc-dispatcher-servlet.xml as <context:component-scan base-package="com.entirety.app"/>
It appears that you are configuring the services within the Dispatcher configuration and not within the root context.
Spring Security's configuration is typically configured in the root context. For example, one might extend the AbstractSecurityWebApplicationInitializer as shown below:
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
How are you importing the Security configuration? If the Spring Security configuration is in the root context then it will not see beans defined in the Dispatcher Servlet context.
The solution is to move the configuring of your services in the root context or move the Spring Security configuration to the dispatcher's ApplicationContext. For example, moving Spring Security configuration to the dispatcher context would look like the following if your dispatcher servlet was named mvc.
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
protected String getDispatcherWebApplicationContextSuffix() {
return "mvc";
}
}