SM-2161: JMX InstanceAlreadyExistsException when restarting web distribution on WebSphere
git-svn-id: https://svn.apache.org/repos/asf/servicemix/smx3/trunk@1366290 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ManagementContext.java b/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ManagementContext.java
index c306633..57eb331 100644
--- a/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ManagementContext.java
+++ b/core/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ManagementContext.java
@@ -26,11 +26,15 @@
import java.util.concurrent.Executors;
import javax.jbi.JBIException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
+import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.apache.servicemix.jbi.container.EnvironmentContext;
@@ -91,6 +95,10 @@
return mbeanServerContext.getMBeanServer();
}
+ protected void setMBeanServer(MBeanServer server) {
+ mbeanServerContext.setMBeanServer(server);
+ }
+
/**
* @return the domain
*/
@@ -531,17 +539,33 @@
* @param description
* @throws JMException
*/
- public void registerMBean(ObjectName name, Object resource, Class interfaceMBean, String description) throws JMException {
+ public ObjectName registerMBean(ObjectName name, Object resource, Class interfaceMBean, String description) throws JMException {
if (mbeanServerContext.getMBeanServer() != null) {
Object mbean = MBeanBuilder.buildStandardMBean(resource, interfaceMBean, description, executors);
- if (mbeanServerContext.getMBeanServer().isRegistered(name)) {
- mbeanServerContext.getMBeanServer().unregisterMBean(name);
- }
- mbeanServerContext.getMBeanServer().registerMBean(mbean, name);
- beanMap.put(name, resource);
+ return registerMBean(name, resource, mbean);
+ } else {
+ return name;
}
}
+ /*
+ * Register an MBean for a given resource, specifying the object name and the actual MBean implementation
+ *
+ * @param name the MBean's ObjectName
+ * @param resource the original bean for which the MBean is a wrapper
+ * @param mbean the MBean implementation
+ */
+ protected ObjectName registerMBean(ObjectName name, Object resource, Object mbean)
+ throws InstanceNotFoundException, MBeanRegistrationException, InstanceAlreadyExistsException, NotCompliantMBeanException {
+
+ if (mbeanServerContext.getMBeanServer().isRegistered(name)) {
+ mbeanServerContext.getMBeanServer().unregisterMBean(name);
+ }
+ ObjectName objectName = mbeanServerContext.getMBeanServer().registerMBean(mbean, name).getObjectName();
+ beanMap.put(objectName, resource);
+ return objectName;
+ }
+
/**
* Retrive an System ObjectName
*
@@ -619,8 +643,8 @@
}
ObjectName objName = createObjectName(service);
LOGGER.debug("Registering system service: {}", objName);
- registerMBean(objName, service, interfaceType, service.getDescription());
- systemServices.put(name, objName);
+ ObjectName registeredName = registerMBean(objName, service, interfaceType, service.getDescription());
+ systemServices.put(name, registeredName);
} catch (MalformedObjectNameException e) {
throw new JBIException(e);
} catch (JMException e) {
diff --git a/core/servicemix-core/src/test/java/org/apache/servicemix/jbi/management/WebSphereManagementContextTest.java b/core/servicemix-core/src/test/java/org/apache/servicemix/jbi/management/WebSphereManagementContextTest.java
new file mode 100644
index 0000000..027cefb
--- /dev/null
+++ b/core/servicemix-core/src/test/java/org/apache/servicemix/jbi/management/WebSphereManagementContextTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.servicemix.jbi.management;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+import junit.framework.TestCase;
+import org.apache.servicemix.jbi.container.JBIContainer;
+import org.junit.Test;
+
+/**
+ * Additional tests to ensure the {@link ManagementContext} behaves properly when the actual ObjectName does not match
+ * the ObjectName used for registration (e.g. on WebSphere, where cell/node/process information gets appended to the ObjectName)
+ */
+public class WebSphereManagementContextTest extends TestCase {
+
+ private static final ObjectName OBJECT_NAME =
+ ManagementContext.getSystemObjectName(ManagementContext.DEFAULT_DOMAIN, JBIContainer.DEFAULT_NAME, SampleMBean.class);
+
+ @Test
+ public void testObjectNameAltered() throws Exception {
+ ManagementContext context = new ManagementContext();
+ MBeanServer server = MBeanServerFactory.createMBeanServer();
+ context.setMBeanServer(server);
+
+ SampleMBeanImpl impl = new SampleMBeanImpl();
+ RenamingStandardMBean mbean = new RenamingStandardMBean(impl, SampleMBean.class);
+
+ // let's register and unregister the MBean
+ context.registerMBean(OBJECT_NAME, impl, mbean);
+ context.unregisterMBean(impl);
+
+ // if the previous unregistration failed because of non-matching object names, the method below will throw
+ // javax.management.InstanceAlreadyExistsException
+ context.registerMBean(OBJECT_NAME, impl, mbean);
+ }
+
+
+ /*
+ * MBean interface definition used for testing
+ */
+ public static interface SampleMBean {
+
+ void doSomething();
+
+ }
+
+ /*
+ * MBean implementation
+ */
+ public static final class SampleMBeanImpl implements SampleMBean {
+
+ public void doSomething() {
+ // graciously do nothing here
+ }
+ }
+
+ /*
+ * {@link StandardMBean} implementation that will append parts to the MBean's object name upon registration
+ * (i.e. adding node/cell/process parts similar to what WebSphere does)
+ */
+ public final class RenamingStandardMBean extends StandardMBean implements MBeanRegistration {
+
+
+ public <T> RenamingStandardMBean(T object, Class<T> type) throws NotCompliantMBeanException {
+ super(object, type);
+ }
+
+
+ public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception {
+ return new ObjectName(objectName.toString() + ",node=node1,cell=cell1,process=process1");
+ }
+
+ public void postRegister(Boolean aBoolean) {
+ // graciously do nothing here
+ }
+
+ public void preDeregister() throws Exception {
+ // graciously do nothing here
+ }
+
+ public void postDeregister() {
+ // graciously do nothing here
+ }
+ }
+}