2

I have trouble understanding Spring MVC configuration and initialisation. I'm not sure when to use annotation and when not to use annotation!

My app is structured in two war modules. I'm not too concerned about duplicating the bean container in both. But at startup both modules are initialising the spring context twice as evidenced in this log taken from one of the modules from startup:

[2015-08-15 03:49:51,416] Artifact frontend:war exploded: Deploy took 27,529 milliseconds
15:50:00.051 DEBUG com.ocscommerce.admin.configuration.WebConfig 53 <init> - Initialising WebConfig
15:50:06.409 DEBUG com.ocscommerce.admin.configuration.AppConfig 48 <init> - Loading application context
15:50:06.424 DEBUG com.ocscommerce.admin.configuration.SecurityConfig 54 <init> - Loading security config.
15:50:07.327 DEBUG com.ocscommerce.services.configuration.SolrConfig 43 <init> - Loading SOLR Config.
2015-08-15 15:50:08.194 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2015-08-15 15:50:08.200 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
15:50:11.269 DEBUG com.ocscommerce.admin.configuration.WebConfig 53 <init> - Initialising WebConfig
15:50:13.498 DEBUG com.ocscommerce.admin.configuration.AppConfig 48 <init> - Loading application context
15:50:13.503 DEBUG com.ocscommerce.admin.configuration.SecurityConfig 54 <init> - Loading security config.
15:50:13.999 DEBUG com.ocscommerce.services.configuration.SolrConfig 43 <init> - Loading SOLR Config.
2015-08-15 15:50:14.336 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2015-08-15 15:50:14.337 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue

why there's 4 memcached connections, I'm not sure, but that's a problem for another day....

For today I just want to figure out why my context is being initialised twice for each module...

Web.XML - has references to the appconfig, and to the webconfig classes in the xml. Each module has separate web.xml files.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/pages/errors/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/pages/errors/500.jsp</location>
    </error-page>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.ocscommerce.admin.configuration.AppConfig</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <page-encoding>UTF-8</page-encoding>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>

        </jsp-property-group>
    </jsp-config>

    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                com.ocscommerce.admin.configuration.WebConfig
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>encoding-filter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding-filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <filter>
        <display-name>springMultipartFilter</display-name>
        <filter-name>springMultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springMultipartFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <display-name>springSecurityFilterChain</display-name>
        <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>
        <dispatcher>ERROR</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
</web-app>

Then in the AppConfig class, it imports some other bean definition classes that are probably irrelevant to the question. The signature looks like this:

@Configuration
@PropertySource(value = {"classpath:application.properties"})
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableCaching
@EnableTransactionManagement
@ComponentScan({"com.ocscommerce.admin", "com.ocscommerce.services"})
@Import(value = {SolrConfig.class, SecurityConfig.class, PersistenceConfig.class})
public class AppConfig {
}

Then WebConfig extends the WebMvcAdapter and has components like this:

@Configuration
@EnableWebMvc
@ComponentScan({"com.ocscommerce.admin", "com.ocscommere.services"})
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableCaching
public class WebConfig extends WebMvcConfigurerAdapter {
}

I'm wondering if I have too many component scans there?

Can someone help me fix this config?

Thank you...

Richard G
  • 5,243
  • 11
  • 53
  • 95

1 Answers1

1

I think you've answered your own question, you're doing a component scan in both the web config and app config.

Refactor the package name in the component scans so that the web config is only picking up any of beans that are relevant to the web tier and the app config is only picking your application beans (eg services). Remember that with the contextloaderlistener, the webconfig will be able to see the beans that are in the app config.

Dick Chesterwood
  • 2,629
  • 2
  • 25
  • 33
  • see the previous answer, I took out the component scans from the webconfig but the server won't start because it complains of missing autowire dependencies from the services tier. I use Intellij and it complains it's missing too, we checked classpath already. – Richard G Aug 16 '15 at 00:12
  • You shouldn't remove all of the component scans from `WebConfig`, only those that are specific to your application domain. `WebConfig` should scan only those classes relevant to Spring MVC, such as `@Configuration` related to Spring MVC or `@Controller` classes, for example. Spring should create these objects in the dispatcher context. (continued...) – Derek Mahar Jan 18 '16 at 21:23
  • (...continuation) `AppConfig` should scan those classes relevant to the application domain and Spring should create these objects in the root context. The Spring dispatcher context inherits the root context, so objects in the dispatcher context like controllers may access objects in the root context. – Derek Mahar Jan 18 '16 at 21:24