Announcement Announcement Module
No announcement yet.
Loading context files from within jars... and tomcat. Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Loading context files from within jars... and tomcat.

    I'm reading spring context xml from the classpath using "classpath*:META-INF/*-library.xml". This works beautifully and as expected.

    When the files are loaded from within jars that are on the classpath, I have a problem when I undeploy the web application. The application is shutdown, and partially undeploys, but then spring tries to reload files specified by the contextConfigLocation parameter.

    Here's the log (spacing added for clarity)...

    INFO: Manager: undeploy: Undeploying web application at '/atmospherics'
    [2006-03-15 13:41:53,359] INFO: org.apache.catalina.core.ApplicationContext(645) | Closing WebApplicationContext of Spring FrameworkServlet 'action-phone'
    [2006-03-15 13:41:53,359] INFO: org.apache.catalina.core.ApplicationContext(645) | Closing WebApplicationContext of Spring FrameworkServlet 'action'
    [2006-03-15 13:41:53,359] INFO: org.apache.catalina.core.ApplicationContext(645) | Closing Spring root WebApplicationContext
    [2006-03-15 13:41:53,379] INFO: com.cloudsystems.atmos.systemcontrol.systemmanagement.SystemManagementServiceImpl(228) | Destroying system management service
    [2006-03-15 13:41:53,379] INFO: org.apache.catalina.core.ApplicationContext(645) | Shutting down Log4J
    Mar 15, 2006 1:41:53 PM org.apache.catalina.startup.HostConfig checkResources
    INFO: Reloading context [/atmospherics]
    Mar 15, 2006 1:41:53 PM org.apache.catalina.core.StandardContext stop
    INFO: Container org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/atmospherics] has not been started
    Mar 15, 2006 1:41:54 PM org.apache.catalina.startup.ContextConfig applicationWebConfig
    INFO: Missing application web.xml, using defaults only StandardEngine[Catalina].StandardHost[localhost].StandardContext[/atmospherics]
    log4j:WARN No appenders could be found for logger (org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/atmospherics]).
    log4j:WARN Please initialize the log4j system properly.
    2006-03-15 13:41:54,261 ERROR org.springframework.web.context.ContextLoader - Context initialization failed
    org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is Could not open ServletContext resource [/WEB-INF/applicationContext.xml] Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
    Mar 15, 2006 1:41:54 PM org.apache.catalina.loader.WebappClassLoader loadClass
    INFO: Illegal access: this web application instance has been stopped already.  Could not load org.apache.log4j.spi.ThrowableInformation.  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.
    Tomcat thinks that the web application is still around because it is not entirely undeployed. WEB-INF/lib is still left in the webapps directory along with all of the project libraries. I think this is why it's reloaded.

    Note that the ApplicationContext is trying to load a context file specified in the web.xml, which is missing... so that value must be cached someplace.

    And this only happens when I'm loading context files from within a jar. If I load the same context files directly off of the classpath (which is not in a jar), it works fine and tomcat is able to undeploy the application without this strange restarting behavior.

    I'm pretty stumped... can anyone shed some light on this? I'm using Spring 1.2.7, Java 1.5.0, and Tomcat 5.5.12.


    Here is the code that loads these *-library context files:

    public void loadDeviceLibrary() {
        AbstractApplicationContext devicesContext = null;
        try {
            devicesContext = new ClassPathXmlApplicationContext(new String[] { "classpath*:" + libraryDescriptor });
        catch (BeanCreationException e) {
            log.error("An error exists in a '" + libraryDescriptor
                + "' file and the device library cannot be initialized.", e);
        Map devices = devicesContext.getBeansOfType(DeviceConfig.class);
   "Adding " + devices.size() + " devices to the device library...");
        for (Iterator i = devices.values().iterator(); i.hasNext();) {
        // Close the application contexts.
    Last edited by cnelson; Mar 15th, 2006, 06:50 PM.

  • #2
    After much testing and searching, I found this issue and thread which discusses my problem:

    Unfortunately, when using the classpath* wildcard, context files loaded from within jar files lock the jars and Tomcat becomes unhappy when the application is undeployed (even when using antiJARLocking).

    I have found a less elegant solution that is a work-around which does not require using the wildcard form of classpath. It works as expected without messing up Tomcat.

    It's a real shame that there isn't a good work-around for this problem.


    • #3
      I too had to install a workaround. I used to load all spring contexts via "classpath*:meta-inf/*.ctx.xml". But once I started deploying to tomcat this pattern did not resolve any files. So I had to change the pattern to "classpath*:/meta-infa/component.ctx.xml", with the limitation that each jar can provide only one "auto-loaded" spring context file.


      • #4
        This is exactly what I have done, and when the one auto-loaded beans file gets too large, I'll split it into separate files and load them explicitly via <import resource="..."/> elements in the auto-loaded file.

        Just wanted to offer that in case anybody reading this is venturing down this path for the first time.