Announcement Announcement Module
Collapse
No announcement yet.
Tomcat problem: ConfigurableApplicationContext not closing? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Tomcat problem: ConfigurableApplicationContext not closing?

    Hello everyone!

    I have a Tomcat webapp which creates a ConfigurableApplicationContext from an XML file (containing some Apache database and pooling classes). When I put a new release in the "webapps" folder, the application fails to close down and I get the classic Tomcat shutdown / redeployment error "INFO: Illegal access: this web application instance has been stopped already.".

    I have pinned down the problem to retrieval of the JdbcTemplate. If I retrieve the template and execute an SQL query on it, then this problem occurs. If I don't -- and just create the ApplicationContext but don't do any SQL stuff -- then the webapp closes down just fine, and the new release deploys as expected.

    When my servlet is going to die, I call the close() method on the application context. I can see in the logs that it gets called, but the close() method itself doesn't log anything so I'm not sure what, if anything, actually gets closed. My theory is that some Apache DB class is not getting killed when the context closes, but I'm not sure how to find out which one or what do do about it.

    Any insight and trouble-shooting advice would be greatly appreciated!

    My Spring configuration below:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schem...ing-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <bean id="environment" class="org.springframework.beans.factory.config.Pr opertyPlaceholderConfigurer" lazy-init="false">
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="locations">
    <list>
    <value>
    file:C:\Documents and Settings\robert\eclipse-workspace\database.properties
    </value>
    </list>
    </property>
    </bean>

    <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="basicDataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="pool" destroy-method="close" class="org.apache.commons.pool.impl.GenericObjectP ool">
    <property name="minEvictableIdleTimeMillis" value="300000"/>
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>
    <property name="maxActive" value="20"/>
    </bean>

    <bean id="connectionFactory" class="org.apache.commons.dbcp.DataSourceConnectio nFactory">
    <constructor-arg ref="basicDataSource"/>
    </bean>

    <bean id="poolableConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionF actory">
    <constructor-arg index="0" ref="connectionFactory"/>
    <constructor-arg index="1" ref="pool"/>
    <constructor-arg index="2"><null/></constructor-arg>
    <constructor-arg index="3" value="select sysdate from dual"/>
    <constructor-arg index="4" value="false"/>
    <constructor-arg index="5" value="true"/>
    </bean>

    <bean id="pooledDataSource" class="org.apache.commons.dbcp.PoolingDataSource" depends-on="poolableConnectionFactory">
    <constructor-arg ref="pool"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
    <property name="dataSource" ref="pooledDataSource"/>
    </bean>

    </beans>

    Regards,
    Robert

  • #2
    If it helps, I've now noticed that when this occurs, the only file left in my webapp directory on Tomcat redeployment is my Oracle JDBC jar, ojdbc-1.4.jar, in the web-info\lib folder. I'm guessing that my BasicDataSource instance holds on to it and that the BasicDataSource isn't properly by Spring when the context dies. I guess in theory it could also be a problem with the BasicDataSource itself. Any advice on how to proceed is appreciated.

    Comment


    • #3
      And this is the actual log with stack trace from Tomcat on failure to redeploy. Something to do with my instance of org.apache.commons.pool.impl.GenericObjectPool I guess...

      INFO: Undeploying context [/apptest]
      2007-okt-05 20:51:51 org.apache.catalina.startup.HostConfig deployWAR
      INFO: Deploying web application archive apptest.war
      2007-okt-05 20:52:31 org.apache.catalina.loader.WebappClassLoader loadClass
      INFO: Illegal access: this web application instance has been stopped already. Could not load java.util.ListIterator. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
      java.lang.IllegalStateException
      at org.apache.catalina.loader.WebappClassLoader.loadC lass(WebappClassLoader.java:1244)
      at org.apache.catalina.loader.WebappClassLoader.loadC lass(WebappClassLoader.java:1204)
      at java.lang.ClassLoader.loadClassInternal(Unknown Source)
      at org.apache.commons.pool.impl.GenericObjectPool.evi ct(GenericObjectPool.java:981)
      at org.apache.commons.pool.impl.GenericObjectPool$Evi ctor.run(GenericObjectPool.java:1112)
      at java.util.TimerThread.mainLoop(Unknown Source)
      at java.util.TimerThread.run(Unknown Source)

      Comment


      • #4
        Some further details:

        My understanding, having looked at the GenericObjectPool documentation and source, is that the problem occurs when the Evictor thread (which periodically examines the state of idle objects -- in this case connections) tries to iterate through the list of objects. At that point the class loader somehow kicks in, perhaps because the members on which methods are called have been garbage collected. At that point Tomcat denies reloading the classes as it believes the webapp has been killed already.

        I tried to get around this by explicitly retrieving my GenericObjectPool instance from the ConfigurableApplicationContext in the contextDestroyed() method of my ServletContextListener class, and then calling close() on that instance, but that unfortunately did not help.

        Comment


        • #5
          There is universal solution for DBCP-related problems - get rid of DBCP and use C3P0 instead.

          Comment


          • #6
            Thanks for the suggestion. I will definitely look into it, if the license fits.

            However, I'm somewhat concerned that this problem could creep up again generally since it appears to have something to do with instances closing down, it looks Spring related to me one way or another.

            Comment


            • #7
              Originally posted by Robert Björn View Post
              Thanks for the suggestion. I will definitely look into it, if the license fits.

              However, I'm somewhat concerned that this problem could creep up again generally since it appears to have something to do with instances closing down, it looks Spring related to me one way or another.
              Its license is LGPL.

              Comment

              Working...
              X