Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 515
codehammer Avatar asked Aug 16 '13 03:08

codehammer


People also ask

Are bean in Spring eagerly initialized?

By default, Spring creates all singleton beans eagerly at the startup/bootstrapping of the application context. The reason behind this is simple: to avoid and detect all possible errors immediately rather than at runtime.

Can two beans have same ID in Spring?

Here, @Bean instantiates two beans with ids the same as the method names and registers them within the BeanFactory (Spring container) interface. Next, we can initialize the Spring container and request any of the beans from the Spring container. This strategy also makes it simple to achieve dependency injection.

How beans are initialized in Spring?

The order of bean initialization is same as it's defined in the spring bean configuration file. The context is returned only when all the spring beans are initialized properly with post-init method executions. Employee name is printed as “Pankaj” because it was initialized in the post-init method.

What is lazy initialization Spring?

By default in Spring, all the defined beans, and their dependencies, are created when the application context is created. In contrast, when we configure a bean with lazy initialization, the bean will only be created, and its dependencies injected, once they're needed.


1 Answers

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.

like image 148
Gary Russell Avatar answered Dec 31 '22 18:12

Gary Russell