Singleton MBean for Clustering
monocongo Jul 23, 2004 1:31 PMI 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