I have problem with Spring autowire. I'm trying to use Autowire to inject repository, which by the way already works when I'm injecting it into the controller, into authentication service. For further reference I'm adding relevant code and error.
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">
<display-name>Restful Web Application</display-name>
<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>
enterprise.util.SpringSecurityConfig
</param-value>
</context-param>
<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>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>restEnterprise</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restEnterprise</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
restEnterpise-servlet.xml -- EmployeeRepository is in dbService
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="enterprise.service" />
<context:component-scan base-package="enterprise.controller" />
<context:component-scan base-package="enterprise.util" />
<context:component-scan base-package="dbService" />
<mvc:annotation-driven />
</beans>
SpringSecurityConfig.java
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenAuthenticationService tokenAuthenticationService; //handles adding auth token to response and checking for auth header in requests
private final EmployeeDetailsService employeeDetailsService;
public SpringSecurityConfig() {
super(true);
tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets");
employeeDetailsService = new EmployeeDetailsService();
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.debug(true);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.headers().cacheControl().and().and()
.authorizeRequests()
// Allow anonymous logins
.antMatchers("/auth/**").permitAll()
// All other request need to be authenticated
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
//http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
public EmployeeDetailsService userDetailsService() {
return employeeDetailsService;
}
//--------------
@Bean
public TokenAuthenticationService tokenAuthenticationService() {
return tokenAuthenticationService;
}
}
EmployeeDetailsService.java
@Component
public class EmployeeDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
private EmployeeRepository employeeRep;
@Override
public final UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Employee employee = employeeRep.findByLogin(username);
if (employee == null) {
throw new UsernameNotFoundException("Employee not found");
}
List<GrantedAuthority> authorities = buildUserAuthority(employee.getRole());
return buildUserForAuthentication(employee, authorities);
}
// Converts Employee to
// org.springframework.security.core.userdetails.User
private User buildUserForAuthentication(Employee user,
List<GrantedAuthority> authorities) {
return new User(user.getLogin(), user.getPassword(),
true, true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(String userRole) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
setAuths.add(new SimpleGrantedAuthority("ROLE_" + userRole.toUpperCase()));
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
Error during deploy
2015-08-18 10:15:34,389 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) JBAS014613: Operation ("redeploy") failed - address: ([("deployment" => "enterprise.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./enterprise" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./enterprise: Failed to start service
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dbService.dao.EmployeeRepository enterprise.service.EmployeeDetailsService.employeeRep; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [dbService.dao.EmployeeRepository] 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)}
As I've said - this autowire works when I'm using it in controller but not in EmployeeDetailsService.