Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC, two instances of configuration instead of one

I'm starting to learn about Spring MVC. I'm trying to get rid of all Spring XML configuration. Here is my web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
    version="3.0">
  <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
       instead of the default XmlWebApplicationContext -->
  <context-param>
      <param-name>contextClass</param-name>
      <param-value>
          org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
  </context-param>

  <!-- Configuration locations must consist of one or more comma- or space-delimited
       fully-qualified @Configuration classes. Fully-qualified packages may also be
       specified for component-scanning -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
  </context-param>

  <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Declare a Spring MVC DispatcherServlet as usual -->
  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
           instead of the default XmlWebApplicationContext -->
      <init-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </init-param>
      <!-- Again, config locations must consist of one or more comma- or space-delimited
           and fully-qualified @Configuration classes -->
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
      </init-param>
  </servlet>

  <!-- map all requests for / to the dispatcher servlet -->
  <servlet-mapping>
      <servlet-name>dispatcher</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

Appconfiguration.java:

@Configuration
@EnableTransactionManagement
@ComponentScan("pl.mbrnwsk.sklep")
public class AppConfiguration {

    public String hbm2ddl_auto = "update";

    public AppConfiguration(){
        System.out.println("AppConfiguration");
    }

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("org.hsqldb.jdbcDriver");
        ds.setUrl("jdbc:hsqldb:file:/SklepDB/");
        ds.setUsername("SA");
        ds.setPassword("");
        return ds;
    }

    @Bean
    public SessionFactory sessionFactory() {
        LocalSessionFactoryBuilder ss = new LocalSessionFactoryBuilder(dataSource());
        ss.scanPackages("pl.mbrnwsk.sklep.model");
        ss.setProperty("hibernate.show_sql", "true");
        ss.setProperty("hibernate.hbm2ddl.auto", hbm2ddl_auto);
        ss.setProperty("hibernate.dialect",
                "org.hibernate.dialect.HSQLDialect");
        return ss.buildSessionFactory();
    }

    @Bean
    public PlatformTransactionManager txManager(){
        return new HibernateTransactionManager(sessionFactory());   
    }
}

The instance of AppConfiguration is being created two times: once when I start Tomcat and twice when I enter some url that should be handled by dispatcher. This is not desired behaviour. I would like to have AppConfiguration created just with Tomcat start. How to achieve this? And second question, what does listener do?

like image 758
user1091733 Avatar asked Dec 20 '25 23:12

user1091733


1 Answers

The problem here is that you are using the same config for the servlet and the root context. Thats why you have two instance of the configuration. In Spring MVC, you have 2 contexts, the servlet context and the root context. The servlet context is for your controllers and the root context for your business objects and your services.

If you don't want to use XML, create two config classes. Something like this :

Root context :

@Configuration
@EnableTransactionManagement
@ComponentScan("pl.mbrnwsk.sklep")
public class AppConfiguration {

    public String hbm2ddl_auto = "update";

    public AppConfiguration(){
        System.out.println("AppConfiguration");
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("org.hsqldb.jdbcDriver");
        ds.setUrl("jdbc:hsqldb:file:/SklepDB/");
        ds.setUsername("SA");
        ds.setPassword("");
        return ds;
    }

    @Bean
    public SessionFactory sessionFactory() {
        LocalSessionFactoryBuilder ss = new LocalSessionFactoryBuilder(dataSource());
        ss.scanPackages("pl.mbrnwsk.sklep.model");
        ss.setProperty("hibernate.show_sql", "true");
        ss.setProperty("hibernate.hbm2ddl.auto", hbm2ddl_auto);
        ss.setProperty("hibernate.dialect",
                "org.hibernate.dialect.HSQLDialect");
        return ss.buildSessionFactory();
    }

    @Bean
    public PlatformTransactionManager txManager(){
        return new HibernateTransactionManager(sessionFactory());   
    }
}

Servlet context :

@Configuration
@ComponentScan("pl.mbrnwsk.sklep.controller")
public class ServletConfiguration {

    public AppConfiguration(){
        System.out.println("ServletConfiguration");
    }

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

Web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
        version="3.0">
      <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
           instead of the default XmlWebApplicationContext -->
      <context-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </context-param>

      <!-- Configuration locations must consist of one or more comma- or space-delimited
           fully-qualified @Configuration classes. Fully-qualified packages may also be
           specified for component-scanning -->
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
      </context-param>

      <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

      <!-- Declare a Spring MVC DispatcherServlet as usual -->
      <servlet>
          <servlet-name>dispatcher</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
               instead of the default XmlWebApplicationContext -->
          <init-param>
              <param-name>contextClass</param-name>
              <param-value>
                  org.springframework.web.context.support.AnnotationConfigWebApplicationContext
              </param-value>
          </init-param>
          <!-- Again, config locations must consist of one or more comma- or space-delimited
               and fully-qualified @Configuration classes -->
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>pl.mbrnwsk.sklep.config.ServletConfiguration</param-value>
          </init-param>
      </servlet>

      <!-- map all requests for / to the dispatcher servlet -->
      <servlet-mapping>
          <servlet-name>dispatcher</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
</web-app>
like image 102
Jean-Philippe Bond Avatar answered Dec 22 '25 14:12

Jean-Philippe Bond



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!