Amit
Amit

Reputation: 13394

BeanCreationException while using recommended way of Spring Configuration

I have one AppConfig.java and one SecurityConfig.java file in my project, I was following some blog on web and saw below configuration setting..

package mybasepackage.login.springsecurity.config;

@Configuration
@EnableWebMvc
@ComponentScan({"mybasepackage.login.springsecurity.*"})
public class AppConfig {
    @Bean(name = "dataSource")
    public DataSource getDataSource() {
        //code to construct datasource
    }

    @Bean(name = "passwordEncoder")
    public PasswordEncoder passwordEncoder() {
        return new CustomPasswordEncoder();
    }

}

package mybasepackage.login.springsecurity.config;

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        private DataSource dataSource;

        @Autowired
        private PasswordEncoder passwordEncoder;
}

However when I try above code I get BeanCreationException because datasource can't be created.

When I use below code, it works as expected,

package mybasepackage.login.springsecurity.config;

@Configuration
public class AppConfig {
    @Bean(name = "dataSource")
    public DataSource dataSource() {
            //code to create dataSource
    }

    @Bean(name = "passwordEncoder")
    public PasswordEncoder passwordEncoder() {
        return new CustomPasswordEncoder();
    }



}


package mybasepackage.login.springsecurity.config;

@Configuration
@EnableWebSecurity
@Import({ AppConfig.class })
@ComponentScan({ "mybasepackage.login.springsecurity.*" })

public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private DataSource dataSource;

        @Autowired
        private PasswordEncoder passwordEncoder;
}

However I can't understand why the first (correct and recommended) approach is not working and why the second approach is working ?

Also, in either case my controller which is in mybasepackage.login.springsecurity.controller package is never never recognized by the system, is that also related to this strange behavior ?

Upvotes: 2

Views: 88

Answers (2)

Ali Dehghani
Ali Dehghani

Reputation: 48213

@ComponentScan({"mybasepackage.login.springsecurity.*"})

There is no need for .* for base packages, it's recursive by default. I guess dispatcher servlet config (AppConfig in your example) is child context and another one is parent context and you can't reference to child beans from parent.

It's better to sperate your spring configurations based on say architectural aspects and only define related beans to that aspect in each config. For example, you could have a WebConfig java config which is annotated by EnableWebMvc and defines web related stuff, a DataConfig which defines your data related beans such as DataSource, TransactionManager, ... and a SecurityConfig which is annotated by EnableWebSecurity and defines security beans such as PasswordEncoder,... .

Upvotes: 1

user4610470
user4610470

Reputation:

here i have sample application configuration.

spring-servlet xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" 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/context
            http://www.springframework.org/schema/context/spring-context-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/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:annotation-config />

    <mvc:annotation-driven />

    <context:component-scan base-package="com.WordOfTheDay" />

    <mvc:interceptors>
        <bean id="webContentInterceptor"
            class="org.springframework.web.servlet.mvc.WebContentInterceptor">
            <property name="cacheSeconds" value="0" />
            <property name="useExpiresHeader" value="false" />
            <property name="useCacheControlHeader" value="true" />
            <property name="useCacheControlNoStore" value="true" />
        </bean>
    </mvc:interceptors>

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/Messages" />
        <property name="cacheSeconds" value="3000" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager"
        p:sessionFactory-ref="sessionFactory" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.connection.CharSet">utf8</prop>
                <prop key="hibernate.connection.characterEncoding">utf8</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
            </props>
        </property>
        <property name="packagesToScan" value="com.WordOfTheDay"></property>
    </bean>

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/demo"
        p:username="root" p:password="123" />


    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/views/" p:suffix=".jsp" />

</beans>

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/security
                           http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <security:http auto-config="true">

        <security:intercept-url pattern="/login.do"
            access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/logout.do"
            access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/fail2login.do"
            access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <security:intercept-url pattern="/json/*.do"
            access="IS_AUTHENTICATED_ANONYMOUSLY" />

        <security:intercept-url pattern="/*" access="ROLE_ADMIN" />
        <security:form-login login-page="/login.do"
            default-target-url="/home.do" authentication-failure-url="/fail2login.do" />

        <security:session-management>
            <security:concurrency-control
                max-sessions="1" />
        </security:session-management>
        <security:logout logout-success-url="/logout.do"
            delete-cookies="JSESSIONID" invalidate-session="true" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:jdbc-user-service
                data-source-ref="dataSource"
                users-by-username-query="select userName, password, status from User where userName=?"
                authorities-by-username-query="select us.userName, ur.userRoleName from User us, UserRole ur   
                where ur.userName =?  " />
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

xml base configuration maybe very easy.

Upvotes: 0

Related Questions