codehammer
codehammer

Reputation: 885

Spring beans getting initialized twice - Spring Integration

I'm trying to integrate my application with Spring Integration and experiencing that my custom spring beans are getting initialized twice, basically I see that the init method on these beans are getting called twice, once during the server startup and second time when HTTP request is made through DispatcherServlet.

Here is my web.xml configuration:

  <servlet>
        <servlet-name>webapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/servlet-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>webapp</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Here is my servlet-config.xml (with namespaces removed)

<import resource="springbeans-config.xml"/>

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

<context:annotation-config/>

<int:channel id="inboundChannel"/>
<int:channel id="outboundChannel"/>

<http:inbound-gateway request-channel="inboundChannel" reply-channel="outboundChannel" name="/*" supported-methods="GET, POST, PUT, DELETE" reply-timeout="120000"/>

<int:chain input-channel="inboundChannel">
    <int:service-activator ref="clearContext"/>
    <int:service-activator ref="gatewayFilter"/>
    <int:service-activator ref="audit_logger"/>
    <int:service-activator ref="gatewayContextHandler" method="process"/>
</int:chain>

The custom file springbeans-config.xml containing all the bean definitions is imported as shown above. For e.g. the bean definition below would be invoked twice, during the server startup and while making HTTP request which gets invoked through DispatcherServlet.

    <bean name="sample" class="com.test.SampleImpl" init-method="init">
    <property name="xpathHelper" ref="XPathHelper"/>
    <property name="cacheManager" ref="cacheManager"/>
</bean>

Wondering what I'm missing here. Would appreciate any pointers / help on this. Thanks.

===============================================================

UPDATE - SOLVED

loanshark example within SpringIntegration samples helped to resolve this issue.

Here is the updated web.xml

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

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

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

<servlet-mapping>
    <servlet-name>gateway</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Updated servlet-config.xml (with namespaces removed). Removed the import to bean definition file and component-scan and annotation-config in this file.

<http:inbound-gateway request-channel="inboundChannel" reply-channel="outboundChannel" name="/*" supported-methods="GET, POST, PUT, DELETE" reply-timeout="120000"/>

<int:chain input-channel="inboundChannel">
    <int:service-activator ref="clearContext"/>
    <int:service-activator ref="gatewayFilter"/>
    <int:service-activator ref="audit_logger"/>
    <int:service-activator ref="gatewayContextHandler" method="process"/>
</int:chain>

Renamed springbeans-config.xml to applicationContext.xml as per the sample, but I guess should not matter. Note, there are no imports in this file too.

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

<context:annotation-config/>

<bean name="sample" class="com.test.SampleImpl" init-method="init">
    <property name="xpathHelper" ref="XPathHelper"/>
    <property name="cacheManager" ref="cacheManager"/>
</bean>

Upvotes: 6

Views: 9364

Answers (1)

Gary Russell
Gary Russell

Reputation: 174739

Spring MVC Apps generally have 2 contexts; the servlet context and the root context.

It's generally good practice to put your "web" beans (@Controllers, views, Http inbound adatpers etc) in the servlet context and all the "business" beans in the root context.

Instead of importing your beans, you should put them in the root context using the context loader listener.

Beans in the servlet context can get references to beans in the root context, but not vice-versa.

The root context is loaded first; the filename doesn't matter but when using wildcards in the contextConfigLocation you need to be careful that the servlet context config is not picked up a second time.

Upvotes: 5

Related Questions