Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: tcp-connection-factory not cleaned up on webapp container shutdown

  1. #1
    Join Date
    Jan 2009
    Posts
    22

    Default tcp-connection-factory not cleaned up on webapp container shutdown

    Hi all,

    I'm coming across a problem which I hope is a simple fix.

    I'm using a tcp-connection-factory and tcp-inbound-channel-adapter to receive messages from a SI TCP client, given the config below:

    Code:
    <ip:tcp-connection-factory id="tcpserver"
                                 type="server"
                                 port="7899"
                                 single-use="true"
                                 so-timeout="30000"
                                 using-nio= "true"
                                 serializer="defaultSerializer"
                                 deserializer="defaultDeserializer"/>
    
    <ip:tcp-inbound-channel-adapter id="inboundServer"
        channel="statsChannel"
        connection-factory="tcpserver"/>
    This all works nicely and message receipt is OK, until it comes to the point where I want to shut my webapp container (Tomcat) down. Stopping the container results in a hanging thread somewhere, and I have to kill -9 the Tomcat process.

    If I remove the tcp-connection-factory declaration from my config and replicate the test, Tomcat shuts down successfully.

    This scenario happens whether the server has received a message or not, if that makes any difference...

    Any thoughts?

  2. #2
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    How are you instantiating the application context?

    When running in a web container, it should be instantiated using a ContextLoaderListener in web.xml; then, when the container is shut down, the listener will close the application context which will, in turn, shut down all Spring Integration components.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #3
    Join Date
    Jan 2009
    Posts
    22

    Default

    Hi Gary,

    Sorry for the delayed response.

    I do declare ContextLoaderListener in my web.xml. I'm guessing this grabs the applicationContext.xml, which houses a custom property configurer, and imports to my other xml configs:

    Code:
    <import resource="integration-config.xml"/>
    I can see info in my logs pertaining to the other elements being shut down (including some of my other SI elements), but it's just this particular tcp-connection-factory element that doesn't seem to stop cleanly.

    P.S. do I have to declare <context-param>s for each of my separate config files instead of doing <import resource="..."/>?
    Last edited by clydefrog; Mar 21st, 2011 at 10:04 AM.

  4. #4
    Join Date
    Jan 2009
    Posts
    22

    Default

    Ah, I guess that putting child xml declarations in applicationContext.xml doesn't inherently register them with the ContextLoaderListener?

    I changed my web.xml config to:

    Code:
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/applicationContext.xml, WEB-INF/integration-config.xml</param-value>
      </context-param>
    and kept the non-listener-dependent configs as children of applicationContext.xml

    This seems to work on shutdown, but only after a given period of time (a few seconds) and with this final exception:

    Code:
    Exception in thread "pool-1-thread-1" java.lang.NullPointerException
    	at org.apache.log4j.Category.isEnabledFor(Category.java:746)
    	at org.apache.commons.logging.impl.Log4JLogger.isTraceEnabled(Log4JLogger.java:327)
    	at org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory.doSelect(TcpNioServerConnectionFactory.java:115)
    	at org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory.run(TcpNioServerConnectionFactory.java:85)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    	at java.lang.Thread.run(Thread.java:619)
    Is this "normal"?

  5. #5
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    Hmmm... that's very strange.

    <import /> Vs. explicitly listing the config file in the context-param shouldn't make any difference; everything goes into the same application context. <import/>s are not really 'child' contexts.

    The null pointer is inside log4j - even weirder.

    Can you reproduce with a simple example?

    Thanks.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #6
    Join Date
    Jan 2009
    Posts
    22

    Default

    Yeah it is pretty weird.

    I seem to get that NPE *after* the webapp has shutdown so I guess the connection factory is attempting to log something, and the logger has already been destroyed.

    I'll try and put together a test case ASAP.

  7. #7
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    Work-around is to use an external <task:executor/> (see the reference guide and https://jira.springsource.org/browse/INT-1854 for details).
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  8. #8
    Join Date
    Jan 2009
    Posts
    22

    Default

    Thanks for the link Gary - I'll try that workaround when I'm back from holiday.

    I didn't file that bug report, so I guess it's a timely coincidence!

  9. #9
    Join Date
    Jan 2009
    Posts
    22

    Default

    That workaround works for me. The executor is now shutdown nicely, and so is my webapp.

    Thanks for the help!

  10. #10

    Default

    I wonder if this relates to the socket closing issue we observerd, and why we added to our: <ip:tcp-inbound-gateway...> the param connection-factory="incomingMuConnectionFactory".

    The <ip:tcp-connection-factory id="incomingMuConnectionFactory"...> then has the param:
    interceptor-factory-chain="socketClosingFactoryChain" /> for is this bean:

    Code:
        <bean id="socketClosingFactoryChain" class="org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain">
            <property name="interceptors">
                <array>
                    <bean class="com.wfb.csts.framework.tcp.connection.SocketClosingInterceptorFactory" />
                </array>
            </property>
        </bean>
    The class is then:
    Code:
    public class SocketClosingInterceptorFactory implements TcpConnectionInterceptorFactory
    {
        @Override
        public TcpConnectionInterceptor getInterceptor() {
            return new AbstractTcpConnectionInterceptor()
            {
                @Override
                public void send(Message<?> message) throws Exception {
                    super.send(message);
                    this.close();
                }
            };
        }
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •