Best configuration for spring 3.2.3

hibernate, spring, spring-mvc

Solution

You can change your web.xml context param to:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

And create any count of context files without importing it to root context

Also it is very useful when you have multimodule project and put configuration files to each module, name it applicationContext-.xml and it will be automatically scanned.

It is good practice to declare mvc components in mvc-dispatcher-servlet.xml: interceptors (locale, theme interceptors and your own), view resolvers, resources, exception-handlers, templating-engine configuration and other components that relates with view.

Also it is useful to declare component-scan only for controllers in servlet configuration:

mvc-dispatcher-servlet.xml:

<context:component-scan base-package="by.company.app" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

When in applicationContext exclude @Controller scan:

applicationContext.xml:

<context:component-scan base-package="by.company.app">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

That helps to avoid duplicated bean definitions

Example of separate applicationContexts (namespaces declaration omitted):

applicationContext.xml:

<beans>    
    <context:property-placeholder location="classpath*:META-INF/spring/a-*.properties" />

    <task:annotation-driven/>

    <context:spring-configured/>

    <context:component-scan base-package="by.company.app">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
</beans>

applicationContext-db.xml

<beans>
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://${database.host}:${database.port}/${database.db-path}" />
        <property name="driverClassName" value="${database.driverClassName}" />
        <property name="username" value="${database.username}" />
        <property name="password" value="${database.password}" /> 
    </bean>

    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnit"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties"> 
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.max_fetch_depth">3</prop> 
                <prop key="hibernate.jdbc.fetch_size">50</prop> 
                <prop key="hibernate.jdbc.batch_size">10</prop> 
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.connection.charSet">UTF-8</prop>
                <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
            </props> 
        </property>
    </bean>

    <jpa:repositories base-package="by.company.app" />

</beans>

Problem

I'm trying to understand spring configuration. I read both articles: - http://www.onjava.com/pub/a/onjava/2006/03/22/advanced-spring-configuration.html?page=1 - http://syntx.io/difference-between-loading-context-via-dispatcherservlet-and-contextloaderlistener/ These suggest to have 2 configuration files: “Application Context” and “Web Application Context”. If you have ever tried to develop a web application using the Spring MVC framework, you know that there are two configuration files that should be used: /WEB-INF/applicationContext.xml allows you to configure your beans, or to indicate the context of your application. This is the place where you define your business logic beans, resources, and all other beans that are not directly related to the web tier. /WEB-INF/[servlet-name]-servlet.xml is used to configure the web tier and view resolvers, controllers, validators, and all other beans that you need in the MVC framework. The [servlet-name] refers to the name of the Spring's dispatcher servlet defined in the web.xml deployment descriptor. According to this, I write my web.xml as follow: ``` <?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"> <!-- Application Context --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/spring-security.xml</param-value> </context-param> <!-- Spring MVC --> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- Spring Security --> <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> </filter-mapping> <!-- Fin Spring Security --> </web-app> ``` This is my applicationContext.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:jee="http://www.springframework.org/schema/jee" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"> <!-- Look in tom cats context --> <jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/rhcimax"/> <!-- Hibernate Session Factory --> <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="packagesToScan"> <array> <value>com.blah.baseProject</value> </array> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect </value> </property> </bean> <!-- Hibernate Transaction Manager --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="mySessionFactory"/> </bean> <!-- Activates annotation based transaction management --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans> ``` And this is my mvc-dispatcher-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:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!-- Enable @Controller annotation support --> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- Map simple view name such as "test" into /WEB-INF/views/test.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/view/" /> <property name="suffix" value=".jsp" /> </bean> <!-- Scan classpath for annotations (eg: @Service, @Repository etc) --> <context:component-scan base-package="com.blah.baseProject"/> </beans> ``` I want to know if this configuration is almost correct. This configuration runs but I feel that applicationContext.xml is not been called since I get this exception: ``` org.hibernate.HibernateException: No Session found for current thread ``` My intention is to keep good practices in spring and to learn the right configuration. "It is a best practice to keep a clear separation between middle-tier services such as business logic components and data access classes (that are typically defined in the ApplicationContext) and web- related components such as controllers and view resolvers (that are defined in the WebApplicationContext per Dispatcher Servlet)."

Original source