Index: core/src/main/java/org/quickfixj/jmx/JmxExporter.java =================================================================== --- core/src/main/java/org/quickfixj/jmx/JmxExporter.java (revision 899) +++ core/src/main/java/org/quickfixj/jmx/JmxExporter.java (working copy) @@ -17,30 +17,73 @@ package org.quickfixj.jmx; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; +import javax.management.ObjectName; import org.quickfixj.jmx.mbean.connector.ConnectorJmxExporter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import quickfix.Connector; import quickfix.mina.SessionConnector; public class JmxExporter { + /** + * Constant indicating that registration should fail when + * attempting to register an MBean under a name that already exists. + *
This is the default registration behaviour. + */ + public static final int REGISTRATION_FAIL_ON_EXISTING = 0; + /** + * Constant indicating that registration should ignore the affected MBean + * when attempting to register an MBean under a name that already exists. + */ + public static final int REGISTRATION_IGNORE_EXISTING = 1; + /** + * Constant indicating that registration should replace the affected MBean + * when attempting to register an MBean under a name that already exists. + */ + public static final int REGISTRATION_REPLACE_EXISTING = 2; + + private int registrationBehaviour; + + private final Logger log = LoggerFactory.getLogger(getClass()); + private final MBeanServer mbeanServer; private ConnectorJmxExporter connectorExporter = new ConnectorJmxExporter(); - public JmxExporter(MBeanServer mbeanServer) { + public JmxExporter(MBeanServer mbeanServer, int registrationBehaviour) { this.mbeanServer = mbeanServer; + this.registrationBehaviour = registrationBehaviour; } + public JmxExporter(MBeanServer mbeanServer) { + this(mbeanServer, REGISTRATION_FAIL_ON_EXISTING); + } + public JmxExporter() throws JMException { - this.mbeanServer = createMBeanServer(); + this(createMBeanServer()); } - private MBeanServer createMBeanServer() throws JMException { + /** + * Specify what action should be taken when attempting to register an MBean + * under an {@link javax.management.ObjectName} that already exists. + *
Default is REGISTRATION_FAIL_ON_EXISTING.
+ * @see #REGISTRATION_FAIL_ON_EXISTING
+ * @see #REGISTRATION_IGNORE_EXISTING
+ * @see #REGISTRATION_REPLACE_EXISTING
+ */
+ public void setRegistrationBehavior(int registrationBehaviour) {
+ this.registrationBehaviour = registrationBehaviour;
+ }
+
+ private static MBeanServer createMBeanServer() throws JMException {
try {
Class> factoryClass = Class.forName("java.lang.management.ManagementFactory");
try {
@@ -57,10 +100,48 @@
}
public void export(Connector connector) {
- connectorExporter.export(mbeanServer, (SessionConnector)connector);
+ connectorExporter.export(this, (SessionConnector)connector);
}
public MBeanServer getMBeanServer() {
return mbeanServer;
}
+
+ /**
+ * Actually register the MBean with the server. The behaviour when encountering
+ * an existing MBean can be configured using the registrationBehaviour constructor or {@link #setRegistrationBehavior(int)}.
+ * This design (and also code) was unashamedly cribbed from Spring's
+ * MBeanRegistrationSupport
+ * class. Thanks Spring team!
+ * @see #REGISTRATION_FAIL_ON_EXISTING
+ * @see #REGISTRATION_IGNORE_EXISTING
+ * @see #REGISTRATION_REPLACE_EXISTING
+ * @param mbean
+ * @param objectName
+ * @throws JMException
+ */
+ public void registerMBean(Object mbean, ObjectName objectName) throws JMException {
+ try {
+ mbeanServer.registerMBean(mbean, objectName);
+ } catch (InstanceAlreadyExistsException ex) {
+ if (this.registrationBehaviour == REGISTRATION_IGNORE_EXISTING) {
+ if (log.isDebugEnabled()) {
+ log.debug("Ignoring existing MBean at [" + objectName + "]");
+ }
+ } else if (this.registrationBehaviour == REGISTRATION_REPLACE_EXISTING) {
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Replacing existing MBean at [" + objectName + "]");
+ }
+ mbeanServer.unregisterMBean(objectName);
+ mbeanServer.registerMBean(mbean, objectName);
+ } catch (InstanceNotFoundException ex2) {
+ log.error("Unable to replace existing MBean at [" + objectName + "]", ex2);
+ throw ex;
+ }
+ } else {
+ throw ex;
+ }
+ }
+ }
}
Index: core/src/main/java/org/quickfixj/jmx/mbean/connector/ConnectorJmxExporter.java
===================================================================
--- core/src/main/java/org/quickfixj/jmx/mbean/connector/ConnectorJmxExporter.java (revision 899)
+++ core/src/main/java/org/quickfixj/jmx/mbean/connector/ConnectorJmxExporter.java (working copy)
@@ -20,11 +20,11 @@
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
-import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.quickfixj.QFJException;
+import org.quickfixj.jmx.JmxExporter;
import org.quickfixj.jmx.mbean.ObjectNameFactory;
import org.quickfixj.jmx.mbean.session.SessionJmxExporter;
import org.slf4j.Logger;
@@ -42,11 +42,11 @@
private final SessionJmxExporter sessionExporter = new SessionJmxExporter();
private final static AtomicInteger connectorIdCounter = new AtomicInteger();
- public void export(MBeanServer mbeanServer, SessionConnector connector) {
- export(mbeanServer, connector, Integer.toString(connectorIdCounter.incrementAndGet()));
+ public void export(JmxExporter jmxExporter, SessionConnector connector) {
+ export(jmxExporter, connector, Integer.toString(connectorIdCounter.incrementAndGet()));
}
- public void export(MBeanServer mbeanServer, SessionConnector connector, String connectorId) {
+ public void export(JmxExporter jmxExporter, SessionConnector connector, String connectorId) {
try {
ConnectorAdmin connectorAdmin;
if (connector instanceof AbstractSocketAcceptor) {
@@ -59,11 +59,11 @@
ObjectName connectorName = getConnectorName(connector, connectorId);
- mbeanServer.registerMBean(connectorAdmin, connectorName);
+ jmxExporter.registerMBean(connectorAdmin, connectorName);
ArrayList