简体   繁体   中英

Spring throws exception for undefined bean

I am following this tutorial to use Spring Security. I would like to use Hibernate for database queries. I configured the code but following exception is thrown.

I defined the bean in spring-security.xml and my-servlet.xml but still no result.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myMemberDetailsService' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1114)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:279)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:320)
    ... 93 more

MemberRepository

public class MemberRepositoryImpl implements MemberRepository {

    SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Override
    public Member findByUserName(String username) {

        List<Member> members = new ArrayList<Member>();
        members = sessionFactory.getCurrentSession()
                .createQuery("from Member where username=?")
                .setParameter(0, username).list();

        if (members.size() > 0) {
            return members.get(0);
        } else {
            return null;
        }
    }

}

MyMemberDetailsService

public class MyMemberDetailsService implements UserDetailsService {

    private MemberRepository memberRep;

    @Override
    public UserDetails loadUserByUsername(final String username)
            throws UsernameNotFoundException {

        Member member = memberRep.findByUserName(username);
        HashSet<String> roles = new HashSet<String>();
        roles.add("ROLE_MEMBER");
        List<GrantedAuthority> authorities = buildUserAuthority(roles);

        return buildUserForAuthentication(member, authorities);

    }

    // Converts com.mkyong.users.model.User user to
    // org.springframework.security.core.userdetails.User
    private User buildUserForAuthentication(Member member,
            List<GrantedAuthority> authorities) {
        return new User(member.getUsername(), member.getPassword(),
                member.isEnabled(), true, true, true, authorities);
    }

    private List<GrantedAuthority> buildUserAuthority(Set<String> userRoles) {

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        // Build user's authorities
        for (String userRole : userRoles) {
            setAuths.add(new SimpleGrantedAuthority(userRole));
        }

        List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(
                setAuths);

        return Result;
    }

}

my-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http:/www.springframework.org/schema/beans 
    http:/www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http:/www.springframework.org/schema/aop 
    http:/www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http:/www.springframework.org/schema/tx 
    http:/www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http:/www.springframework.org/schema/context
    http:/www.springframework.org/schema/mvc">


    <context:annotation-config />
    <mvc:annotation-driven />
    <mvc:view-controller path="/index" />
    <mvc:view-controller path="/" view-name="index" />
    <mvc:view-controller path="/signin" />



    <mvc:resources mapping="resources/**" location="resources/" />
    <context:component-scan base-package="com.myProject" />
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" />
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>


    <bean id="memberRep" class="com.myProject.repository.MemberRepositoryImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>


    <bean id="myMemberDetailsService" class="com.myProject.service.MyMemberDetailsService">
        <property name="memberRep" ref="memberRep" />
    </bean>

    <!-- Hibernate Config -->

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:8889/myProject" />
        <property name="username" value="jack" />
        <property name="password" value="jack" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
        depends-on="dataSource">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.myProject.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="userServicePointCut"
            expression="execution(* com.myProject.service.*Service.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
    </aop:config>

    <!-- End Hibernate Config -->
</beans>

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">



    <beans:import resource='login-service.xml' /> 
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/member**" access="hasRole('ROLE_MEMBER')" />
        <intercept-url pattern="/signin" access="permitAll" />


        <access-denied-handler error-page="/403" />
        <form-login login-page="/signin" default-target-url="/index"
            authentication-failure-url="/signin?error" username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" />
        <!-- enable csrf protection -->
        <csrf />
    </http>
    <authentication-manager>
        <authentication-provider user-service-ref="myMemberDetailsService">
            <password-encoder hash="bcrypt" />


        </authentication-provider>
    </authentication-manager>
</beans:beans>

I just read the tutorial and I saw it didn't mention anything about web.xml configuration, so I downloaded it to see how it was configured.

You told, you have tried to define myMemberDetailsService in both places, my-servlet and spring-security but it didn't work.

Well I think it is a problem of configuration so please try to change your web.xml as following ( I used the names you have used in your question, but please check it out to see if there is something wrong ):

<servlet>
    <servlet-name>my-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/my-servlet.xml,
            /WEB-INF/spring-security.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

And remove your global <context-param> for the contextConfigLocation param if present.

If this does not work I will recommend you to use a similar configuration as the tutorial, is to say, leave minimal MVC configuration into my-servlet.xml and configure the rest of beans in separate context.

Hope it helps!

Including UserDetailsService in security xml will resolve the issue.

In your spring-security.xml include the MyMemberDetailsService implementation definition.

<beans:bean class="your.package.MyMemberDetailsService"
    id="myMemberDetailsService" />

I see that you are including login-service.xml in your spring-security.xml . So defining the user service bean in login-service.xml will also resolve the issue.

As per the tutorial, web.xml should contain reference to your spring config xml.

web.xml will look like

<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>

The mvc-dispatcher-servlet xml should contain import of all other xmls.

mvc-dispatcher-servlet xml will look like

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        ...">

        <import resource="my-servlet.xml" />
        <import resource="spring-security.xml" />
        ...
    </beans>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM