diff --git a/framework-docs/modules/ROOT/pages/integration/jmx/interface.adoc b/framework-docs/modules/ROOT/pages/integration/jmx/interface.adoc index f9458765aa..68e1c25206 100644 --- a/framework-docs/modules/ROOT/pages/integration/jmx/interface.adoc +++ b/framework-docs/modules/ROOT/pages/integration/jmx/interface.adoc @@ -11,10 +11,10 @@ controlling the management interfaces of your beans. [[jmx-interface-assembler]] -== Using the `MBeanInfoAssembler` Interface +== Using the `MBeanInfoAssembler` API Behind the scenes, the `MBeanExporter` delegates to an implementation of the -`org.springframework.jmx.export.assembler.MBeanInfoAssembler` interface, which is +`org.springframework.jmx.export.assembler.MBeanInfoAssembler` API, which is responsible for defining the management interface of each bean that is exposed. The default implementation, `org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler`, @@ -28,35 +28,31 @@ 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). +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, since 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 +`@ManagedResource` annotation. You must annotate each method you wish to expose as an +operation with the `@ManagedOperation` annotation and annotate each property you wish to +expose with the `@ManagedAttribute` annotation. When annotating 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. +NOTE: A `@ManagedResource`-annotated bean must be public, as must the methods exposing +operations or attributes. -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]: +The following example shows an 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", @@ -67,20 +63,20 @@ used in xref:integration/jmx/exporting.adoc#jmx-exporting-mbeanserver[Creating a persistPeriod=200, persistLocation="foo", persistName="bar") - public class AnnotationTestBean implements IJmxTestBean { + public class AnnotationTestBean { - private String name; private int age; - - @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) - public int getAge() { - return age; - } + private String name; public void setAge(int age) { this.age = age; } + @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) + public int getAge() { + return this.age; + } + @ManagedAttribute(description="The Name Attribute", currencyTimeLimit=20, defaultValue="bar", @@ -91,13 +87,12 @@ used in xref:integration/jmx/exporting.adoc#jmx-exporting-mbeanserver[Creating a @ManagedAttribute(defaultValue="foo", persistPeriod=300) public String getName() { - return name; + return this.name; } @ManagedOperation(description="Add two numbers") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "x", description = "The first number"), - @ManagedOperationParameter(name = "y", description = "The second number")}) + @ManagedOperationParameter(name = "x", description = "The first number") + @ManagedOperationParameter(name = "y", description = "The second number") public int add(int x, int y) { return x + y; } @@ -109,36 +104,37 @@ used in xref:integration/jmx/exporting.adoc#jmx-exporting-mbeanserver[Creating a } ---- -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 +In the preceding example, you can see that the `AnnotationTestBean` class is annotated +with `@ManagedResource` and that this `@ManagedResource` annotation is configured +with a set of attributes. These attributes 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]. +detail later in xref:integration/jmx/interface.adoc#jmx-interface-metadata-types[Spring JMX Annotations]. -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. +Both the `age` and `name` properties are annotated with `@ManagedAttribute`, +but, in the case of the `age` property, only the getter method is annotated. This causes both of these properties to be included in the management interface -as attributes, but the `age` attribute is read-only. +as managed attributes, but the `age` attribute is read-only. -Finally, the `add(int, int)` method is marked with the `ManagedOperation` attribute, +Finally, the `add(int, int)` method is annotated with `@ManagedOperation`, whereas the `dontExposeMe()` method is not. This causes the management interface to contain only one operation (`add(int, int)`) when you use the `MetadataMBeanInfoAssembler`. +NOTE: The `AnnotationTestBean` class is not required to implement any Java interfaces, +since the JMX management interface is derived solely from annotations. + The following configuration shows how you can configure the `MBeanExporter` to use the `MetadataMBeanInfoAssembler`: [source,xml,indent=0,subs="verbatim,quotes"] ---- + - - @@ -151,102 +147,116 @@ The following configuration shows how you can configure the `MBeanExporter` to u + + + ---- -In the preceding example, an `MetadataMBeanInfoAssembler` bean has been configured with an +In the preceding example, a `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. +annotation-driven management interfaces for your Spring-exposed MBeans. [[jmx-interface-metadata-types]] -== Source-level Metadata Types +== Spring JMX Annotations -The following table describes the source-level metadata types that are available for use in Spring JMX: +The following table describes the annotations that are available for use in Spring JMX: [[jmx-metadata-types]] -.Source-level metadata types +.Spring JMX annotations +[cols="1,1,3"] |=== -| Purpose| Annotation| Annotation Type +| Annotation | Applies to | Description -| Mark all instances of a `Class` as JMX managed resources. | `@ManagedResource` -| Class +| Classes +| Marks all instances of a `Class` as JMX managed resources. -| Mark a method as a JMX operation. -| `@ManagedOperation` -| Method +| `@ManagedNotification` +| Classes +| Indicates a JMX notification emitted by a managed resource. -| Mark a getter or setter as one half of a JMX attribute. | `@ManagedAttribute` -| Method (only getters and setters) +| Methods (only getters and setters) +| Marks a getter or setter as one half of a JMX attribute. -| Define descriptions for operation parameters. -| `@ManagedOperationParameter` and `@ManagedOperationParameters` -| Method +| `@ManagedMetric` +| Methods (only getters) +| Marks a getter as a JMX attribute, with added descriptor properties to indicate that it is a metric. + +| `@ManagedOperation` +| Methods +| Marks a method as a JMX operation. + +| `@ManagedOperationParameter` +| Methods +| Defines a description for an operation parameter. |=== -The following table describes the configuration parameters that are available for use on these source-level -metadata types: +The following table describes some of the common attributes that are available for use in +these annotations. Consult the Javadoc for each annotation for further details. [[jmx-metadata-parameters]] -.Source-level metadata parameters -[cols="1,3,1"] +.Spring JMX annotation attributes +[cols="1,1,3"] |=== -| Parameter | Description | Applies to +| Attribute | Applies to | Description -| `ObjectName` +| `objectName` +| `@ManagedResource` | 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` +| `@ManagedResource`, `@ManagedNotification`, `@ManagedAttribute`, `@ManagedMetric`, + `@ManagedOperation`, `@ManagedOperationParameter` +| Sets the description of the resource, notification, attribute, metric, or operation. | `currencyTimeLimit` +| `@ManagedResource`, `@ManagedAttribute`, `@ManagedMetric` | Sets the value of the `currencyTimeLimit` descriptor field. -| `ManagedResource` or `ManagedAttribute` | `defaultValue` +| `@ManagedAttribute` | Sets the value of the `defaultValue` descriptor field. -| `ManagedAttribute` | `log` +| `@ManagedResource` | Sets the value of the `log` descriptor field. -| `ManagedResource` | `logFile` +| `@ManagedResource` | Sets the value of the `logFile` descriptor field. -| `ManagedResource` | `persistPolicy` +| `@ManagedResource`, `@ManagedMetric` | Sets the value of the `persistPolicy` descriptor field. -| `ManagedResource` | `persistPeriod` +| `@ManagedResource`, `@ManagedMetric` | Sets the value of the `persistPeriod` descriptor field. -| `ManagedResource` | `persistLocation` +| `@ManagedResource` | Sets the value of the `persistLocation` descriptor field. -| `ManagedResource` | `persistName` +| `@ManagedResource` | Sets the value of the `persistName` descriptor field. -| `ManagedResource` | `name` +| `@ManagedOperationParameter` | Sets the display name of an operation parameter. -| `ManagedOperationParameter` | `index` +| `@ManagedOperationParameter` | Sets the index of an operation parameter. -| `ManagedOperationParameter` |=== @@ -255,14 +265,14 @@ metadata types: 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 +interface to add support for auto-detection 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. +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: +bean name as the `ObjectName`, which results in configuration similar to the following: [source,xml,indent=0,subs="verbatim,quotes"] ---- @@ -274,26 +284,29 @@ bean name as the `ObjectName`, which results in a configuration similar to the f - - - - - + + + + + ---- 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]. +However, the `AnnotationTestBean` is still registered, since it is annotated with +`@ManagedResource` and the `MetadataMBeanInfoAssembler` detects this and votes to include +it. The only downside with this approach is that the name of the `AnnotationTestBean` now +has business meaning. You can address this issue by configuring an `ObjectNamingStrategy` +as explained in xref:integration/jmx/naming.adoc[Controlling `ObjectName` Instances for +Your Beans]. You can also see an example which uses the `MetadataNamingStrategy` in +xref:integration/jmx/interface.adoc#jmx-interface-metadata[Using Source-level Metadata: Java Annotations]. + [[jmx-interface-java]] diff --git a/spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java b/spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java index 26d2491e7d..99b75feabe 100644 --- a/spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java +++ b/spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2024 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. @@ -20,19 +20,15 @@ package org.springframework.jmx; * @author Rob Harrop * @author Juergen Hoeller */ -public interface IJmxTestBean { +public interface IJmxTestBean extends ITestBean { int add(int x, int y); long myOperation(); - int getAge(); - void setAge(int age); - void setName(String name) throws Exception; - - String getName(); + int getAge(); // used to test invalid methods that exist in the proxy interface void dontExposeMe(); diff --git a/spring-context/src/test/java/org/springframework/jmx/ITestBean.java b/spring-context/src/test/java/org/springframework/jmx/ITestBean.java new file mode 100644 index 0000000000..e452e3caf7 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/jmx/ITestBean.java @@ -0,0 +1,25 @@ +/* + * Copyright 2002-2024 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 + * + * https://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.jmx; + +public interface ITestBean { + + void setName(String name) throws Exception; + + String getName(); + +} diff --git a/spring-context/src/test/java/org/springframework/jmx/JmxTestBean.java b/spring-context/src/test/java/org/springframework/jmx/JmxTestBean.java index ccd3fb0c82..0082521cc9 100644 --- a/spring-context/src/test/java/org/springframework/jmx/JmxTestBean.java +++ b/spring-context/src/test/java/org/springframework/jmx/JmxTestBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2024 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. @@ -19,12 +19,6 @@ package org.springframework.jmx; import java.io.IOException; /** - * @@org.springframework.jmx.export.metadata.ManagedResource - * (description="My Managed Bean", objectName="spring:bean=test", - * log=true, logFile="build/jmx.log", currencyTimeLimit=15, persistPolicy="OnUpdate", - * persistPeriod=200, persistLocation="./foo", persistName="bar.jmx") - * @@org.springframework.jmx.export.metadata.ManagedNotification - * (name="My Notification", description="A Notification", notificationType="type.foo,type.bar") * @author Rob Harrop * @author Juergen Hoeller */ @@ -39,33 +33,21 @@ public class JmxTestBean implements IJmxTestBean { private boolean isSuperman; - /** - * @@org.springframework.jmx.export.metadata.ManagedAttribute - * (description="The Age Attribute", currencyTimeLimit=15) - */ + @Override + public void setAge(int age) { + this.age = age; + } + @Override public int getAge() { return age; } - @Override - public void setAge(int age) { - this.age = age; - } - - /** - * @@org.springframework.jmx.export.metadata.ManagedOperation(currencyTimeLimit=30) - */ @Override public long myOperation() { return 1L; } - /** - * @@org.springframework.jmx.export.metadata.ManagedAttribute - * (description="The Name Attribute", currencyTimeLimit=20, - * defaultValue="bar", persistPolicy="OnUpdate") - */ @Override public void setName(String name) throws Exception { if ("Juergen".equals(name)) { @@ -80,20 +62,11 @@ public class JmxTestBean implements IJmxTestBean { this.name = name; } - /** - * @@org.springframework.jmx.export.metadata.ManagedAttribute - * (defaultValue="foo", persistPeriod=300) - */ @Override public String getName() { return name; } - /** - * @@org.springframework.jmx.export.metadata.ManagedAttribute(description="The Nick - * Name - * Attribute") - */ public void setNickName(String nickName) { this.nickName = nickName; } @@ -106,30 +79,15 @@ public class JmxTestBean implements IJmxTestBean { this.isSuperman = superman; } - /** - * @@org.springframework.jmx.export.metadata.ManagedAttribute(description="The Is - * Superman - * Attribute") - */ public boolean isSuperman() { return isSuperman; } - /** - * @@org.springframework.jmx.export.metadata.ManagedOperation(description="Add Two - * Numbers - * Together") - * @@org.springframework.jmx.export.metadata.ManagedOperationParameter(index=0, name="x", description="Left operand") - * @@org.springframework.jmx.export.metadata.ManagedOperationParameter(index=1, name="y", description="Right operand") - */ @Override public int add(int x, int y) { return x + y; } - /** - * Test method that is not exposed by the MetadataAssembler. - */ @Override public void dontExposeMe() { throw new RuntimeException(); diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java index 9ca391f16e..8adecbd8d8 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java @@ -22,7 +22,7 @@ import javax.management.modelmbean.ModelMBeanOperationInfo; import org.junit.jupiter.api.Test; -import org.springframework.jmx.IJmxTestBean; +import org.springframework.jmx.ITestBean; import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests; import org.springframework.jmx.export.metadata.JmxAttributeSource; @@ -93,7 +93,7 @@ class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests { } @Override - protected IJmxTestBean createJmxTestBean() { + protected ITestBean createJmxTestBean() { return new AnnotationTestSubBean(); } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBean.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBean.java index db38feb2be..d3a5ddf368 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBean.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2024 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. @@ -16,7 +16,7 @@ package org.springframework.jmx.export.annotation; -import org.springframework.jmx.IJmxTestBean; +import org.springframework.jmx.ITestBean; import org.springframework.jmx.support.MetricType; import org.springframework.stereotype.Service; @@ -29,7 +29,7 @@ import org.springframework.stereotype.Service; logFile = "build/jmx.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200, persistLocation = "./foo", persistName = "bar.jmx") @ManagedNotification(name = "My Notification", notificationTypes = { "type.foo", "type.bar" }) -public class AnnotationTestBean implements IJmxTestBean { +public class AnnotationTestBean implements ITestBean { private String name; @@ -40,21 +40,13 @@ public class AnnotationTestBean implements IJmxTestBean { private boolean isSuperman; - @Override - @ManagedAttribute(description = "The Age Attribute", currencyTimeLimit = 15) - public int getAge() { - return age; - } - - @Override public void setAge(int age) { this.age = age; } - @Override - @ManagedOperation(currencyTimeLimit = 30) - public long myOperation() { - return 1L; + @ManagedAttribute(description = "The Age Attribute", currencyTimeLimit = 15) + public int getAge() { + return this.age; } @Override @@ -69,7 +61,7 @@ public class AnnotationTestBean implements IJmxTestBean { @Override @ManagedAttribute(defaultValue = "foo", persistPeriod = 300) public String getName() { - return name; + return this.name; } @ManagedAttribute(description = "The Nick Name Attribute") @@ -90,7 +82,11 @@ public class AnnotationTestBean implements IJmxTestBean { return isSuperman; } - @Override + @ManagedOperation(currencyTimeLimit = 30) + public long myOperation() { + return 1L; + } + @ManagedOperation(description = "Add Two Numbers Together") @ManagedOperationParameter(name="x", description="Left operand") @ManagedOperationParameter(name="y", description="Right operand") @@ -99,9 +95,8 @@ public class AnnotationTestBean implements IJmxTestBean { } /** - * Test method that is not exposed by the MetadataAssembler. + * Method that is not exposed by the MetadataAssembler. */ - @Override public void dontExposeMe() { throw new RuntimeException(); } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java index 814598b4d5..d33c300d64 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java @@ -17,7 +17,6 @@ package org.springframework.jmx.export.annotation; import org.springframework.beans.factory.FactoryBean; -import org.springframework.jmx.IJmxTestBean; /** * @author Juergen Hoeller @@ -36,7 +35,7 @@ public class AnnotationTestBeanFactory implements FactoryBean getObjectType() { + public Class getObjectType() { return FactoryCreatedAnnotationTestBean.class; } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java index fe29582805..2da809cbcd 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java @@ -18,10 +18,8 @@ package org.springframework.jmx.export.assembler; import javax.management.Attribute; import javax.management.Descriptor; -import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; -import javax.management.MBeanOperationInfo; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBeanAttributeInfo; @@ -31,7 +29,7 @@ import javax.management.modelmbean.ModelMBeanOperationInfo; import org.junit.jupiter.api.Test; import org.springframework.jmx.AbstractJmxTests; -import org.springframework.jmx.IJmxTestBean; +import org.springframework.jmx.ITestBean; import org.springframework.jmx.support.ObjectNameManager; import static org.assertj.core.api.Assertions.assertThat; @@ -48,76 +46,68 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests { protected abstract String getObjectName(); + @Test - void testMBeanRegistration() throws Exception { + void mBeanRegistration() throws Exception { // beans are registered at this point - just grab them from the server ObjectInstance instance = getObjectInstance(); assertThat(instance).as("Bean should not be null").isNotNull(); } @Test - void testRegisterOperations() throws Exception { - IJmxTestBean bean = getBean(); - assertThat(bean).isNotNull(); + void registerOperations() throws Exception { + assertThat(getBean()).isNotNull(); MBeanInfo inf = getMBeanInfo(); assertThat(inf.getOperations()).as("Incorrect number of operations registered").hasSize(getExpectedOperationCount()); } @Test - void testRegisterAttributes() throws Exception { - IJmxTestBean bean = getBean(); - assertThat(bean).isNotNull(); + void registerAttributes() throws Exception { + assertThat(getBean()).isNotNull(); MBeanInfo inf = getMBeanInfo(); assertThat(inf.getAttributes()).as("Incorrect number of attributes registered").hasSize(getExpectedAttributeCount()); } @Test - void testGetMBeanInfo() throws Exception { + void getMBeanAttributeInfo() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); assertThat(info).as("MBeanInfo should not be null").isNotNull(); + assertThat(info.getAttributes()) + .hasSize(getExpectedAttributeCount()) + .allSatisfy(element -> { + assertThat(element).as("MBeanAttributeInfo should not be null").isNotNull(); + assertThat(element.getDescription()).as("Description for MBeanAttributeInfo should not be null").isNotNull(); + }); } @Test - void testGetMBeanAttributeInfo() throws Exception { + void getMBeanOperationInfo() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); - MBeanAttributeInfo[] inf = info.getAttributes(); - assertThat(inf).as("Invalid number of Attributes returned").hasSize(getExpectedAttributeCount()); - - for (MBeanAttributeInfo element : inf) { - assertThat(element).as("MBeanAttributeInfo should not be null").isNotNull(); - assertThat(element.getDescription()).as("Description for MBeanAttributeInfo should not be null").isNotNull(); - } + assertThat(info).as("MBeanInfo should not be null").isNotNull(); + assertThat(info.getOperations()) + .hasSize(getExpectedOperationCount()) + .allSatisfy(element -> { + assertThat(element).as("MBeanOperationInfo should not be null").isNotNull(); + assertThat(element.getDescription()).as("Description for MBeanOperationInfo should not be null").isNotNull(); + }); } @Test - void testGetMBeanOperationInfo() throws Exception { - ModelMBeanInfo info = getMBeanInfoFromAssembler(); - MBeanOperationInfo[] inf = info.getOperations(); - assertThat(inf).as("Invalid number of Operations returned").hasSize(getExpectedOperationCount()); - - for (MBeanOperationInfo element : inf) { - assertThat(element).as("MBeanOperationInfo should not be null").isNotNull(); - assertThat(element.getDescription()).as("Description for MBeanOperationInfo should not be null").isNotNull(); - } - } - - @Test - void testDescriptionNotNull() throws Exception { + void descriptionNotNull() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); assertThat(info.getDescription()).as("The MBean description should not be null").isNotNull(); } @Test - void testSetAttribute() throws Exception { + void setAttribute() throws Exception { ObjectName objectName = ObjectNameManager.getInstance(getObjectName()); getServer().setAttribute(objectName, new Attribute(NAME_ATTRIBUTE, "Rob Harrop")); - IJmxTestBean bean = (IJmxTestBean) getContext().getBean("testBean"); - assertThat(bean.getName()).isEqualTo("Rob Harrop"); + assertThat(getBean().getName()).isEqualTo("Rob Harrop"); } @Test - void testGetAttribute() throws Exception { + void getAttribute() throws Exception { ObjectName objectName = ObjectNameManager.getInstance(getObjectName()); getBean().setName("John Smith"); Object val = getServer().getAttribute(objectName, NAME_ATTRIBUTE); @@ -125,7 +115,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests { } @Test - void testOperationInvocation() throws Exception{ + void operationInvocation() throws Exception{ ObjectName objectName = ObjectNameManager.getInstance(getObjectName()); Object result = getServer().invoke(objectName, "add", new Object[] {20, 30}, new String[] {"int", "int"}); @@ -133,7 +123,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests { } @Test - void testAttributeInfoHasDescriptors() throws Exception { + void attributeInfoHasDescriptors() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); ModelMBeanAttributeInfo attr = info.getAttribute(NAME_ATTRIBUTE); @@ -145,42 +135,35 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests { } @Test - void testAttributeHasCorrespondingOperations() throws Exception { + void attributeHasCorrespondingOperations() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); ModelMBeanOperationInfo get = info.getOperation("getName"); assertThat(get).as("get operation should not be null").isNotNull(); - assertThat(Integer.valueOf(4)).as("get operation should have visibility of four").isEqualTo(get.getDescriptor().getFieldValue("visibility")); + assertThat(get.getDescriptor().getFieldValue("visibility")).as("get operation should have visibility of four").isEqualTo(4); assertThat(get.getDescriptor().getFieldValue("role")).as("get operation should have role \"getter\"").isEqualTo("getter"); ModelMBeanOperationInfo set = info.getOperation("setName"); assertThat(set).as("set operation should not be null").isNotNull(); - assertThat(Integer.valueOf(4)).as("set operation should have visibility of four").isEqualTo(set.getDescriptor().getFieldValue("visibility")); + assertThat(set.getDescriptor().getFieldValue("visibility")).as("set operation should have visibility of four").isEqualTo(4); assertThat(set.getDescriptor().getFieldValue("role")).as("set operation should have role \"setter\"").isEqualTo("setter"); } @Test - void testNotificationMetadata() throws Exception { + void notificationMetadata() throws Exception { ModelMBeanInfo info = (ModelMBeanInfo) getMBeanInfo(); MBeanNotificationInfo[] notifications = info.getNotifications(); assertThat(notifications).as("Incorrect number of notifications").hasSize(1); assertThat(notifications[0].getName()).as("Incorrect notification name").isEqualTo("My Notification"); - - String[] notifTypes = notifications[0].getNotifTypes(); - - assertThat(notifTypes).as("Incorrect number of notification types").hasSize(2); - assertThat(notifTypes[0]).as("Notification type.foo not found").isEqualTo("type.foo"); - assertThat(notifTypes[1]).as("Notification type.bar not found").isEqualTo("type.bar"); + assertThat(notifications[0].getNotifTypes()).as("notification types").containsExactly("type.foo", "type.bar"); } protected ModelMBeanInfo getMBeanInfoFromAssembler() throws Exception { - IJmxTestBean bean = getBean(); - return getAssembler().getMBeanInfo(bean, getObjectName()); + return getAssembler().getMBeanInfo(getBean(), getObjectName()); } - protected IJmxTestBean getBean() { - Object bean = getContext().getBean("testBean"); - return (IJmxTestBean) bean; + protected ITestBean getBean() { + return getContext().getBean("testBean", ITestBean.class); } protected MBeanInfo getMBeanInfo() throws Exception { diff --git a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java index 31c9f7fd66..8c96293dc3 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.Test; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.testfixture.interceptor.NopInterceptor; -import org.springframework.jmx.IJmxTestBean; +import org.springframework.jmx.ITestBean; import org.springframework.jmx.JmxTestBean; import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.metadata.JmxAttributeSource; @@ -156,7 +156,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble @Test void testWithCglibProxy() throws Exception { - IJmxTestBean tb = createJmxTestBean(); + Object tb = createJmxTestBean(); ProxyFactory pf = new ProxyFactory(); pf.setTarget(tb); pf.addAdvice(new NopInterceptor()); @@ -230,7 +230,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble return 9; } - protected IJmxTestBean createJmxTestBean() { + protected ITestBean createJmxTestBean() { return new JmxTestBean(); }