LiveBeansView does not rely on application contexts order anymore
This commit makes sure that the `unregister` order of registered application contexts has no incidence on the removal of the LiveBeansView MBean. Rather than using the last application context's name to compute the identity of the MBean to remove, the identity is stored when the MBean is created. This commit also adds missing tests. Issue: SPR-14848
This commit is contained in:
parent
7dd3e26da4
commit
1f3b8ff2f7
|
|
@ -44,6 +44,7 @@ import org.springframework.util.StringUtils;
|
|||
* Spring Tool Suite 3.1 and higher.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.2
|
||||
* @see #getSnapshotAsJson()
|
||||
* @see org.springframework.web.context.support.LiveBeansViewServlet
|
||||
|
|
@ -57,6 +58,7 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
|||
private static final Set<ConfigurableApplicationContext> applicationContexts =
|
||||
new LinkedHashSet<>();
|
||||
|
||||
private static String applicationName;
|
||||
|
||||
static void registerApplicationContext(ConfigurableApplicationContext applicationContext) {
|
||||
String mbeanDomain = applicationContext.getEnvironment().getProperty(MBEAN_DOMAIN_PROPERTY_NAME);
|
||||
|
|
@ -65,8 +67,9 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
|||
if (applicationContexts.isEmpty()) {
|
||||
try {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
applicationName = applicationContext.getApplicationName();
|
||||
server.registerMBean(new LiveBeansView(),
|
||||
new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationContext.getApplicationName()));
|
||||
new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationName));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ApplicationContextException("Failed to register LiveBeansView MBean", ex);
|
||||
|
|
@ -83,10 +86,12 @@ public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAwar
|
|||
try {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
String mbeanDomain = applicationContext.getEnvironment().getProperty(MBEAN_DOMAIN_PROPERTY_NAME);
|
||||
server.unregisterMBean(new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationContext.getApplicationName()));
|
||||
server.unregisterMBean(new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationName));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ApplicationContextException("Failed to unregister LiveBeansView MBean", ex);
|
||||
} finally {
|
||||
applicationName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.context.support;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Set;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link LiveBeansView}
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class LiveBeansViewTests {
|
||||
|
||||
@Rule
|
||||
public TestName name = new TestName();
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
public void registerIgnoredIfPropertyIsNotSet() throws MalformedObjectNameException {
|
||||
ConfigurableApplicationContext context = createApplicationContext("app");
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
LiveBeansView.registerApplicationContext(context);
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
LiveBeansView.unregisterApplicationContext(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerUnregisterSingleContext() throws MalformedObjectNameException {
|
||||
this.environment.setProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME, this.name.getMethodName());
|
||||
ConfigurableApplicationContext context = createApplicationContext("app");
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
LiveBeansView.registerApplicationContext(context);
|
||||
assertSingleLiveBeansViewMbean("app");
|
||||
LiveBeansView.unregisterApplicationContext(context);
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerUnregisterServeralContexts() throws MalformedObjectNameException {
|
||||
this.environment.setProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME, this.name.getMethodName());
|
||||
ConfigurableApplicationContext context = createApplicationContext("app");
|
||||
ConfigurableApplicationContext childContext = createApplicationContext("child");
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
LiveBeansView.registerApplicationContext(context);
|
||||
assertSingleLiveBeansViewMbean("app");
|
||||
LiveBeansView.registerApplicationContext(childContext);
|
||||
assertEquals(1, searchLiveBeansViewMeans().size()); // Only one MBean
|
||||
LiveBeansView.unregisterApplicationContext(childContext);
|
||||
assertSingleLiveBeansViewMbean("app"); // Root context removes it
|
||||
LiveBeansView.unregisterApplicationContext(context);
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerUnregisterServeralContextsDifferentOrder() throws MalformedObjectNameException {
|
||||
this.environment.setProperty(LiveBeansView.MBEAN_DOMAIN_PROPERTY_NAME, this.name.getMethodName());
|
||||
ConfigurableApplicationContext context = createApplicationContext("app");
|
||||
ConfigurableApplicationContext childContext = createApplicationContext("child");
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
LiveBeansView.registerApplicationContext(context);
|
||||
assertSingleLiveBeansViewMbean("app");
|
||||
LiveBeansView.registerApplicationContext(childContext);
|
||||
assertSingleLiveBeansViewMbean("app"); // Only one MBean
|
||||
LiveBeansView.unregisterApplicationContext(context);
|
||||
LiveBeansView.unregisterApplicationContext(childContext);
|
||||
assertEquals(0, searchLiveBeansViewMeans().size());
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext createApplicationContext(String applicationName) {
|
||||
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
|
||||
given(context.getEnvironment()).willReturn(this.environment);
|
||||
given(context.getApplicationName()).willReturn(applicationName);
|
||||
return context;
|
||||
}
|
||||
|
||||
public void assertSingleLiveBeansViewMbean(String applicationName) throws MalformedObjectNameException {
|
||||
Set<ObjectName> objectNames = searchLiveBeansViewMeans();
|
||||
assertEquals(1, objectNames.size());
|
||||
assertEquals("Wrong MBean name",
|
||||
String.format("%s:application=%s", this.name.getMethodName(), applicationName),
|
||||
objectNames.iterator().next().getCanonicalName());
|
||||
|
||||
}
|
||||
|
||||
private Set<ObjectName> searchLiveBeansViewMeans()
|
||||
throws MalformedObjectNameException {
|
||||
String objectName = String.format("%s:*,%s=*", this.name.getMethodName(),
|
||||
LiveBeansView.MBEAN_APPLICATION_KEY);
|
||||
return ManagementFactory.getPlatformMBeanServer().queryNames(new ObjectName(objectName), null);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue