418 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			418 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| [[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"]
 | |
| ----
 | |
| 	<beans>
 | |
| 		<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
 | |
| 			<property name="assembler" ref="assembler"/>
 | |
| 			<property name="namingStrategy" ref="namingStrategy"/>
 | |
| 			<property name="autodetect" value="true"/>
 | |
| 		</bean>
 | |
| 
 | |
| 		<bean id="jmxAttributeSource"
 | |
| 				class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
 | |
| 
 | |
| 		<!-- will create management interface using annotation metadata -->
 | |
| 		<bean id="assembler"
 | |
| 				class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
 | |
| 			<property name="attributeSource" ref="jmxAttributeSource"/>
 | |
| 		</bean>
 | |
| 
 | |
| 		<!-- will pick up the ObjectName from the annotation -->
 | |
| 		<bean id="namingStrategy"
 | |
| 				class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
 | |
| 			<property name="attributeSource" ref="jmxAttributeSource"/>
 | |
| 		</bean>
 | |
| 
 | |
| 		<bean id="testBean" class="org.springframework.jmx.AnnotationTestBean">
 | |
| 			<property name="name" value="TEST"/>
 | |
| 			<property name="age" value="100"/>
 | |
| 		</bean>
 | |
| 	</beans>
 | |
| ----
 | |
| 
 | |
| 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"]
 | |
| ----
 | |
| 	<beans>
 | |
| 
 | |
| 		<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
 | |
| 			<!-- notice how no 'beans' are explicitly configured here -->
 | |
| 			<property name="autodetect" value="true"/>
 | |
| 			<property name="assembler" ref="assembler"/>
 | |
| 		</bean>
 | |
| 
 | |
| 		<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
 | |
| 			<property name="name" value="TEST"/>
 | |
| 			<property name="age" value="100"/>
 | |
| 		</bean>
 | |
| 
 | |
| 		<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
 | |
| 			<property name="attributeSource">
 | |
| 				<bean class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
 | |
| 			</property>
 | |
| 		</bean>
 | |
| 
 | |
| 	</beans>
 | |
| ----
 | |
| 
 | |
| 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"]
 | |
| ----
 | |
| 	<beans>
 | |
| 
 | |
| 		<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
 | |
| 			<property name="beans">
 | |
| 				<map>
 | |
| 					<entry key="bean:name=testBean5" value-ref="testBean"/>
 | |
| 				</map>
 | |
| 			</property>
 | |
| 			<property name="assembler">
 | |
| 				<bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
 | |
| 					<property name="managedInterfaces">
 | |
| 						<value>org.springframework.jmx.IJmxTestBean</value>
 | |
| 					</property>
 | |
| 				</bean>
 | |
| 			</property>
 | |
| 		</bean>
 | |
| 
 | |
| 		<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
 | |
| 			<property name="name" value="TEST"/>
 | |
| 			<property name="age" value="100"/>
 | |
| 		</bean>
 | |
| 
 | |
| 	</beans>
 | |
| ----
 | |
| 
 | |
| 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"]
 | |
| ----
 | |
| 	<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
 | |
| 		<property name="beans">
 | |
| 			<map>
 | |
| 				<entry key="bean:name=testBean5" value-ref="testBean"/>
 | |
| 			</map>
 | |
| 		</property>
 | |
| 		<property name="assembler">
 | |
| 			<bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
 | |
| 				<property name="managedMethods">
 | |
| 					<value>add,myOperation,getName,setName,getAge</value>
 | |
| 				</property>
 | |
| 			</bean>
 | |
| 		</property>
 | |
| 	</bean>
 | |
| ----
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 
 | |
| 
 |