1 Reply Latest reply on Jul 29, 2004 5:12 PM by James Adams

    Singleton MBean for Clustering

    James Adams Novice

      I am currently trying the approach to Singleton MBeans for clustering suggested in the JBoss Clustering article by Ivelin Ivanov at http://www.onjava.com/pub/a/onjava/2003/08/20/jboss_clustering.html, however there is not enough information in the article -- and I am still working on this approach. I have modified a singleton class to be a singleton MBean as described but as yet I am having trouble with the JBoss not being able to start the service, with complaints of a nested throwable and an method not being available in the singleton class:

      12:38:51,141 ERROR [URLDeploymentScanner] Incomplete Deployment listing:
      Incompletely deployed packages:
      org.jboss.deployment.DeploymentInfo@7d7cded7 { url=file:/C:/jboss-3.2.5/server/all/farm/cluster-examples-service.xml }
       deployer: org.jboss.deployment.SARDeployer@10a2d64
       status: Deployment FAILED reason: create operation failed for package file:/C:/jboss-3.2.5/server/all/farm/cluster-examples-service.xml; - nested throwable: (org.jboss.deployment.DeploymentException: com.harborsideplus.grover.mbean.AllUserMessagesSingleton.<init>(); - nested throwable: (java.lang.NoSuchMethodException: com.harborsideplus.grover.mbean.AllUserMessagesSingleton.<init>()))
       state: FAILED
       watch: file:/C:/jboss-3.2.5/server/all/farm/cluster-examples-service.xml
      



      I have modified the singleton to be a MBean as described in the article, the MBean and interfaces are listed below:


      // ---------- All UserMessagesSingletonMBean interface ----------------
      package com.harborsideplus.grover.mbean;
      
      import com.harborsideplus.grover.util.UserMessages;
      
      /**
       * @author James Adams
       *
       */
      public interface AllUserMessagesSingletonMBean
      {
       //================================================================================
       // managed MBean operations, which control the lifecycle of the singleton service
       //================================================================================
       public void startSingleton ();
       public void stopSingleton ();
      
      
       //================================================================================
       // exposed methods
       //================================================================================
      
       /**
       *
       * @return
       */
       public boolean isMasterNode ();
      
      
       /**
       * Get the user's messages beginning at the specified index.
       *
       * @param userId
       * @param index
       * @return
       */
       public UserMessages getUserMessages (String userId,
       int index);
      
      
       /**
       * Add a message for the specified user. If the specified user doesn't already
       * have a UserMessages list then one will be initialized before adding the message.
       *
       * @param userId
       * @param message
       */
       public void addMessage (String userId,
       String message);
      
      
       /**
       * Get the number of messages for the specified user.
       * @param userId
       * @return
       */
       public int getNumberOfUserMessages (String userId);
      
      }
      
      
      
      //----------- AllUserMessagesSingleton class ---------------------
      
      package com.harborsideplus.grover.mbean;
      
      import java.util.ArrayList;
      import java.util.Enumeration;
      import java.util.Hashtable;
      
      import com.harborsideplus.grover.util.UserMessages;
      
      /**
       * @author James Adams
       *
       */
      public class AllUserMessagesSingleton
       implements AllUserMessagesSingletonMBean
      {
       // reference to the singleton
       private static AllUserMessagesSingleton m_reference;
      
       // hashtable of UserMessages
       private Hashtable m_userMessagesTable;
      
       // flag showing whether or not running on master node
       private boolean m_isMasterNode;
      
      
       //================================================================================
       // managed MBean operations, which control the lifecycle of the singleton service
       //================================================================================
      
       /**
       *
       */
       public void startSingleton ()
       {
       m_isMasterNode = true;
       }
      
       /**
       *
       */
       public void stopSingleton ()
       {
       m_isMasterNode = false;
       }
      
      
       //=============================================================
       // Singleton-related methods
       //=============================================================
      
       /**
       * Constructor method which is private to insure that the class can't be instantiated.
       * A reference to an object of the class must be obtained via the getIOIMessagesBean() method.
       *
       */
       private AllUserMessagesSingleton ()
       {
       // initialize the ArrayList
       m_userMessagesTable = new Hashtable();
       }
      
      
       /**
       * Method used to obtain a reference to the object.
       *
       * @return reference to the singleton object
       */
       public static synchronized AllUserMessagesSingleton getReference ()
       {
       // if the reference hasn't already been created then instantiate an object
       if (m_reference == null)
       {
       // call the constructor
       m_reference = new AllUserMessagesSingleton();
       }
      
       // return our reference
       return m_reference;
       }
      
      
       /**
       * Method provided in order to prevent cloning of the object. The method always throws an
       * exception to indicate that cloning is not supported by this class.
       *
       * @return never returns anything
       * @throws CloneNotSupportedException to inicate that cloning is not supported by this class
       */
       public Object clone ()
       throws CloneNotSupportedException
       {
       // do not allow cloning - throw an exception
       throw new CloneNotSupportedException();
       }
      
      
       //======================================================================
       // Public methods
       //======================================================================
      
       /**
       *
       */
       public boolean isMasterNode ()
       {
       return m_isMasterNode;
       }
      
      
       /**
       * Get the UserMessages for the specified user.
       *
       * @param userId
       * @return
       */
       /*
       public UserMessages getUserMessages (String userId)
       {
       // handle null keys
       if (userId == null)
       {
       return null;
       }
      
       // return the corresponding UserMessages, or null if it doesn't exist
       return (UserMessages) m_userMessagesTable.get(userId);
       }
       */
      
       /**
       * Get the UserMessages for the specified user, from the specified index to the end.
       *
       * @param userId
       * @param index
       * @return
       */
       public UserMessages getUserMessages (String userId,
       int index)
       {
       // handle bad parameters
       if ((userId == null) || (index < 0))
       {
       return null;
       }
      
       // get the UserMessages for the specified user
       UserMessages userMessages = (UserMessages) m_userMessagesTable.get(userId);
      
       if (userMessages != null)
       {
       // if the index is past the range then return null
       if (index > userMessages.getLastIndex())
       {
       return null;
       }
       // if the index is zero then we want the entire thing -- no need to get a subset
       else if (index == 0)
       {
       return userMessages;
       }
       // return a subset of the original messages
       else
       {
       // index is within range - copy the messages from the index
       // to the end into a new UserMessages object and return it
      
       // create the new UserMessages we'll return
       UserMessages newUserMessages = new UserMessages(userId);
      
       // loop over the original messages, copying them into the new messages object
       for (int i = index; i <= userMessages.getLastIndex(); i++)
       {
       newUserMessages.addMessage(userMessages.getMessage(i));
       }
      
       // return the messages
       return newUserMessages;
       }
       }
       else
       {
       // no messages were found for the specified user
       return null;
       }
       }
      
      
       /**
       * Add a message for the specified user. If the specified user doesn't already
       * have a UserMessages list then one will be initialized before adding the message.
       *
       * @param userId
       * @param message
       */
       public void addMessage (String userId,
       String message)
       {
       // either add to an existing list or create one first before adding to it
       if (m_userMessagesTable.containsKey(userId))
       {
       // get the existing UserMessages for this user
       UserMessages userMessages = (UserMessages) m_userMessagesTable.get(userId);
      
       // add the message to the list
       userMessages.addMessage(message);
       }
       else
       {
       // create a UserMessages for this user
       UserMessages userMessages = new UserMessages(userId);
      
       // add the message to the list
       userMessages.addMessage(message);
      
       // add the user messages list to the hash
       m_userMessagesTable.put(userId, userMessages);
       }
       }
      
      
       /**
       * Get the number of messages for the specified user.
       * @param userId
       * @return
       */
       public int getNumberOfUserMessages (String userId)
       {
       if (m_userMessagesTable.containsKey(userId))
       {
       return ((UserMessages) m_userMessagesTable.get(userId)).size();
       }
       else
       {
       return 0;
       }
       }
      
      }
      
      
      




      The MBean classes are being included with my application's EJB Jar file which is part of the EAR file which is deployed in the JBOSS_HOME/server/all/deploy directory.

      I have modified JBOSS_HOME/server/all/farm/cluster-examples-service.xml by adding the following entry:


      <!-- ===================================================== -->
       <!-- This MBean is an example of a cluster Singleton -->
       <!-- ===================================================== -->
       <mbean code="com.harborsideplus.grover.mbean.AllUserMessagesSingleton"
       name="grover.mbean:service=AllUserMessagesSingleton">
       </mbean>
      
       <!-- ===================================================== -->
       <!-- | This is a singleton controller which works similarly to the -->
       <!-- | SchedulerProvider (when a MBean target is used) -->
       <!-- ===================================================== -->
       <mbean code="org.jboss.ha.singleton.HASingletonController"
       name="jboss:service=HASingletonController">
       <depends>jboss:service=DefaultPartition</depends>
       <depends>grover.mbean:service=AllUserMessagesSingleton</depends>
       <attribute name="TargetName">grover.mbean:service=AllUserMessagesSingleton</attribute>
       <attribute name="TargetStartMethod">startSingleton</attribute>
       <attribute name="TargetStopMethod">stopSingleton</attribute>
       </mbean>
      




      Any suggestions as to what I am doing wrong ? Thanks in advance for any ideas, feedback, etc.


      -James

        • 1. Re: Singleton MBean for Clustering
          James Adams Novice

          I am now putting the singleton MBean class and interface in the same
          SAR as another MBean I have for my application, instead of in the EAR as
          before. The entry for the singleton and controller are now in
          JBOSS/server/all/deploy/cluster-service.xml.

          When I start JBoss I now get a DeploymentException (nested throwable -
          see below). The output below is from JBoss 4.0, and I get similar
          behavior using 3.2.5.

          Does anyone recognize this ? Any ideas at all ? Thanks in advance...


          ERROR [MainDeployer] could not create deployment: file:/C:/jboss-4.0.0DR4/server/all/deploy/1000grover-mbeans.sar

          org.jboss.deployment.DeploymentException: - nested throwable: (java.lang.reflect.UndeclaredThrowableException)
          at org.jboss.system.ServiceConfigurator.install(ServiceConfigurator.java:139)
          at org.jboss.system.ServiceController.install(ServiceController.java:200)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:324)
          at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:141)
          at org.jboss.mx.server.Invocation.dispatch(Invocation.java:80)
          at org.jboss.mx.server.Invocation.invoke(Invocation.java:72)