tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p...@apache.org
Subject cvs commit: jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session JvmRouteBinderValve.java JvmRouteSessionIDBinderLifecycleListener.java JvmRouteSessionIDBinderListener.java LocalStrings.properties SessionIDMessage.java mbeans-descriptors.xml
Date Wed, 01 Dec 2004 09:40:04 GMT
pero        2004/12/01 01:40:04

  Added:       modules/cluster/src/share/org/apache/catalina/cluster/session
                        JvmRouteBinderValve.java
                        JvmRouteSessionIDBinderLifecycleListener.java
                        JvmRouteSessionIDBinderListener.java
                        LocalStrings.properties SessionIDMessage.java
                        mbeans-descriptors.xml
  Log:
  JvmRouteBinderValve/JvmRouteSessionIDBinderListener to bind cluster session after primary
node failure at first calling backup node.
  This was an option to have session stickyness after cluster node crashed or longer maintance.
Work only with JESSIONID cookies.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/JvmRouteBinderValve.java
  
  Index: JvmRouteBinderValve.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.catalina.cluster.session;
  
  import java.io.IOException;
  
  import javax.servlet.ServletException;
  import javax.servlet.http.Cookie;
  import javax.servlet.http.HttpSession;
  
  import org.apache.catalina.Container;
  import org.apache.catalina.Context;
  import org.apache.catalina.Globals;
  import org.apache.catalina.Host;
  import org.apache.catalina.Lifecycle;
  import org.apache.catalina.LifecycleException;
  import org.apache.catalina.LifecycleListener;
  import org.apache.catalina.Manager;
  import org.apache.catalina.Session;
  import org.apache.catalina.cluster.CatalinaCluster;
  import org.apache.catalina.cluster.ClusterMessage;
  import org.apache.catalina.connector.Request;
  import org.apache.catalina.connector.Response;
  import org.apache.catalina.session.ManagerBase;
  import org.apache.catalina.util.LifecycleSupport;
  import org.apache.catalina.util.StringManager;
  import org.apache.catalina.valves.ValveBase;
  
  /**
   * Valve to handle Tomcat jvmRoute takeover using mod_jk module after node
   * failure. After a node crashed the next request going to other cluster node.
   * Now the answering from apache is slower ( make some error handshaking. Very
   * bad with apache at my windows.). We rewrite now the cookie jsessionid
   * information to the backup cluster node. After the next response all client
   * request goes direct to the backup node. The change sessionid send also to all
   * other cluster nodes. Well, now the session stickyness work directly to the
   * backup node and traffic don't go back too restarted cluster nodes!
   * 
   * At all cluster node you must configure the
   * {@link org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListener JvmRouteSessionIDBinderListener}
   * with
   * {@link org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListenerLifecycle JvmRouteSessionIDBinderListenerLifecycle}
   * 
   * 
   * Add this Valve to your clustered application or setup it to context default
   * conf/enginename/hostname/context.xml.default for all host application
   * 
   * <pre>
   * 
   *                    &lt;Context&gt;
   *                      &lt;Valve className=&quot;org.apache.catalina.cluster.session.JvmRouteBinderValve&quot;
/&gt;  
   *                    &lt;/Context&gt;
   *  
   * </pre>
   * 
   * @author Peter Rossbach
   * @version 1.0
   */
  public class JvmRouteBinderValve extends ValveBase implements Lifecycle {
  
      /*--Static Variables----------------------------------------*/
      public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
              .getLog(JvmRouteBinderValve.class);
  
      /**
       * The descriptive information about this implementation.
       */
      protected static final String info = "org.apache.catalina.session.JvmRouteBinderValve/1.0";
  
      /*--Instance Variables--------------------------------------*/
  
      /**
       * the cluster
       */
      protected CatalinaCluster cluster;
  
      /**
       * Session Manager for and app <code>manager</code>
       */
      protected Manager manager;
  
      /**
       * is manager a distrbuted
       */
      protected boolean managerCheck = false;
  
      /**
       * The string manager for this package.
       */
      protected StringManager sm = StringManager
              .getManager("org.apache.catalina.cluster.session");
  
      /**
       * Has this component been started yet?
       */
      protected boolean started = false;
  
      /**
       * enabled this component
       */
      protected boolean enabled = true;
  
      /**
       * number of session that no at this tomcat instanz hosted
       */
      protected long numberOfSessions = 0;
  
      protected String sessionIdAttribute = "JvmRouteOrignalSessionID";
  
      /**
       * The lifecycle event support for this component.
       */
      protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  
      /*--Logic---------------------------------------------------*/
  
      /**
       * Return descriptive information about this implementation.
       */
      public String getInfo() {
  
          return (info);
  
      }
  
      /**
       * set session id attribute to failed node for request.
       * 
       * @return Returns the sessionIdAttribute.
       */
      public String getSessionIdAttribute() {
          return sessionIdAttribute;
      }
  
      /**
       * get name of failed reqeust session attribute
       * 
       * @param sessionIdAttribute
       *            The sessionIdAttribute to set.
       */
      public void setSessionIdAttribute(String sessionIdAttribute) {
          this.sessionIdAttribute = sessionIdAttribute;
      }
  
      /**
       * @return Returns the numberOfSessions.
       */
      public long getNumberOfSessions() {
          return numberOfSessions;
      }
  
      /**
       * @return Returns the enabled.
       */
      public boolean getEnabled() {
          return enabled;
      }
  
      /**
       * @param enabled
       *            The enabled to set.
       */
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
  
      /**
       * Detect possible the JVMRoute change at cluster backup node..
       * 
       * @param request
       *            tomcat request being processed
       * @param response
       *            tomcat response being processed
       * @exception IOException
       *                if an input/output error has occurred
       * @exception ServletException
       *                if a servlet error has occurred
       */
      public void invoke(Request request, Response response) throws IOException,
              ServletException {
  
          // FIXME manager starts after valve!
          getManager();
          if (getEnabled() && manager != null) {
              handlePossibleTurnover(request, response);
          }
          // Pass this request on to the next valve in our pipeline
          getNext().invoke(request, response);
      }
  
      /**
       * handle possible session turn over.
       * 
       * @see JvmRouteBinderValve#handleJvmRoute(String, String, Request,
       *      Response)
       * @param request
       * @param response
       */
      protected void handlePossibleTurnover(Request request, Response response) {
          HttpSession session = request.getSession(false);
          if (session != null) {
              long t1 = System.currentTimeMillis();
              String jvmRoute = getLocalJvmRoute();
              if (jvmRoute == null) {
                  if (log.isWarnEnabled())
                      log.warn("No engine jvmRoute!");
                  return;
              }
              if (request.isRequestedSessionIdFromURL()) {
                  if (log.isInfoEnabled())
                      log.info("Skip reassign jvm route check, sessionid comes from URL!");
              } else {
                  handleJvmRoute(session.getId(), jvmRoute, request, response);
              }
              if (log.isInfoEnabled()) {
                  long t2 = System.currentTimeMillis();
                  long time = t2 - t1;
                  if (log.isInfoEnabled())
                      log.info("Turnover Check time " + time + "msec");
              }
          }
      }
  
      /**
       * get jvmroute from engine
       * 
       * @return
       */
      protected String getLocalJvmRoute() {
          return ((ManagerBase) manager).getJvmRoute();
      }
  
      /**
       * get Cluster DeltaManager
       * 
       * @return
       */
      protected Manager getManager() {
          if (!managerCheck) {
              managerCheck = true;
              if (container.getManager() instanceof DeltaManager) {
                  manager = container.getManager();
                  if (log.isDebugEnabled())
                      log.debug("Found Cluster DeltaManager "
                              + container.getManager() + " at "
                              + getContainer().getName());
              } else if (log.isDebugEnabled())
                  log.debug("No Cluster DeltaManager "
                          + container.getManager() + " at "
                          + getContainer().getName());
          }
          return manager;
      }
  
      /**
       * Handle jvmRoute stickyness after tomcat instance failed. After this
       * correction a new Cookie send to client with new jvmRoute and the
       * SessionID change propage to the other cluster nodes.
       * 
       * @param sessionId
       *            request SessionID from Cookie
       * @param localJvmRoute
       *            local jvmRoute
       * @param response
       *            Tomcat Response
       */
      protected void handleJvmRoute(String sessionId, String localJvmRoute,
              Request request, Response response) {
          // get requested jvmRoute.
          String requestJvmRoute = null;
          int index = sessionId.indexOf(".");
          if (index > 0) {
              requestJvmRoute = sessionId
                      .substring(index + 1, sessionId.length());
          }
          if (requestJvmRoute != null && !requestJvmRoute.equals(localJvmRoute)) {
              if (log.isDebugEnabled()) {
                  log.debug("We have detected a failover with differen jvmRoute."
                          + " old one: " + requestJvmRoute + " new one: "
                          + localJvmRoute + ". Will reset the session id.");
              }
              // OK - turnover the session ?
              String newSessionID = sessionId.substring(0, index) + "."
                      + localJvmRoute;
              Session catalinaSession = null;
              try {
                  catalinaSession = manager.findSession(sessionId);
              } catch (IOException e) {
                  // Hups!
              }
              if (catalinaSession != null) {
                  changeSessionID(sessionId, request, response, newSessionID,
                          catalinaSession);
                  numberOfSessions++;
              } else {
                  if (log.isDebugEnabled()) {
                      log.debug("Unable to find session= [" + sessionId + "]");
                  }
              }
          }
      }
  
      /**
       * change session id and send to all cluster nodes
       * 
       * @param sessionId
       *            original session id
       * @param request
       * @param response
       * @param newSessionID
       *            new session id for node migration
       * @param catalinaSession
       *            current session with original session id
       */
      protected void changeSessionID(String sessionId, Request request,
              Response response, String newSessionID, Session catalinaSession) {
          lifecycle.fireLifecycleEvent("Before session migration",
                  catalinaSession);
          request.setRequestedSessionId(newSessionID);
          catalinaSession.setId(newSessionID);
          if (catalinaSession instanceof DeltaSession)
              ((DeltaSession) catalinaSession).resetDeltaRequest();
          setNewSessionCookie(newSessionID, request, response);
          // set orginal sessionid at request, to allow application detect the
          // change
          if (sessionIdAttribute != null && !"".equals(sessionIdAttribute))
              request.setAttribute(sessionIdAttribute, sessionId);
          // now sending the change to all other clusternode!
          sendSessionIDClusterBackup(sessionId, newSessionID);
          lifecycle
                  .fireLifecycleEvent("After session migration", catalinaSession);
          if (log.isDebugEnabled()) {
              log
                      .debug("Changed catalina session to= ["
                              + newSessionID + "] old one= [" + sessionId + "]");
          }
      }
  
      /**
       * Send the changed Sessionid to all clusternodes.
       * 
       * @see JvmRouteSessionIDBinderListener#messageReceived(ClusterMessage)
       * @param sessionId
       *            current failed sessionid
       * @param newSessionID
       *            new session id, bind to the new cluster node
       */
      protected void sendSessionIDClusterBackup(String sessionId,
              String newSessionID) {
          SessionIDMessage msg = new SessionIDMessage();
          msg.setOrignalSessionID(sessionId);
          msg.setBackupSessionID(newSessionID);
          Context context = (Context) getContainer();
          msg.setContextPath(context.getPath());
          cluster.send(msg);
      }
  
      /**
       * Sets a new cookie for the given session id and response and see
       * {@link org.apache.catalina.connector.Request#configureSessionCookie(javax.servlet.http.Cookie)
       * 
       * @param sessionId
       *            The session id
       * @param response
       *            Tomcat Response
       */
  
      protected void setNewSessionCookie(String sessionId, Request request,
              Response response) {
          if (response != null) {
              Context context = (Context) getContainer();
              if (context.getCookies()) {
                  // set a new session cookie
                  Cookie newCookie = new Cookie(Globals.SESSION_COOKIE_NAME,
                          sessionId);
                  newCookie.setMaxAge(-1);
                  String contextPath = null;
                  if (!response.getConnector().getEmptySessionPath()
                          && (context != null)) {
                      contextPath = context.getEncodedPath();
                  }
                  if ((contextPath != null) && (contextPath.length() > 0)) {
                      newCookie.setPath(contextPath);
                  } else {
                      newCookie.setPath("/");
                  }
                  if (request.isSecure()) {
                      newCookie.setSecure(true);
                  }
                  if (log.isDebugEnabled()) {
                      log.debug("Setting cookie with session id:" + sessionId
                              + " & name: " + Globals.SESSION_COOKIE_NAME
                              + " & path: " + newCookie.getPath() + " & secure: "
                              + newCookie.getSecure());
                  }
                  response.addCookie(newCookie);
              }
          }
      }
  
      // ------------------------------------------------------ Lifecycle Methods
  
      /**
       * Add a lifecycle event listener to this component.
       * 
       * @param listener
       *            The listener to add
       */
      public void addLifecycleListener(LifecycleListener listener) {
  
          lifecycle.addLifecycleListener(listener);
  
      }
  
      /**
       * Get the lifecycle listeners associated with this lifecycle. If this
       * Lifecycle has no listeners registered, a zero-length array is returned.
       */
      public LifecycleListener[] findLifecycleListeners() {
  
          return lifecycle.findLifecycleListeners();
  
      }
  
      /**
       * Remove a lifecycle event listener from this component.
       * 
       * @param listener
       *            The listener to add
       */
      public void removeLifecycleListener(LifecycleListener listener) {
  
          lifecycle.removeLifecycleListener(listener);
  
      }
  
      /**
       * Prepare for the beginning of active use of the public methods of this
       * component. This method should be called after <code>configure()</code>,
       * and before any of the public methods of the component are utilized.
       * 
       * @exception LifecycleException
       *                if this component detects a fatal error that prevents this
       *                component from being used
       */
      public void start() throws LifecycleException {
  
          // Validate and update our current component state
          if (started)
              throw new LifecycleException(sm
                      .getString("jvmRoute.valve.alreadyStarted"));
          lifecycle.fireLifecycleEvent(START_EVENT, null);
          started = true;
          Container container = getContainer().getParent();
          if (container instanceof Host
                  && ((Host) container).getCluster() != null)
              cluster = (CatalinaCluster) ((Host) container).getCluster();
          if (cluster == null) {
              throw new RuntimeException(
                      "No clustering support at container "
                              + container.getName());
          }
  
          if (log.isInfoEnabled())
              log.info("JvmRouteBinderValve started");
  
      }
  
      /**
       * Gracefully terminate the active use of the public methods of this
       * component. This method should be the last one called on a given instance
       * of this component.
       * 
       * @exception LifecycleException
       *                if this component detects a fatal error that needs to be
       *                reported
       */
      public void stop() throws LifecycleException {
  
          // Validate and update our current component state
          if (!started)
              throw new LifecycleException(sm
                      .getString("jvmRoute.valve.notStarted"));
          lifecycle.fireLifecycleEvent(STOP_EVENT, null);
          started = false;
  
          cluster = null;
          manager = null;
          managerCheck = false;
  
          numberOfSessions = 0;
          if (log.isInfoEnabled())
              log.info("JvmRouteBinderValve stopped)");
  
      }
  
  }
  
  
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderLifecycleListener.java
  
  Index: JvmRouteSessionIDBinderLifecycleListener.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.catalina.cluster.session;
  
  import javax.management.MBeanServer;
  import javax.management.MBeanServerFactory;
  import javax.management.ObjectName;
  import javax.management.modelmbean.ModelMBean;
  
  import org.apache.catalina.Lifecycle;
  import org.apache.catalina.LifecycleEvent;
  import org.apache.catalina.LifecycleListener;
  import org.apache.catalina.cluster.CatalinaCluster;
  import org.apache.catalina.cluster.MessageListener;
  import org.apache.catalina.core.StandardHost;
  import org.apache.catalina.util.StringManager;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.commons.modeler.ManagedBean;
  import org.apache.commons.modeler.Registry;
  
  /**
   * Register new JvmRouteSessionIDBinderListener to receive Session ID changes.
   * 
   * add following at your server.xml Host section
   * 
   * <pre>
   *     &lt;Host &gt;... 
   *       &lt;Listener className=&quot;org.apache.catalina.cluster.session.JvmRouteSessionIDBinderLifecycleListener&quot;
/&gt;
   *       &lt;Cluster ...&gt;
   *     &lt;/Host&gt;
   * </pre>
   * 
   * @author Peter Rossbach
   */
  public class JvmRouteSessionIDBinderLifecycleListener implements
          LifecycleListener {
      private static Log log = LogFactory
              .getLog(JvmRouteSessionIDBinderLifecycleListener.class);
  
      /**
       * The descriptive information string for this implementation.
       */
      private static final String info = "org.apache.catalina.cluster.session.JvmRouteSessionIDBinderLifecycleListener/1.0";
  
      /**
       * The string resources for this package.
       */
      protected static final StringManager sm = StringManager
              .getManager("org.apache.catalina.cluster.session");
  
      private boolean enabled = true;
  
      private MBeanServer mserver = null;
  
      private Registry registry = null;
  
      private MessageListener sessionMoverListener;
  
      /* start and stop cluster 
       * @see org.apache.catalina.LifecycleListener#lifecycleEvent(org.apache.catalina.LifecycleEvent)
       */
      public void lifecycleEvent(LifecycleEvent event) {
  
          if (enabled && event.getSource() instanceof StandardHost) {
  
              if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
                  if (log.isDebugEnabled())
                      log.debug("SessionID Binder Listener started");
                  startSessionIDListener((StandardHost) event.getSource());
              } else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
                  if (log.isDebugEnabled())
                      log.debug("SessionID Binder Listener stopped");
                  stopSessionIDListener((StandardHost) event.getSource());
              }
          }
      }
  
      /**
       * start sessionID mover at cluster
       * @param host clustered host
       */
      protected void stopSessionIDListener(StandardHost host) {
          if (sessionMoverListener != null) {
              CatalinaCluster cluster = (CatalinaCluster) host.getCluster();
              cluster.removeClusterListener(sessionMoverListener);
          }
      }
  
      /**
       * start sessionID mover at cluster
       * @param host clustered host
       */
      protected void startSessionIDListener(StandardHost host) {
          try {
              ObjectName objectName = null;
              getMBeanServer();
              objectName = new ObjectName(host.getDomain()
                      + ":type=Listener,name=JvmRouteSessionIDBinderListener");
  
              if (mserver.isRegistered(objectName)) {
                  log.info(sm.getString("jvmRoute.run.already"));
                  return;
              }
              sessionMoverListener = new JvmRouteSessionIDBinderListener();
              mserver.registerMBean(getManagedBean(sessionMoverListener), objectName);
              CatalinaCluster cluster = (CatalinaCluster) host.getCluster();
              sessionMoverListener.setCluster(cluster);
              ((JvmRouteSessionIDBinderListener) sessionMoverListener).start();
          } catch (Exception ex) {
              log.error(ex.getMessage(), ex);
          }
      }
  
      protected MBeanServer getMBeanServer() throws Exception {
          if (mserver == null) {
              if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
                  mserver = (MBeanServer) MBeanServerFactory
                          .findMBeanServer(null).get(0);
              } else {
                  mserver = MBeanServerFactory.createMBeanServer();
              }
              registry = Registry.getRegistry(null, null);
              registry.loadMetadata(this.getClass().getResourceAsStream(
                      "mbeans-descriptors.xml"));
          }
          return (mserver);
      }
  
      /**
       * Returns the ModelMBean
       * 
       * @param object
       *            The Object to get the ModelMBean for
       * @return The ModelMBean
       * @throws Exception
       *             If an error occurs this constructors throws this exception
       */
      public ModelMBean getManagedBean(Object object) throws Exception {
          ManagedBean managedBean = registry.findManagedBean(object.getClass()
                  .getName());
          ModelMBean mbean = managedBean.createMBean(object);
          return mbean;
      }
  
      /**
       * @return Returns the enabled.
       */
      public boolean isEnabled() {
          return enabled;
      }
  
      /**
       * @param enabled
       *            The enabled to set.
       */
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
  
      /**
       * Return descriptive information about this Listener implementation and the
       * corresponding version number, in the format
       * <code>&lt;description&gt;/&lt;version&gt;</code>.
       */
      public String getInfo() {
  
          return (info);
  
      }
  }
  
  
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderListener.java
  
  Index: JvmRouteSessionIDBinderListener.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.catalina.cluster.session;
  
  import java.io.IOException;
  
  import org.apache.catalina.Container;
  import org.apache.catalina.Context;
  import org.apache.catalina.LifecycleException;
  import org.apache.catalina.Session;
  import org.apache.catalina.cluster.CatalinaCluster;
  import org.apache.catalina.cluster.ClusterMessage;
  import org.apache.catalina.cluster.MessageListener;
  import org.apache.catalina.core.StandardEngine;
  import org.apache.catalina.util.StringManager;
  
  /**
   * Receive SessionID cluster change from other backup node after primary session node is
failed.
   * 
   * @author Peter Rossbach
   * @version 1.0
   */
  public class JvmRouteSessionIDBinderListener implements MessageListener {
      /*--Static Variables----------------------------------------*/
      public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
              .getLog(JvmRouteSessionIDBinderListener.class);
  
      /**
       * The descriptive information about this implementation.
       */
      protected static final String info = "org.apache.catalina.session.JvmRouteSessionIDBinderListener/1.0";
  
      /*--Instance Variables--------------------------------------*/
  
      /**
       * The string manager for this package.
       */
      private StringManager sm = StringManager
              .getManager("org.apache.catalina.cluster.session");
  
      protected CatalinaCluster cluster = null;
  
      protected boolean started = false;
  
      /**
       * number of session that goes to this cluster node
       */
      private long numberOfSessions = 0;
  
      /*--Constructor---------------------------------------------*/
      
      public JvmRouteSessionIDBinderListener() {
      }
  
      /*--Logic---------------------------------------------------*/
      
      /**
       * Return descriptive information about this implementation.
       */
      public String getInfo() {
  
          return (info);
  
      }
  
      /**
       * @return Returns the numberOfSessions.
       */
      public long getNumberOfSessions() {
          return numberOfSessions;
      }
  
      /**
       * Add this Mover as Cluster Listener ( receiver)
       * @throws LifecycleException
       */
      public void start() throws LifecycleException {
          if (started)
              return;
          getCluster().addClusterListener(this);
          started = true;
          if (log.isInfoEnabled())
              log.info("Cluster JvmRouteSessionIDBinderListener started.");
      }
  
      /**
       * Remove this from Cluster Listener
       * @throws LifecycleException
       */
      public void stop() throws LifecycleException {
          started = false;
          getCluster().removeClusterListener(this);
          if (log.isInfoEnabled())
              log.info("Cluster JvmRouteSessionIDBinderListener stopped.");
      }
  
      /**
       * Callback from the cluster, when a message is received, The cluster will
       * broadcast it invoking the messageReceived on the receiver.
       * 
       * @param msg
       *            ClusterMessage - the message received from the cluster
       */
      public void messageReceived(ClusterMessage msg) {
          if (msg instanceof SessionIDMessage && msg != null) {
              SessionIDMessage sessionmsg = (SessionIDMessage) msg;
              if (log.isDebugEnabled())
                  log
                          .debug("Cluster JvmRouteSessionIDBinderListener received session
ID "
                                  + sessionmsg.getOrignalSessionID()
                                  + " set to "
                                  + sessionmsg.getBackupSessionID()
                                  + " for context path"
                                  + sessionmsg.getContextPath());
              Container host = getCluster().getContainer();
              if (host != null) {
                  Context context = (Context) host.findChild(sessionmsg
                          .getContextPath());
                  if (context != null) {
                      try {
                          Session session = context.getManager().findSession(
                                  sessionmsg.getOrignalSessionID());
                          if (session != null) {
                              session.setId(sessionmsg.getBackupSessionID());
                          } else if (log.isInfoEnabled())
                              log.info("Lost Session "
                                      + sessionmsg.getOrignalSessionID());
                      } catch (IOException e) {
                          log.error(e);
                      }
  
                  } else if (log.isErrorEnabled())
                      log.error("Context " + sessionmsg.getContextPath()
                              + "not found at "
                              + ((StandardEngine) host.getParent()).getJvmRoute()
                              + "!");
              } else if (log.isErrorEnabled())
                  log.error("No host found " + sessionmsg.getContextPath());
          }
      }
  
      /**
       * Accept only SessionIDMessages
  	 * 
       * @param msg
       *            ClusterMessage
       * @return boolean - returns true to indicate that messageReceived should be
       *         invoked. If false is returned, the messageReceived method will
       *         not be invoked.
       */
      public boolean accept(ClusterMessage msg) {
          return (msg instanceof SessionIDMessage);
      }
  
      /*--Instance Getters/Setters--------------------------------*/
      public CatalinaCluster getCluster() {
          return cluster;
      }
  
      public void setCluster(CatalinaCluster cluster) {
          this.cluster = cluster;
      }
  
      public boolean equals(Object listener) {
          return super.equals(listener);
      }
  
      public int hashCode() {
          return super.hashCode();
      }
  
  }
  
  
  
  
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  jvmRoute.valve.alreadyStarted=jvmRoute backup sessionID correction is started
  jvmRoute.valve.notStarted=jvmRoute backup sessionID correction run already
  jvmRoute.run.already=jvmRoute SessionID receiver run already
  
  
  
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/SessionIDMessage.java
  
  Index: SessionIDMessage.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.catalina.cluster.session;
  
  import org.apache.catalina.cluster.ClusterMessage;
  
  /**
   * Session id change cluster message
   * 
   * @author Peter Roßbach
   * 
   */
  public class SessionIDMessage implements ClusterMessage {
  
  	private org.apache.catalina.cluster.Member address;
  
  	private int messageNumber;
  
  	private long timestamp;
  
  	private String orignalSessionID;
  
  	private String backupSessionID;
  
  	private String contextPath;
  
  	public org.apache.catalina.cluster.Member getAddress() {
  		return address;
  	}
  
  	public void setAddress(org.apache.catalina.cluster.Member address) {
  		this.address = address;
  	}
  
  	public String getUniqueId() {
  		StringBuffer result = new StringBuffer(getOrignalSessionID());
  		result.append("#-#");
  		result.append(getBackupSessionID());
  		result.append("#-#");
  		result.append(getMessageNumber());
  		result.append("#-#");
  		result.append(System.currentTimeMillis());
  		return result.toString();
  	}
  
  	/**
  	 * @return Returns the contextPath.
  	 */
  	public String getContextPath() {
  		return contextPath;
  	}
  	/**
  	 * @param contextPath The contextPath to set.
  	 */
  	public void setContextPath(String contextPath) {
  		this.contextPath = contextPath;
  	}
  	/**
  	 * @return Returns the messageNumber.
  	 */
  	public int getMessageNumber() {
  		return messageNumber;
  	}
  
  	/**
  	 * @param messageNumber
  	 *            The messageNumber to set.
  	 */
  	public void setMessageNumber(int messageNumber) {
  		this.messageNumber = messageNumber;
  	}
  
  	/**
  	 * @return Returns the timestamp.
  	 */
  	public long getTimestamp() {
  		return timestamp;
  	}
  
  	/**
  	 * @param timestamp
  	 *            The timestamp to set.
  	 */
  	public void setTimestamp(long timestamp) {
  		this.timestamp = timestamp;
  	}
  
  	/**
  	 * @return Returns the backupSessionID.
  	 */
  	public String getBackupSessionID() {
  		return backupSessionID;
  	}
  
  	/**
  	 * @param backupSessionID
  	 *            The backupSessionID to set.
  	 */
  	public void setBackupSessionID(String backupSessionID) {
  		this.backupSessionID = backupSessionID;
  	}
  
  	/**
  	 * @return Returns the orignalSessionID.
  	 */
  	public String getOrignalSessionID() {
  		return orignalSessionID;
  	}
  
  	/**
  	 * @param orignalSessionID
  	 *            The orignalSessionID to set.
  	 */
  	public void setOrignalSessionID(String orignalSessionID) {
  		this.orignalSessionID = orignalSessionID;
  	}
  }
  
  
  1.1                  jakarta-tomcat-catalina/modules/cluster/src/share/org/apache/catalina/cluster/session/mbeans-descriptors.xml
  
  Index: mbeans-descriptors.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE mbeans-descriptors PUBLIC
     "-//Apache Software Foundation//DTD Model MBeans Configuration File"
     "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">
  <mbeans-descriptors>
      <mbean name="ClusterJvmRouteMoverValve" description="mod_jk jvmRoute jsessionid cookie
