Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-6356

Clustering failover not working on Tomcat

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 6.17.0, 7.5.0
    • Fix Version/s: 6.27.0, 7.7.0, 8.0.0-M6
    • Component/s: wicket
    • Environment:
      Tomcat 8.0.32, Apache 2.4, OSx and Solaris 9,

      Description

      Clustering failover with Tomcat 8 is not working for us in Production or locally on my Mac. The reason is the following from the debugging that I did and from the best of my understanding:

      Whenever a statefull page is used/touched the SessionEntry is updated. This SessionEntry is stored in the tomcats session under the attribute name "wicket:persistentPageManagerData-APPLICATION_NAME".
      However at the end of the wicket request, Session.internalDetach() is called and setAttribute() is called passing the wicket session under the name "wicket:wicket.hub:session". This triggers the replication in Tomcat (only when setAttribute is called and ONLY that attribute is replicated). Because the SessionEntry is stored under a different attribute name its never replicated.

      The only time the SessionEntry is replicated is when a node first starts up and joins the cluster , at this point all sessions are replicated across (including all attritbutes) by the daltamanager and SessionEntry#readObject() is used which contains all the pages. On Tomcat after this initial syncing of all sessions SessionEntry#readObject() is never used.

      So the only time session failover works is when you kill the other instance (in a 2 node cluster) just after the other instance starts up - at this point the correct SessionEntry is on the new instance. If however you visit some more pages the new pages are never replicated across as the SessionEntry is never replicated.

      Further to this IF the SessionEntry was to be replicated it would not be any good as the cache are transient
      private transient List<IManageablePage> sessionCache;
      private transient List<Object> afterReadObject

      This means any new pages created on the old instance (after the new instance has started up) are not available in the http session or the second level page store on the new instance.
      Therefore when the old instance in shut down the user is load balanced to the new instance. At this point the link in the page Wicket is looking for does not exist in the SessionEntry cache or the PageStore so it creates the page and looks for the component/link.This causes a ComponentNotFoundException for us because the links are either in a DataView which is never rendered so does not exist, or the other links are actually added to the page in an Ajax request and again because the page is not rendered are not there, Wicket then throws the exception and it appears to the user the session is lost.

      So in summary there seems there is no way for the current mechanism on Tomcat to work. It would seem the SessionEntry.sessionCache needs to be not transient and setAttribute needs to be called for the SessionEntry at the end of request on the internalDetach so that Tomcats deltamanager replicates that attribute in the session.

      Attached my quickstart , tomcat, and apache conf.

        Attachments

        1. IssueFiles.zip
          34 kB
          wayne pope
        2. PageStoreManager.java
          10 kB
          wayne pope

          Issue Links

            Activity

              People

              • Assignee:
                mgrigorov Martin Grigorov
                Reporter:
                waynegc wayne pope
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: