From 8a9a61b64ffcb4f9d22f16ea1301a2f48e1107ca Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 3 Jan 2017 14:41:48 -0800 Subject: [PATCH] Prevent duplicate JmxEndpoint MBean registration Update JmxEndpoint support so that the `@ManagedResource` annotation is no longer required. This prevents both `EndpointMBeanExporter` and the regular `AnnotationMBeanExporter` from both registering the bean. Fixes gh-7813 See gh-6579 --- .../endpoint/jmx/AbstractJmxEndpoint.java | 2 -- .../endpoint/jmx/AuditEventsJmxEndpoint.java | 6 ++++- .../endpoint/jmx/DataEndpointMBean.java | 2 -- .../actuate/endpoint/jmx/EndpointMBean.java | 2 -- .../endpoint/jmx/EndpointMBeanExporter.java | 24 ++++++++++++++++--- .../actuate/endpoint/jmx/JmxEndpoint.java | 6 +++-- .../endpoint/jmx/LoggersEndpointMBean.java | 2 -- .../endpoint/jmx/ShutdownEndpointMBean.java | 2 -- 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractJmxEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractJmxEndpoint.java index ce43333f13c..ca913c1dc8c 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractJmxEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractJmxEndpoint.java @@ -22,7 +22,6 @@ import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.EndpointProperties; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; -import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.util.ObjectUtils; /** @@ -33,7 +32,6 @@ import org.springframework.util.ObjectUtils; * @author Phillip Webb * @since 1.5.0 */ -@ManagedResource public abstract class AbstractJmxEndpoint implements JmxEndpoint, EnvironmentAware { private final DataConverter dataConverter; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AuditEventsJmxEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AuditEventsJmxEndpoint.java index 2c1186d8dfe..9667abc137e 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AuditEventsJmxEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AuditEventsJmxEndpoint.java @@ -28,6 +28,7 @@ import org.springframework.boot.actuate.audit.AuditEventRepository; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * {@link JmxEndpoint} for {@link AuditEventRepository}. @@ -72,7 +73,10 @@ public class AuditEventsJmxEndpoint extends AbstractJmxEndpoint { private Date parseDate(String date) { try { - return new SimpleDateFormat(DATE_FORMAT).parse(date); + if (StringUtils.hasLength(date)) { + return new SimpleDateFormat(DATE_FORMAT).parse(date); + } + return null; } catch (ParseException ex) { throw new IllegalArgumentException(ex); diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/DataEndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/DataEndpointMBean.java index 385821119b1..36869923de7 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/DataEndpointMBean.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/DataEndpointMBean.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; /** * Simple wrapper around {@link Endpoint} implementations that provide actuator data of @@ -29,7 +28,6 @@ import org.springframework.jmx.export.annotation.ManagedResource; * @author Christian Dupuis * @author Andy Wilkinson */ -@ManagedResource public class DataEndpointMBean extends EndpointMBean { /** diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java index a04e131fa3f..dda22b3d49a 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -35,7 +34,6 @@ import org.springframework.util.ObjectUtils; * @see JmxEndpoint * @see DataEndpointMBean */ -@ManagedResource public abstract class EndpointMBean implements JmxEndpoint { private final DataConverter dataConverter; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java index df3e4db7f63..a07542da61e 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java @@ -46,9 +46,12 @@ import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler; +import org.springframework.jmx.export.metadata.InvalidMetadataException; +import org.springframework.jmx.export.metadata.JmxAttributeSource; import org.springframework.jmx.export.naming.MetadataNamingStrategy; import org.springframework.jmx.export.naming.SelfNaming; import org.springframework.jmx.support.ObjectNameManager; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -70,7 +73,7 @@ public class EndpointMBeanExporter extends MBeanExporter private static final Log logger = LogFactory.getLog(EndpointMBeanExporter.class); - private final AnnotationJmxAttributeSource attributeSource = new AnnotationJmxAttributeSource(); + private final AnnotationJmxAttributeSource attributeSource = new EndpointJmxAttributeSource(); private final MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler( this.attributeSource); @@ -253,8 +256,8 @@ public class EndpointMBeanExporter extends MBeanExporter if (bean instanceof SelfNaming) { return ((SelfNaming) bean).getObjectName(); } - if (bean instanceof EndpointMBean) { - return getObjectName((EndpointMBean) bean, beanKey); + if (bean instanceof JmxEndpoint) { + return getObjectName((JmxEndpoint) bean, beanKey); } return this.defaultNamingStrategy.getObjectName(bean, beanKey); } @@ -363,4 +366,19 @@ public class EndpointMBeanExporter extends MBeanExporter } } + /** + * {@link JmxAttributeSource} for {@link JmxEndpoint JmxEndpoints}. + */ + private static class EndpointJmxAttributeSource extends AnnotationJmxAttributeSource { + + @Override + public org.springframework.jmx.export.metadata.ManagedResource getManagedResource( + Class beanClass) throws InvalidMetadataException { + Assert.state(super.getManagedResource(beanClass) == null, + "@ManagedResource annotation found on JmxEndpoint " + beanClass); + return new org.springframework.jmx.export.metadata.ManagedResource(); + } + + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/JmxEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/JmxEndpoint.java index 70926afa6e5..65a92a0db87 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/JmxEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/JmxEndpoint.java @@ -17,11 +17,13 @@ package org.springframework.boot.actuate.endpoint.jmx; import org.springframework.boot.actuate.endpoint.Endpoint; +import org.springframework.jmx.export.annotation.ManagedResource; /** * A strategy for the JMX layer on top of an {@link Endpoint}. Implementations are allowed - * to use {@code @ManagedAttribute} and the full Spring JMX machinery. Implementations may - * be backed by an actual {@link Endpoint} or may be specifically designed for JMX only. + * to use {@code @ManagedAttribute} and the full Spring JMX machinery but should not use + * the {@link ManagedResource @ManagedResource} annotation. Implementations may be backed + * by an actual {@link Endpoint} or may be specifically designed for JMX only. * * @author Phillip Webb * @since 1.5.0 diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/LoggersEndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/LoggersEndpointMBean.java index b95aea460b0..16b8a02efa4 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/LoggersEndpointMBean.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/LoggersEndpointMBean.java @@ -24,7 +24,6 @@ import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.logging.LogLevel; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.util.Assert; /** @@ -33,7 +32,6 @@ import org.springframework.util.Assert; * @author Vedran Pavic * @since 1.5.0 */ -@ManagedResource public class LoggersEndpointMBean extends EndpointMBean { public LoggersEndpointMBean(String beanName, Endpoint endpoint, diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/ShutdownEndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/ShutdownEndpointMBean.java index d61642f5148..acb181da74b 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/ShutdownEndpointMBean.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/ShutdownEndpointMBean.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.ShutdownEndpoint; import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedResource; /** * Special endpoint wrapper for {@link ShutdownEndpoint}. @@ -29,7 +28,6 @@ import org.springframework.jmx.export.annotation.ManagedResource; * @author Christian Dupuis * @author Andy Wilkinson */ -@ManagedResource public class ShutdownEndpointMBean extends EndpointMBean { /**