views:

49

answers:

2

I'm working through Peter Mularien's Spring Security 3, and am having a problem setting up the UserDetailsManager.

I create the JdbcUserDetailsManager bean as follows:

<bean id="jdbcUserService" class="org.springframework.security.provisioning.JdbcUserDetailsManager">
    <property name="dataSource" ref="mySqlDb" />
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

and autowire its UserDetailsManager interface in my controller like so:

@Autowired
public UserDetailsManager userDetailsManager;

When I start up the app to test it out, I get the following exception:

Error creating bean with name 'changePasswordController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.provisioning.UserDetailsManager com.ebisent.web.ChangePasswordController.userDetailsManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.security.provisioning.UserDetailsManager] is defined: expected single matching bean but found 2: [org.springframework.security.provisioning.JdbcUserDetailsManager#0, jdbcUserService]

I searched through my project to see if I might have set up (Jdbc)UserDetailsManager elsewhere, but I don't appear to have done so. If I remove the "id" attribute in the bean definition, then the ambiguity is between JdbcUserDetailsManager#0 and JdbcUserDetailsManager#1.

My web.xml references app-config.xml in two places:

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

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/app-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
+1  A: 

Robert, Yes. What your web.xml says is to create a web app context of app-config.xml pointing to a parent of app-config.xml. That means you have two copies of each bean - which as you've noticed is incorrect.

Jeanne Boyarsky
Thanks, Jeanne.
robert
A: 

There was definitely a problem with specifying app-config.xml twice, but that's not the answer to the problem originally stated.

It appears that Spring autowires based on type. The bean is defined with the class JdbcUserDetailsManager, which implements UserDetailsManager.

In my controller, I am autowiring the interface UserDetailsManager. Spring finds the interface twice, and complains that it doesn't know which to pick.

Adding the @Qualifier annotation fixes the problem. Here's how it looks now:

@Autowired
@Qualifier("jdbcUserService")  // <-- this references the bean id
public UserDetailsManager userDetailsManager;
robert