Menu

Cannot hot-redeploy Spring App

2003-09-19
2004-03-31
  • Dwight Gunning

    Dwight Gunning - 2003-09-19

    I am using Hibernate with Spring configured beans with relatively few problems. The setup actually uses a ContextLoader servlet that runs on startup instead of a ContextLoader listener as a workaround for some classloading issues I had earlier.

    The configuration loads excellently when the server starts. However, when changes are made to the code, and the Hot-Redeploy feature of WebSphere destroys and reloads the servlets, the Spring configuration fails when it attempts to load the SessionFactory.

    The exception is a PropertyVetoException, and in this case it appears the LocalSessionFactoryBean is not being converted properly to a SessionFactory when the application is hot-redeployed. This makes it necessary to restart the server.

    The start of the stack-trace is as follows:

    ------------------------------------------------

    [9/19/03 16:05:48:375 GMT-05:00] 17705da6 XmlBeanFactor I org.springframework.beans.factory.xml.XmlBeanFactory  Creating shared instance of singleton bean 'trnSessionFactory'
    [9/19/03 16:05:48:438 GMT-05:00] 17705da6 ContextLoader E org.springframework.web.context.ContextLoader  Failed to initialize beans in application context: Can't resolve reference to bean [trnReferenceDAO] while setting properties on bean [trnReferenceDAO]; nested exception is:
        PropertyVetoExceptionsException: 1 errors:-- ErrorCodedPropertyVetoException: message=[Failed to convert property value of type [org.springframework.orm.hibernate.LocalSessionFactoryBean] to required type [net.sf.hibernate.SessionFactory] for property named [sessionFactory]; nested exception is:
        java.lang.IllegalArgumentException: argument type mismatch]; errorCode=[typeMismatch]
    [9/19/03 16:05:48:594 GMT-05:00] 17705da6 ContextLoader E org.springframework.web.context.ContextLoader  TRAS0014I: The following exception was logged PropertyVetoExceptionsException: 1 errors:-- ErrorCodedPropertyVetoException: message=[Failed to convert property value of type [org.springframework.orm.hibernate.LocalSessionFactoryBean] to required type [net.sf.hibernate.SessionFactory] for property named [sessionFactory]; nested exception is:
        java.lang.IllegalArgumentException: argument type mismatch]; errorCode=[typeMismatch]
    java.lang.IllegalArgumentException: argument type mismatch
        at java.lang.reflect.Method.invoke(Native Method)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:514)

     
    • Chris Harris

      Chris Harris - 2003-09-22

      Please excuse this if it is unhelpful/irrelevant:

      I use JBoss, and had a similar problem, where my app whould start up fine on an initial start of the appserver, but not hot-redeploy. The error wasn't the same, but was a similar type-mismatch situation. It occurred because the class concerned hadn't been unloaded at the undeploy; this was becuase an object of the class was still being referenced. In my case, this was because I had the spring.jar in the appserver's general library, where of course it wasn't being undeployed/reployed. I moved it to the application's lib, and everything worked fine.
      Hope this helps.

       
      • Rod Johnson

        Rod Johnson - 2003-09-22

        I deploy spring.jar as part of my application (WAR or EAR referenced by ejb-jar.file's manifest classpath). I've found that hot deploy works perfectly in WebLogic 8.1. I've not tried in WebSphere.

        Please provide further information if you're still having problems.

        Regards,
        Rod

         
        • Edgar Vonk

          Edgar Vonk - 2004-03-30

          I seem to encounter the hot-redeploy problem on WebSphere App Server 4 / WebSphere Portal Server 4.
          WebSphere App Server does not really provide a hot-redeploy as such, but on a running server you can stop an enterprise application, remove it, install a new version of the application and start it again using the WebSphere admin console.

          WebSphere Portal Server provides a more convenient hot-redeploy mechanism ("portlet upgrade") but it uses the same WebSphere App Server mechanism.

          The problem is that after stopping the EAR in which a spring.jar resides the spring.jar cannot be removed from the file system in which WebSphere has deployed the EAR's contents. It seems the classloader still has a Spring class loaded which it cannot unload.

          I have tried this using the Spring Framework 1.0 final release using the 'minimal web application' example provided with Spring. The following JARs reside in my WEB-INF/lib of the minimal web app WAR:
          - spring.jar
          - commons-logging.jar
          - log4j-1.2.8.jar

          After stopping the EAR in which the minimal web app is packaged I can remove all JARs in the WEB-INF/lib except the spring.jar.

          Attempting to redeploy the WAR fails in overwriting the spring.jar as it is locked. The only way I can overwrite the spring.jar (e.g. for upgrading it to a new version) is to stop the entire application server instance in WebSphere.

          It is quite problematic as I have packaged the spring.jar in one of my portlet WARs for use in WebSphere Portal Server and this behaviour in some occasions causes the portlet upgrade to fail. After which the portlet is in a corrupt state and the only thing I can do is stop the app server, remove it by hand and reinstall it.

          I've also tried by only including the spring-core and spring-dao JARs (since currently these are the only ones use) but to no avail.

          I have not tried this yet in WebSphere 5.

          Any ideas?

           
          • Seth Ladd

            Seth Ladd - 2004-03-30

            I am not using WebSphere, but I am using Tomcat 5.0.19 and I too see this problem.  Tomcat will let you redeploy the webapp, but the spring minimal webapp does leak memory on redeploy.  Using a profiler, I seem to see some classes stick around, which causes the WebAppClassLoader to stick around (hence the memory leak).

            From what I saw, the static classes from BeanWrapperImpl (the static init block at the top of the class) stick around even after I've unloaded the minimal webapp.

            I've tested a bare bones webapp and loading and unloading from Tomcat, and that does not leak memory.  So I'm guessing that something that Spring does is sticking around, keeping the classloader around, and therefore, leaks memory.

            I wish I had a solution for you!

            Seth

             
    • Dwight Gunning

      Dwight Gunning - 2003-09-22

      spring.jar is under WEB-INF/lib of the web project. The web Project shares the same classloader with other dependent Java projects, which are specified in the MANIFEST classpath of the Web Project.

       
    • Darren Davison

      Darren Davison - 2003-09-22

      I've seen this happen on WebSphere from within the WSAD IDE but haven't paid the stack traces too much heed in the past, I tend to just restart the server and get back to my application issues.  I'll take a close look tomorrow though.

      What version of WebSphere are you using, and are you experiencing this issue from a server running locally via the IDE or one that you attach to remotely?

       
    • Dwight Gunning

      Dwight Gunning - 2003-09-22

      I am using WSAD 5.0.1, and I am running the WebSphere Test environment, not a remote server.

       
    • Darren Davison

      Darren Davison - 2003-09-23

      If you right-click the server instance from the Servers view in the IDE and select "Restart Project > [YourEAR]" (where YourEAR is the EAR project containing the web module), does the error occur then?

      Also, are you running a version 4.x Test server or a version 5.x test server (it's possible for the IDE to run either with a suitable installation)

       
    • Dwight Gunning

      Dwight Gunning - 2003-09-23

      The error does not occur when I Restart the Project, only upon hot-redeploy. I am using the version 5.x Test Server

       
      • Darren Davison

        Darren Davison - 2003-09-24

        After some time looking at this, I can't see a fix, but my guess would be it's something to do with how the WAS classloaders treat various libraries within either individual projects or the containing EAR file in the IDE.

        Simply restarting an individual project within the EAR triggers the exceptions (which will vary depending on the contents of your Spring context files).  Even without changing any code in your project this seems to occur.  However, if the EAR itself is restarted, and thereby all the modules within it but without having to restart the server, then all projects reload correctly even if changes have been made to application code.

        Originally it looked as though utility JARs, or project JARs (Eclipse projects that are 'dynamically' exported as libraries that your Web modules can reference) may have been the problem as they are configured at this higher level, but even removing them and explicitly exporting a standard JAR file into the project didn't help.

        Can you also trigger this with non-Spring projects (I haven't tried yet) then we'll know whether to take this somewhere more IBM specific or look harder ourselves.  My concern would be that it may possibly occur in production systems if admins re-configure something and restart a project for example.

        Darren.

         
    • Dwight Gunning

      Dwight Gunning - 2003-09-24

      I will try a non-Spring application and see if it happens then. In the meanwhile, you have ben of great help.

       
    • Anonymous

      Anonymous - 2003-09-24

      Just so it is documented and in case this helps, I am having a similar issue hot deploying the completed "Developing a Spring Framework MVC applicaton step-by-step" sample application on JBoss 3.2.2 RC3.  When starting JBoss there is no exception but when redeploying the WAR I get the following stack trace:

      11:27:27,662 INFO  [XmlBeanFactory] Loading XmlBeanFactory from InputStream [java.io.ByteArrayInputStream@31d5e2]
      11:27:27,756 ERROR [Engine] StandardContext[/examplespringapp]: Servlet /examplespringapp threw load() exception javax.servlet.ServletException: Servlet.init() for servlet springapp threw exception
              at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:963)
              at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:823)
              at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3421)
              at org.apache.catalina.core.StandardContext.start(StandardContext.java:3609)
              at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:821)
              at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
              at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:579)
              at org.jboss.web.tomcat.tc4.EmbeddedTomcatService.createWebContext(EmbeddedTomcatService.java:517)
              at org.jboss.web.tomcat.tc4.EmbeddedTomcatService.performDeploy(EmbeddedTomcatService.java:302)
              at org.jboss.web.AbstractWebContainer.start(AbstractWebContainer.java:428)
              at org.jboss.deployment.MainDeployer.start(MainDeployer.java:824)
              at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:632)
              at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:605)
              at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:324)
              at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
              at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546)
              at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:177)
              at $Proxy6.deploy(Unknown Source)
              at org.jboss.deployment.scanner.URLDeploymentScanner.deploy(URLDeploymentScanner.java:302)
              at org.jboss.deployment.scanner.URLDeploymentScanner.scan(URLDeploymentScanner.java:458)
              at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.doScan(AbstractDeploymentScanner.java:201)
              at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.loop(AbstractDeploymentScanner.java:212)
              at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.run(AbstractDeploymentScanner.java:191)
      11:27:28,022 ERROR [Engine] ----- Root Cause -----
      java.lang.VerifyError: (class: gov/pbgc/pamt/examplespringapp/db/ProductManagerDaoJdbc, method: getProductList signature: ()Ljava/util/List;) Incompatible object argument for function call
      ...

      Please let me know if more information would be helpful.

       
    • Edgar Vonk

      Edgar Vonk - 2004-03-31

      Thank you Seth.

      I have tested the exact same scenario on WebSphere 5 and there I do not see the problem. Upon stopping the enterprise app in which the minimal web app runs I can simply remove the spring.jar. It is not locked. Also, upgrading the minimal WAR (which is a lot more convenient in WebSphere 5) overwrites all the resources correctly including the spring.jar.

      I think for now I will put the spring.jar (or rather the spring-dao and core JARs) in WebSphere 5's system classpath. I've tested this before and that works well. With that solution at least I can upgrade my portlet WARs safely.

      That you too see this behaviour in Tomcat 5 is worrying though..

       

Log in to post a comment.