From a6d18f714fb095e290d29c0ad3e7ec9f6cd4b759 Mon Sep 17 00:00:00 2001 From: Vedran Pavic Date: Sun, 20 Nov 2016 17:04:17 +0100 Subject: [PATCH] Add JMX without backing `Endpoint` support Decompose `EndpointMBean` to improve support for JMX endpoints without a backing `Endpoint`. See gh-6579 --- .../endpoint/jmx/AbstractEndpointMBean.java | 94 +++++++++++++++++++ .../actuate/endpoint/jmx/EndpointMBean.java | 33 +------ .../endpoint/jmx/EndpointMBeanSupport.java | 70 ++++++++++++++ .../mvc/AbstractNamedMvcEndpoint.java | 2 +- 4 files changed, 168 insertions(+), 31 deletions(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractEndpointMBean.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanSupport.java diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractEndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractEndpointMBean.java new file mode 100644 index 00000000000..a47b323c059 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/AbstractEndpointMBean.java @@ -0,0 +1,94 @@ +/* + * Copyright 2012-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.boot.actuate.endpoint.jmx; + +import com.fasterxml.jackson.databind.ObjectMapper; + +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; + +/** + * Abstract base class for JMX endpoint implementations without a backing + * {@link Endpoint}. + * + * @author Vedran Pavic + * @since 1.5.0 + */ +public abstract class AbstractEndpointMBean extends EndpointMBeanSupport + implements EnvironmentAware { + + private Environment environment; + + /** + * Enable the endpoint. + */ + private Boolean enabled; + + /** + * Mark if the endpoint exposes sensitive information. + */ + private Boolean sensitive; + + private final boolean sensitiveDefault; + + public AbstractEndpointMBean(ObjectMapper objectMapper, boolean sensitive) { + super(objectMapper); + this.sensitiveDefault = sensitive; + } + + public AbstractEndpointMBean(ObjectMapper objectMapper, boolean sensitive, + boolean enabled) { + super(objectMapper); + this.sensitiveDefault = sensitive; + this.enabled = enabled; + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + protected final Environment getEnvironment() { + return this.environment; + } + + public boolean isEnabled() { + return EndpointProperties.isEnabled(this.environment, this.enabled); + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean isSensitive() { + return EndpointProperties.isSensitive(this.environment, this.sensitive, + this.sensitiveDefault); + } + + public void setSensitive(Boolean sensitive) { + this.sensitive = sensitive; + } + + @Override + public String getEndpointClass() { + return null; + } + +} 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 e9ffdfcd39a..a98160b0cba 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 @@ -16,10 +16,6 @@ package org.springframework.boot.actuate.endpoint.jmx; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.actuate.endpoint.Endpoint; @@ -33,18 +29,13 @@ import org.springframework.util.ClassUtils; * * @author Christian Dupuis * @author Andy Wilkinson + * @author Vedran Pavic */ @ManagedResource -public class EndpointMBean { +public class EndpointMBean extends EndpointMBeanSupport { private final Endpoint endpoint; - private final ObjectMapper mapper; - - private final JavaType listObject; - - private final JavaType mapStringObject; - /** * Create a new {@link EndpointMBean} instance. * @param beanName the bean name @@ -53,15 +44,10 @@ public class EndpointMBean { */ public EndpointMBean(String beanName, Endpoint endpoint, ObjectMapper objectMapper) { + super(objectMapper); Assert.notNull(beanName, "BeanName must not be null"); Assert.notNull(endpoint, "Endpoint must not be null"); - Assert.notNull(objectMapper, "ObjectMapper must not be null"); this.endpoint = endpoint; - this.mapper = objectMapper; - this.listObject = objectMapper.getTypeFactory() - .constructParametricType(List.class, Object.class); - this.mapStringObject = objectMapper.getTypeFactory() - .constructParametricType(Map.class, String.class, Object.class); } @ManagedAttribute(description = "Returns the class of the underlying endpoint") @@ -78,17 +64,4 @@ public class EndpointMBean { return this.endpoint; } - protected Object convert(Object result) { - if (result == null) { - return null; - } - if (result instanceof String) { - return result; - } - if (result.getClass().isArray() || result instanceof List) { - return this.mapper.convertValue(result, this.listObject); - } - return this.mapper.convertValue(result, this.mapStringObject); - } - } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanSupport.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanSupport.java new file mode 100644 index 00000000000..a755c650417 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanSupport.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-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.boot.actuate.endpoint.jmx; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.jmx.export.annotation.ManagedAttribute; +import org.springframework.util.Assert; + +/** + * Abstract base class for JMX endpoint implementations. + * + * @author Vedran Pavic + * @since 1.5.0 + */ +public abstract class EndpointMBeanSupport { + + private final ObjectMapper mapper; + + private final JavaType listObject; + + private final JavaType mapStringObject; + + public EndpointMBeanSupport(ObjectMapper objectMapper) { + Assert.notNull(objectMapper, "ObjectMapper must not be null"); + this.mapper = objectMapper; + this.listObject = objectMapper.getTypeFactory() + .constructParametricType(List.class, Object.class); + this.mapStringObject = objectMapper.getTypeFactory() + .constructParametricType(Map.class, String.class, Object.class); + } + + @ManagedAttribute(description = "Indicates whether the underlying endpoint exposes sensitive information") + public abstract boolean isSensitive(); + + @ManagedAttribute(description = "Returns the class of the underlying endpoint") + public abstract String getEndpointClass(); + + protected Object convert(Object result) { + if (result == null) { + return null; + } + if (result instanceof String) { + return result; + } + if (result.getClass().isArray() || result instanceof List) { + return this.mapper.convertValue(result, this.listObject); + } + return this.mapper.convertValue(result, this.mapStringObject); + } + +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java index 2c791133574..a9bac91d6a8 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java @@ -26,7 +26,7 @@ import org.springframework.util.Assert; * @author Madhura Bhave * @since 1.5.0 */ -public class AbstractNamedMvcEndpoint extends AbstractMvcEndpoint +public abstract class AbstractNamedMvcEndpoint extends AbstractMvcEndpoint implements NamedMvcEndpoint { private final String name;