2. > 2000
> JMX 1.0
> The first version, JMX 1.0
> It established the core concepts and >
architecture that include MBeans
(Managed Beans), the MBeanServer, and
various services for monitoring and
management
> 2004
> JMX 1.2
> This version brought enhancements to
ease the development of management and
monitoring solutions. It included
improvements in the MBean model and the
overall API
> 2004
> JMX in Java 5 SE
> JMX became part of the standard Java platform. This integration greatly increased its
adoption, as it became available in all standard Java distributions
> Minor improvements (generics) for Java 6 in 2006
3. > JMX APIs are at Java 6 level
> Naming convention based
> Minimal support for annotations
> Long term open issues and improvements
> Security concerns
> Performance
> Ease of use
4. > JMX Annotations
> JDK-8044507 (JEP)
> By yours truly
> Update the JMX APIs to allow using
annotations to register and use MBeans
> JEP created in 2014 then went dormant
> Builds on JSR 255
> more comprehensive JMX spec update
> created: 2004
> withdrawn: 2016
> never fully implemented
> JMX Rest Connector
> JDK-8171311 (JEP)
> Provide a lightweight REST connector
> default instead of aging RMI
> JEP created in 2016, closed 2018
> considered unnecessary due eg.
Jolokia
> JMX still works only via RMI OOTB
> Improved Key Management
> Non-public issue (sec related)
> Allow SSH-like experience
> no more fumbling with keystore and
certstore on client and server
> Not sure about its fate
> most probably cancelled as well
5. > JMX Annotations
> Simple service
> A simple service MXBean
> Custom description for service, attributes and operations
> Custom units for attributes and operations
> Notification support
> “Traditional” JMX
> Needs SimpleServiceMXBean interface
> Needs SimpleServiceMXBeanImpl implementation
> For custom descriptions
> Create custom MBeanInfo for the service
> Implement DynamicMBean with reflective operation/attribute access
> For notifications
> SimpleServiceMXBean extends NotificationEmitter
> SimpleServiceMXBeanImpl implements NotificationBroadcaster
> SimpleServiceMXBeanImpl delegates to NotificationBroadcasterSupport
> SimpleServiceMXBeanImpl provides MBeanNotificationInfos
> Lot of boilerplate!
6. > JMX Annotations
> Managed service
@ManagedService(
objectName="net.java.jmx:type=StandardService",
description="A simple service exposed as an MXBean",
service=Service.class,
tags = {
@Tag(name = "tag1", value = "val1"),
@Tag(name = "tag2", value = "val2")
}
)
public class SimpleService {
…
}
7. > JMX Annotations
> Managed service
@ManagedService(
objectName="net.java.jmx:type=StandardService",
description="A simple service exposed as an MXBean",
service=Service.class,
tags = {
@Tag(name = "tag1", value = "val1"),
@Tag(name = "tag2", value = "val2")
}
)
public class SimpleService {
…
}
Freeform service name
Included ObjectName
Included description
Custom service class
Freeform tags
8. > JMX Annotations
> Managed attributes
public class SimpleService {
// A write-only attribute measured in "ticks"
@ManagedAttribute(access = AttributeAccess.WRITE, units = "ticks")
int counter = 1;
// A read-only attribute being an array of strings
@ManagedAttribute(access = AttributeAccess.READ,
description = "ReadOnly Attribute")
String[] arr = new String[]{"sa", "ba", "ca"};
// Declare a read-write attribute ...
@ManagedAttribute(access = AttributeAccess.READWRITE,
tags = {
@Tag(name = "tag1", value = "val1"),
@Tag(name = "tag2", value = "val2")
}
)
private String label = "the label";
…
}
9. > JMX Annotations
> Managed attributes
public class SimpleService {
// A write-only attribute measured in "ticks"
@ManagedAttribute(access = AttributeAccess.WRITE, units = "ticks")
int counter = 1;
// A read-only attribute being an array of strings
@ManagedAttribute(access = AttributeAccess.READ,
description = "ReadOnly Attribute")
String[] arr = new String[]{"sa", "ba", "ca"};
// Declare a read-write attribute ...
@ManagedAttribute(access = AttributeAccess.READWRITE,
tags = {
@Tag(name = "tag1", value = "val1"),
@Tag(name = "tag2", value = "val2")
}
)
private String label = "the label";
…
}
Attribute access
Support for units
Included description
Freeform tags
Custom getters/setters
10. > JMX Annotations
> Managed operations
public class SimpleService {
// an operation modifying the 'counter' attribute
@ManagedOperation(impact = Impact.ACTION,
description = "Increases the associated counter by 1")
public int count() {
return ++counter;
}
// an operation declaring custom 'units' metadata for one of its parameters
@ManagedOperation
public void checkTime(@Parameter(units = "ms") long ts) {
System.err.println(new Date(ts));
}
…
}
11. > JMX Annotations
> Managed operations
public class SimpleService {
// an operation modifying the 'counter' attribute
@ManagedOperation(impact = Impact.ACTION,
description = "Increases the associated counter by 1")
public int count() {
return ++counter;
}
// an operation declaring custom 'units' metadata for one of its parameters
@ManagedOperation
public void checkTime(@ParameterInfo(units = "ms") long ts) {
System.err.println(new Date(ts));
}
…
}
Service impact
Included description
Metadata for parameters
Custom units
Freeform tags
12. > JMX Annotations
> Notifications
public class SimpleService {
@NotificationInfos({
@NotificationInfo(types = "test.mbean.label", description = "Label was set")
@NotificationInfo(types = "test.mbean.threshold", description = "Counter threshold reached")
})
private NotificationSender ns;
@ManagedAttribute
public void setLabel(String l) {
ns.sendNotification("test.mbean.label", "Label set", l);
label = l;
}
@ManagedOperation(impact = Impact.ACTION, description = "Increases the associated counter by 1")
public int count() {
if (counter >= 5) {
ns.sendNotification("test.mbean.threshold", "Threshold reached", counter);
}
return ++counter;
}
…
}
13. > JMX Annotations
> Notifications
public class SimpleService {
@NotificationInfos({
@NotificationInfo(types = "test.mbean.label", description = "Label was set")
@NotificationInfo(types = "test.mbean.threshold", description = "Counter threshold reached")
})
private NotificationSender ns;
@ManagedAttribute
public void setLabel(String l) {
ns.sendNotification("test.mbean.label", "Label set", l);
label = l;
}
@ManagedOperation(impact = Impact.ACTION, description = "Increases the associated counter by 1")
public int count() {
if (counter >= 5) {
ns.sendNotification("test.mbean.threshold", "Threshold reached", counter);
}
return ++counter;
}
…
}
Injected notification sender
Notification info types
Simple emitter
14. > JMX Annotations
> Custom registration handler
public class SimpleService {
// handle the registration/unregsitration of the MBean
@RegistrationHandler
public void onRegistration(RegistrationEvent re) {
switch(re.getKind()) {
case REGISTER: {
System.err.println("Registered " + re.getObjectName().getCanonicalName());
break;
}
case UNREGISTER: {
System.err.println("Unregistered " + re.getObjectName().getCanonicalName());
break;
}
}
}
…
}
15. > JMX Annotations
> Custom registration handler
public class SimpleService {
// handle the registration/unregsitration of the MBean
@RegistrationHandler
public void onRegistration(RegistrationEvent re) {
switch(re.getKind()) {
case REGISTER: {
System.err.println("Registered " + re.getObjectName().getCanonicalName());
break;
}
case UNREGISTER: {
System.err.println("Unregistered " + re.getObjectName().getCanonicalName());
break;
}
}
}
…
}
Simple registration listener
‘When-registered’ hook
‘When-unregistered’ hook
16. > JMX Annotations
> Where to get it?
GitHub!
> https://github.com/DataDog/openjdk-jdk/tree/jb/jmx_annotations
> https://github.com/DataDog/openjdk-jdk/pull/4
17. > JMX REST Connector
> Simple, self-contained implementation
> Base URL - http[s]://<host_name>:<port>/jmx/default
> auto-discovery capable - JDP, perf-counter, JCMD
> Endpoints
> <root>/mbeans
GET : list of all registered MBeans
> <root>/<mbean_name>
GET : get corresponding MBeanInfo
> <root>/<mbean_name>/<attribute_name>
GET : get the attribute value
> <root>/<mbean_name>/?attributes=a,b,c|all
GET : get values of multiple MBean attributes
> <root>/domains
GET : get all available domains
> <root>/?domain=default
GET : get default domain
> <root>/?domain=<domain_name>/mbeans
GET : list of all MBeans in the domain
20. > JMX REST Connector
> Query Response
> Wrapped in
// success
{
"status": 200,
"request": {
original HTTP request
},
"response": {
result of above request
}
}
// error
{
"status": 4XX/5XX,
"request": {
original HTTP request
},
"error": "<error message>"
}
21. > JMX REST Connector
> Query Response Body
> Java->JSON auto-serialization for
- MXBeans
- OpenMBeans
- String, primitive values and arrays of them
- BigInteger, BigDecimal
- Date, ObjectName, CompositeData, TabularData
22. > JMX REST Connector
> Mostly working but abandoned
> Harsha Wardhana’s CR space
> https://cr.openjdk.org/~hb/8171311/webrev.01/
> might be up for adoption(?)
23. > Summary
> JMX feels outdated
> Labour intensive APIs
> Coupled with RMI
> Needs persistent connection and pull loop from client
> There are proposals to improve it
> Evolution rather than revolution
> Some parts almost fully functional
> Million Dollar Question
> Has JMX any future?
> Who is willing to invest?
24. It’s a wrap-up!
Thanks, Qs are welcome!
Jaroslav Bachorik
X:
@Bachorik
J
GH: jbachorik All images generated by Dall-E