[[jmx-interface]] = Controlling the Management Interface of Your Beans In the example in the xref:integration/jmx/exporting.adoc#jmx-exporting-registration-behavior[preceding section], you had little control over the management interface of your bean. All of the `public` properties and methods of each exported bean were exposed as JMX attributes and operations, respectively. To exercise finer-grained control over exactly which properties and methods of your exported beans are actually exposed as JMX attributes and operations, Spring JMX provides a comprehensive and extensible mechanism for controlling the management interfaces of your beans. [[jmx-interface-assembler]] == Using the `MBeanInfoAssembler` Interface Behind the scenes, the `MBeanExporter` delegates to an implementation of the `org.springframework.jmx.export.assembler.MBeanInfoAssembler` interface, which is responsible for defining the management interface of each bean that is exposed. The default implementation, `org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler`, defines a management interface that exposes all public properties and methods (as you saw in the examples in the preceding sections). Spring provides two additional implementations of the `MBeanInfoAssembler` interface that let you control the generated management interface by using either source-level metadata or any arbitrary interface. [[jmx-interface-metadata]] == Using Source-level Metadata: Java Annotations By using the `MetadataMBeanInfoAssembler`, you can define the management interfaces for your beans by using source-level metadata. The reading of metadata is encapsulated by the `org.springframework.jmx.export.metadata.JmxAttributeSource` interface. Spring JMX provides a default implementation that uses Java annotations, namely `org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource`. You must configure the `MetadataMBeanInfoAssembler` with an implementation instance of the `JmxAttributeSource` interface for it to function correctly (there is no default). To mark a bean for export to JMX, you should annotate the bean class with the `ManagedResource` annotation. You must mark each method you wish to expose as an operation with the `ManagedOperation` annotation and mark each property you wish to expose with the `ManagedAttribute` annotation. When marking properties, you can omit either the annotation of the getter or the setter to create a write-only or read-only attribute, respectively. NOTE: A `ManagedResource`-annotated bean must be public, as must the methods exposing an operation or an attribute. The following example shows the annotated version of the `JmxTestBean` class that we used in xref:integration/jmx/exporting.adoc#jmx-exporting-mbeanserver[Creating an MBeanServer]: [source,java,indent=0,subs="verbatim,quotes",chomp="-packages"] ---- package org.springframework.jmx; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedAttribute; @ManagedResource( objectName="bean:name=testBean4", description="My Managed Bean", log=true, logFile="jmx.log", currencyTimeLimit=15, persistPolicy="OnUpdate", persistPeriod=200, persistLocation="foo", persistName="bar") public class AnnotationTestBean implements IJmxTestBean { private String name; private int age; @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) public int getAge() { return age; } public void setAge(int age) { this.age = age; } @ManagedAttribute(description="The Name Attribute", currencyTimeLimit=20, defaultValue="bar", persistPolicy="OnUpdate") public void setName(String name) { this.name = name; } @ManagedAttribute(defaultValue="foo", persistPeriod=300) public String getName() { return name; } @ManagedOperation(description="Add two numbers") @ManagedOperationParameters({ @ManagedOperationParameter(name = "x", description = "The first number"), @ManagedOperationParameter(name = "y", description = "The second number")}) public int add(int x, int y) { return x + y; } public void dontExposeMe() { throw new RuntimeException(); } } ---- In the preceding example, you can see that the `JmxTestBean` class is marked with the `ManagedResource` annotation and that this `ManagedResource` annotation is configured with a set of properties. These properties can be used to configure various aspects of the MBean that is generated by the `MBeanExporter` and are explained in greater detail later in xref:integration/jmx/interface.adoc#jmx-interface-metadata-types[Source-level Metadata Types]. Both the `age` and `name` properties are annotated with the `ManagedAttribute` annotation, but, in the case of the `age` property, only the getter is marked. This causes both of these properties to be included in the management interface as attributes, but the `age` attribute is read-only. Finally, the `add(int, int)` method is marked with the `ManagedOperation` attribute, whereas the `dontExposeMe()` method is not. This causes the management interface to contain only one operation (`add(int, int)`) when you use the `MetadataMBeanInfoAssembler`. The following configuration shows how you can configure the `MBeanExporter` to use the `MetadataMBeanInfoAssembler`: [source,xml,indent=0,subs="verbatim,quotes"] ---- ---- In the preceding example, an `MetadataMBeanInfoAssembler` bean has been configured with an instance of the `AnnotationJmxAttributeSource` class and passed to the `MBeanExporter` through the assembler property. This is all that is required to take advantage of metadata-driven management interfaces for your Spring-exposed MBeans. [[jmx-interface-metadata-types]] == Source-level Metadata Types The following table describes the source-level metadata types that are available for use in Spring JMX: [[jmx-metadata-types]] .Source-level metadata types |=== | Purpose| Annotation| Annotation Type | Mark all instances of a `Class` as JMX managed resources. | `@ManagedResource` | Class | Mark a method as a JMX operation. | `@ManagedOperation` | Method | Mark a getter or setter as one half of a JMX attribute. | `@ManagedAttribute` | Method (only getters and setters) | Define descriptions for operation parameters. | `@ManagedOperationParameter` and `@ManagedOperationParameters` | Method |=== The following table describes the configuration parameters that are available for use on these source-level metadata types: [[jmx-metadata-parameters]] .Source-level metadata parameters [cols="1,3,1"] |=== | Parameter | Description | Applies to | `ObjectName` | Used by `MetadataNamingStrategy` to determine the `ObjectName` of a managed resource. | `ManagedResource` | `description` | Sets the friendly description of the resource, attribute or operation. | `ManagedResource`, `ManagedAttribute`, `ManagedOperation`, or `ManagedOperationParameter` | `currencyTimeLimit` | Sets the value of the `currencyTimeLimit` descriptor field. | `ManagedResource` or `ManagedAttribute` | `defaultValue` | Sets the value of the `defaultValue` descriptor field. | `ManagedAttribute` | `log` | Sets the value of the `log` descriptor field. | `ManagedResource` | `logFile` | Sets the value of the `logFile` descriptor field. | `ManagedResource` | `persistPolicy` | Sets the value of the `persistPolicy` descriptor field. | `ManagedResource` | `persistPeriod` | Sets the value of the `persistPeriod` descriptor field. | `ManagedResource` | `persistLocation` | Sets the value of the `persistLocation` descriptor field. | `ManagedResource` | `persistName` | Sets the value of the `persistName` descriptor field. | `ManagedResource` | `name` | Sets the display name of an operation parameter. | `ManagedOperationParameter` | `index` | Sets the index of an operation parameter. | `ManagedOperationParameter` |=== [[jmx-interface-autodetect]] == Using the `AutodetectCapableMBeanInfoAssembler` Interface To simplify configuration even further, Spring includes the `AutodetectCapableMBeanInfoAssembler` interface, which extends the `MBeanInfoAssembler` interface to add support for autodetection of MBean resources. If you configure the `MBeanExporter` with an instance of `AutodetectCapableMBeanInfoAssembler`, it is allowed to "`vote`" on the inclusion of beans for exposure to JMX. The only implementation of the `AutodetectCapableMBeanInfo` interface is the `MetadataMBeanInfoAssembler`, which votes to include any bean that is marked with the `ManagedResource` attribute. The default approach in this case is to use the bean name as the `ObjectName`, which results in a configuration similar to the following: [source,xml,indent=0,subs="verbatim,quotes"] ---- ---- Notice that, in the preceding configuration, no beans are passed to the `MBeanExporter`. However, the `JmxTestBean` is still registered, since it is marked with the `ManagedResource` attribute and the `MetadataMBeanInfoAssembler` detects this and votes to include it. The only problem with this approach is that the name of the `JmxTestBean` now has business meaning. You can address this issue by changing the default behavior for `ObjectName` creation as defined in xref:integration/jmx/naming.adoc[Controlling `ObjectName` Instances for Your Beans]. [[jmx-interface-java]] == Defining Management Interfaces by Using Java Interfaces In addition to the `MetadataMBeanInfoAssembler`, Spring also includes the `InterfaceBasedMBeanInfoAssembler`, which lets you constrain the methods and properties that are exposed based on the set of methods defined in a collection of interfaces. Although the standard mechanism for exposing MBeans is to use interfaces and a simple naming scheme, `InterfaceBasedMBeanInfoAssembler` extends this functionality by removing the need for naming conventions, letting you use more than one interface and removing the need for your beans to implement the MBean interfaces. Consider the following interface, which is used to define a management interface for the `JmxTestBean` class that we showed earlier: [source,java,indent=0,subs="verbatim,quotes"] ---- public interface IJmxTestBean { public int add(int x, int y); public long myOperation(); public int getAge(); public void setAge(int age); public void setName(String name); public String getName(); } ---- This interface defines the methods and properties that are exposed as operations and attributes on the JMX MBean. The following code shows how to configure Spring JMX to use this interface as the definition for the management interface: [source,xml,indent=0,subs="verbatim,quotes"] ---- org.springframework.jmx.IJmxTestBean ---- In the preceding example, the `InterfaceBasedMBeanInfoAssembler` is configured to use the `IJmxTestBean` interface when constructing the management interface for any bean. It is important to understand that beans processed by the `InterfaceBasedMBeanInfoAssembler` are not required to implement the interface used to generate the JMX management interface. In the preceding case, the `IJmxTestBean` interface is used to construct all management interfaces for all beans. In many cases, this is not the desired behavior, and you may want to use different interfaces for different beans. In this case, you can pass `InterfaceBasedMBeanInfoAssembler` a `Properties` instance through the `interfaceMappings` property, where the key of each entry is the bean name and the value of each entry is a comma-separated list of interface names to use for that bean. If no management interface is specified through either the `managedInterfaces` or `interfaceMappings` properties, the `InterfaceBasedMBeanInfoAssembler` reflects on the bean and uses all of the interfaces implemented by that bean to create the management interface. [[jmx-interface-methodnames]] == Using `MethodNameBasedMBeanInfoAssembler` `MethodNameBasedMBeanInfoAssembler` lets you specify a list of method names that are exposed to JMX as attributes and operations. The following code shows a sample configuration: [source,xml,indent=0,subs="verbatim,quotes"] ---- add,myOperation,getName,setName,getAge ---- In the preceding example, you can see that the `add` and `myOperation` methods are exposed as JMX operations, and `getName()`, `setName(String)`, and `getAge()` are exposed as the appropriate half of a JMX attribute. In the preceding code, the method mappings apply to beans that are exposed to JMX. To control method exposure on a bean-by-bean basis, you can use the `methodMappings` property of `MethodNameMBeanInfoAssembler` to map bean names to lists of method names.