The Mingleton Pattern

I recently found myself in need of singleton, you know, a single instance of an object shared across the JVM? But I needed to maintain multiple instances of this singleton, each having a different meaning to my application (but instances of the same Java class). The problem I was trying to solve is to have a Managed Bean (MBean in JMX terms) for a class of objects, the instances of which I’m not particularly interested in managing, since they are potentially transient. I wanted to manage this group of “things” using a single instance of the Delegate MBean per class of “thing” to be managed.

I needed a Multiple Singleton, which I call a Mingleton. Multiple instances of a class, whose instances represent an entire class of “things” themselves. I knew things were about to get wild.

The immediate application at hand was to manage a bunch of “things” using only their “class” (not necessarily their Java Class, but something distinct about the purpose of the “thing” which could include their Java Class, but not restricted to it). I created a sort of “stand-in” object that I called an MBeanDelegate that contained information (such as the “thing”s Log4J Logger singleton) that is common (at the meta-level anyways) across all “things.” I only wanted one of these MBeanDelegates per “thing” so that I can control every instance of each type of “thing” by touching only one MBeanDelegate per “thing” class I wanted to manage. Got it?

So, I had to monkey around with the Singleton pattern a little bit to make this happen, resulting in my Mingleton (cue “Evil Frankenstein Laugh”).

The usual “getInstance” method of the Singleton I modified to take context information (in this case, the Java Class object, but it could have been anything that makes the class of “thing” unique). My Mingleton then checks a Map it maintains of Singletons corresponding to the context information (again, the Java Class object of the “thing” for which I want my Mingleton to manage a Singleton). If it’s there, great, return it. If not, create one and stick it in the Map. By the way, the getInstance() method is synchronized to avoid any nastiness.

The code below uses a class from a chapter I wrote for the O’Reilly book, “Java Enterprise Best Practices” called “JMX Best Practices” where I lay out a pattern for making the DynamicMBean interface easier to use. The class is called DynamicMBeanFacade, and comes with, among other goodies, a ready-to-use DynamicMBean interface implementation. Here’s a link to the book on amazon.com. I know you’re gonna want to
pick up a copy
, right? 😉

Here’s the code:

package com.jstevenperry.management;

import java.util.HashMap;

import javax.management.MBeanServer;
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.MalformedObjectNameException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.NotCompliantMBeanException;

// From sample code for “Java Enterprise Best Practices” Chapter 7,
// “JMX Best Practices”.
import jmxbp.common.DynamicMBeanFacade;

import org.apache.log4j.Logger;
import org.apache.log4j.Level;

public class MBeanDelegate extends DynamicMBeanFacade {
private Logger _logger;
public Logger getLogger() { return _logger; }

/**
* Creates a new instance of MBeanDelegate.
*/
private MBeanDelegate() {
//
// In this example code, the registration of, and management
/// interface creation for this MBean is relegated to the agent.
/// However, make sure that the “setLogLevel” operation is exposed
/// at the very least.
this.addOperation(“setLogFilteringLevel”, “Sets the Log Level for this MBeans logger. Valid values are: ALL, DEBUG, INFO, WARN, ERROR, FATAL”);
}

private static HashMap _mbeans = new HashMap();

public static synchronized MBeanDelegate getMBeanDelegate(Class linkedClass) throws ServiceException {
MBeanDelegate mbean = (MBeanDelegate)_mbeans.get(linkedClass);
if (mbean == null) {
mbean = new MBeanDelegate();
mbean._logger = Logger.getLogger(linkedClass);
_mbeans.put(linkedClass, mbean);
}
return mbean;
}

public synchronized void setLogLevel(String level) {
// Default to current level
Level newLevel = _logger.getLevel();
if (level.equals(“OFF”)) {
newLevel = Level.OFF;
} else if (level.equals(“FATAL”)) {
newLevel = Level.FATAL;
} else if (level.equals(“ERROR”)) {
newLevel = Level.ERROR;
} else if (level.equals(“WARN”)) {
newLevel = Level.WARN;
} else if (level.equals(“INFO”)) {
newLevel = Level.INFO;
} else if (level.equals(“DEBUG”)) {
newLevel = Level.DEBUG;
} else if (level.equals(“ALL”)) {
newLevel = Level.ALL;
}
}
}

This is a fairly simple example, but illustrative of how you can use JMX to manage objects at runtime. I don’t know about you, but I get really tired of having to modify log4j.xml and redeploy my application each time I want to change the Log level of one of my appenders. Using this approach, you can change them at runtime.

If this is helpful to you, let me know.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: