I'm implementing Spring Security using Java configuration in my Spring Web MVC project, and for some reason the @Autowired
annotation is not injecting fields in my security config class. I found this very similar question on SO, but my setup is much simpler and the accepted answer doesn't apply at all in my case.
For reference, I followed the first three chapters of Spring's own security documentation (here) and got in-memory authentication working pretty quickly. I then wanted to switch to JDBC authentication and inject a DataSource
with the @Autowired
annotation (as shown in this example). However, I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.tyedart.web.config.security.SecurityConfig.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Here is my security config class. As you can see I'm working around the problem by explicitly looking up my data source:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// @Autowired
// private DataSource dataSource;
// @Autowired
// public PasswordEncoder passwordEncoder;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
InitialContext ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup("java:/comp/env/jdbc/TyedArtDB");
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth
.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(passwordEncoder);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/manage/**").hasRole("ADMIN")
.and()
.formLogin();
}
}
And here is my very simple root-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
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/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/TyedArtDB"/>
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans>
What am I doing wrong?