backup correction" domain="Catalina"
          group="Valve" type="org.apache.catalina.cluster.session.JvmRouteBinderValve">
          <attribute name="info" 
  		           description="describe version" type="java.lang.String" writeable="false"/>
          <attribute name="enabled" 
  		           description="enable a jvm Route check" type="boolean"/>
          <attribute name="numberOfSessions"
  		           description="number of jvmRoute session corrections" type="long" writeable="false"/>
          <attribute name="sessionIdAttribute" 
  		    description="Name of attribute with sessionid value before turnover a session" 
  		    type="java.lang.String" 
  		    />
          <operation name="start" description="Stops the ClusterJvmRouteMoverValve" 
  		           impact="ACTION" returnType="void"/>
          <operation name="stop" description="Stops the ClusterJvmRouteMoverValve" 
  		           impact="ACTION" returnType="void"/>
      </mbean>
  	<mbean name="ClusterSessionIDMoverListener"
  		description="Monitors the jvmRoute activity"
  		domain="Catalina"
          group="Listener"
  		type="org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListener">
          <attribute name="info" 
  		           description="describe version" type="java.lang.String" writeable="false"/>
          <attribute name="numberOfSessions" 
  		    description="number of jvmRoute session corrections" 
  		    type="long" 
  		    writeable="false"/>
      </mbean>
  
  </mbeans-descriptors>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Mime
View raw message