Skip to content

Commit 3aefc96

Browse files
committed
@ManagedOperationParameter declares @Target/@Retention/@Documented/@repeatable now
This also turns @ManagedNotification into a repeatable annotation and consistently applies findAnnotation/getRepeatableAnnotations. Issue: SPR-13700
1 parent 0524f3a commit 3aefc96

File tree

10 files changed

+94
-97
lines changed

10 files changed

+94
-97
lines changed

spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java

Lines changed: 48 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,32 @@
1717
package org.springframework.jmx.export.annotation;
1818

1919
import java.lang.annotation.Annotation;
20+
import java.lang.reflect.Array;
2021
import java.lang.reflect.Method;
22+
import java.util.Collection;
23+
import java.util.Set;
2124

25+
import org.springframework.beans.BeanUtils;
2226
import org.springframework.beans.annotation.AnnotationBeanUtils;
2327
import org.springframework.beans.factory.BeanFactory;
2428
import org.springframework.beans.factory.BeanFactoryAware;
2529
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2630
import org.springframework.core.annotation.AnnotationUtils;
2731
import org.springframework.jmx.export.metadata.InvalidMetadataException;
2832
import org.springframework.jmx.export.metadata.JmxAttributeSource;
29-
import org.springframework.jmx.export.metadata.ManagedAttribute;
30-
import org.springframework.jmx.export.metadata.ManagedMetric;
31-
import org.springframework.jmx.export.metadata.ManagedNotification;
32-
import org.springframework.jmx.export.metadata.ManagedOperation;
33-
import org.springframework.jmx.export.metadata.ManagedOperationParameter;
34-
import org.springframework.jmx.export.metadata.ManagedResource;
3533
import org.springframework.util.StringValueResolver;
3634

3735
/**
3836
* Implementation of the {@code JmxAttributeSource} interface that
39-
* reads JDK 1.5+ annotations and exposes the corresponding attributes.
37+
* reads annotations and exposes the corresponding attributes.
4038
*
4139
* @author Rob Harrop
4240
* @author Juergen Hoeller
4341
* @author Jennifer Hickey
4442
* @since 1.2
45-
* @see org.springframework.jmx.export.annotation.ManagedResource
46-
* @see org.springframework.jmx.export.annotation.ManagedAttribute
47-
* @see org.springframework.jmx.export.annotation.ManagedOperation
43+
* @see ManagedResource
44+
* @see ManagedAttribute
45+
* @see ManagedOperation
4846
*/
4947
public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFactoryAware {
5048

@@ -66,25 +64,23 @@ public String resolveStringValue(String strVal) {
6664
}
6765

6866
@Override
69-
public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
70-
org.springframework.jmx.export.annotation.ManagedResource ann =
71-
AnnotationUtils.getAnnotation(beanClass, org.springframework.jmx.export.annotation.ManagedResource.class);
67+
public org.springframework.jmx.export.metadata.ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
68+
ManagedResource ann = AnnotationUtils.findAnnotation(beanClass, ManagedResource.class);
7269
if (ann == null) {
7370
return null;
7471
}
75-
ManagedResource managedResource = new ManagedResource();
72+
org.springframework.jmx.export.metadata.ManagedResource managedResource = new org.springframework.jmx.export.metadata.ManagedResource();
7673
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.embeddedValueResolver);
7774
return managedResource;
7875
}
7976

8077
@Override
81-
public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
82-
org.springframework.jmx.export.annotation.ManagedAttribute ann =
83-
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class);
78+
public org.springframework.jmx.export.metadata.ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
79+
ManagedAttribute ann = AnnotationUtils.findAnnotation(method, ManagedAttribute.class);
8480
if (ann == null) {
8581
return null;
8682
}
87-
ManagedAttribute managedAttribute = new ManagedAttribute();
83+
org.springframework.jmx.export.metadata.ManagedAttribute managedAttribute = new org.springframework.jmx.export.metadata.ManagedAttribute();
8884
AnnotationBeanUtils.copyPropertiesToBean(ann, managedAttribute, "defaultValue");
8985
if (ann.defaultValue().length() > 0) {
9086
managedAttribute.setDefaultValue(ann.defaultValue());
@@ -93,65 +89,53 @@ public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadat
9389
}
9490

9591
@Override
96-
public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
97-
org.springframework.jmx.export.annotation.ManagedMetric ann =
98-
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class);
99-
if (ann == null) {
100-
return null;
101-
}
102-
ManagedMetric managedMetric = new ManagedMetric();
103-
AnnotationBeanUtils.copyPropertiesToBean(ann, managedMetric);
104-
return managedMetric;
92+
public org.springframework.jmx.export.metadata.ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
93+
ManagedMetric ann = AnnotationUtils.findAnnotation(method, ManagedMetric.class);
94+
return copyPropertiesToBean(ann, org.springframework.jmx.export.metadata.ManagedMetric.class);
10595
}
10696

10797
@Override
108-
public ManagedOperation getManagedOperation(Method method) throws InvalidMetadataException {
109-
Annotation ann = AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class);
110-
if (ann == null) {
111-
return null;
112-
}
113-
ManagedOperation op = new ManagedOperation();
114-
AnnotationBeanUtils.copyPropertiesToBean(ann, op);
115-
return op;
98+
public org.springframework.jmx.export.metadata.ManagedOperation getManagedOperation(Method method) throws InvalidMetadataException {
99+
ManagedOperation ann = AnnotationUtils.findAnnotation(method, ManagedOperation.class);
100+
return copyPropertiesToBean(ann, org.springframework.jmx.export.metadata.ManagedOperation.class);
116101
}
117102

118103
@Override
119-
public ManagedOperationParameter[] getManagedOperationParameters(Method method)
104+
public org.springframework.jmx.export.metadata.ManagedOperationParameter[] getManagedOperationParameters(Method method)
120105
throws InvalidMetadataException {
121106

122-
ManagedOperationParameters params = AnnotationUtils.findAnnotation(method, ManagedOperationParameters.class);
123-
ManagedOperationParameter[] result = null;
124-
if (params == null) {
125-
result = new ManagedOperationParameter[0];
126-
}
127-
else {
128-
Annotation[] paramData = params.value();
129-
result = new ManagedOperationParameter[paramData.length];
130-
for (int i = 0; i < paramData.length; i++) {
131-
Annotation annotation = paramData[i];
132-
ManagedOperationParameter managedOperationParameter = new ManagedOperationParameter();
133-
AnnotationBeanUtils.copyPropertiesToBean(annotation, managedOperationParameter);
134-
result[i] = managedOperationParameter;
135-
}
136-
}
137-
return result;
107+
Set<ManagedOperationParameter> anns = AnnotationUtils.getRepeatableAnnotations(
108+
method, ManagedOperationParameter.class, ManagedOperationParameters.class);
109+
return copyPropertiesToBeanArray(anns, org.springframework.jmx.export.metadata.ManagedOperationParameter.class);
138110
}
139111

140112
@Override
141-
public ManagedNotification[] getManagedNotifications(Class<?> clazz) throws InvalidMetadataException {
142-
ManagedNotifications notificationsAnn = AnnotationUtils.getAnnotation(clazz, ManagedNotifications.class);
143-
if (notificationsAnn == null) {
144-
return new ManagedNotification[0];
113+
public org.springframework.jmx.export.metadata.ManagedNotification[] getManagedNotifications(Class<?> clazz)
114+
throws InvalidMetadataException {
115+
116+
Set<ManagedNotification> anns = AnnotationUtils.getRepeatableAnnotations(
117+
clazz, ManagedNotification.class, ManagedNotifications.class);
118+
return copyPropertiesToBeanArray(anns, org.springframework.jmx.export.metadata.ManagedNotification.class);
119+
}
120+
121+
122+
@SuppressWarnings("unchecked")
123+
private static <T> T[] copyPropertiesToBeanArray(Collection<? extends Annotation> anns, Class<T> beanClass) {
124+
T[] beans = (T[]) Array.newInstance(beanClass, anns.size());
125+
int i = 0;
126+
for (Annotation ann : anns) {
127+
beans[i++] = copyPropertiesToBean(ann, beanClass);
145128
}
146-
Annotation[] notifications = notificationsAnn.value();
147-
ManagedNotification[] result = new ManagedNotification[notifications.length];
148-
for (int i = 0; i < notifications.length; i++) {
149-
Annotation notification = notifications[i];
150-
ManagedNotification managedNotification = new ManagedNotification();
151-
AnnotationBeanUtils.copyPropertiesToBean(notification, managedNotification);
152-
result[i] = managedNotification;
129+
return beans;
130+
}
131+
132+
private static <T> T copyPropertiesToBean(Annotation ann, Class<T> beanClass) {
133+
if (ann == null) {
134+
return null;
153135
}
154-
return result;
136+
T bean = BeanUtils.instantiate(beanClass);
137+
AnnotationBeanUtils.copyPropertiesToBean(ann, bean);
138+
return bean;
155139
}
156140

157141
}

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedAttribute.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2005 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,8 +23,8 @@
2323
import java.lang.annotation.Target;
2424

2525
/**
26-
* JDK 1.5+ method-level annotation that indicates to expose a given bean
27-
* property as JMX attribute, corresponding to the ManagedAttribute attribute.
26+
* Method-level annotation that indicates to expose a given bean property as a
27+
* JMX attribute, corresponding to the {@code ManagedAttribute} attribute.
2828
* Only valid when used on a JavaBean getter or setter.
2929
*
3030
* @author Rob Harrop

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedMetric.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,9 +25,9 @@
2525
import org.springframework.jmx.support.MetricType;
2626

2727
/**
28-
* JDK 1.5+ method-level annotation that indicates to expose a given bean
29-
* property as JMX attribute, with added Descriptor properties to indicate that
30-
* it is a metric. Only valid when used on a JavaBean getter.
28+
* Method-level annotation that indicates to expose a given bean property as a
29+
* JMX attribute, with added descriptor properties to indicate that it is a metric.
30+
* Only valid when used on a JavaBean getter.
3131
*
3232
* @author Jennifer Hickey
3333
* @since 3.0

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedNotification.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,13 +19,15 @@
1919
import java.lang.annotation.Documented;
2020
import java.lang.annotation.ElementType;
2121
import java.lang.annotation.Inherited;
22+
import java.lang.annotation.Repeatable;
2223
import java.lang.annotation.Retention;
2324
import java.lang.annotation.RetentionPolicy;
2425
import java.lang.annotation.Target;
2526

2627
/**
27-
* JDK 1.5+ method-level annotation that indicates a JMX notification
28-
* emitted by a bean.
28+
* Type-level annotation that indicates a JMX notification emitted by a bean.
29+
*
30+
* <p>As of Spring Framework 4.2.4, this annotation is declared as repeatable.
2931
*
3032
* @author Rob Harrop
3133
* @since 2.0
@@ -35,6 +37,7 @@
3537
@Retention(RetentionPolicy.RUNTIME)
3638
@Inherited
3739
@Documented
40+
@Repeatable(ManagedNotifications.class)
3841
public @interface ManagedNotification {
3942

4043
String name();

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedNotifications.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,8 +24,8 @@
2424
import java.lang.annotation.Target;
2525

2626
/**
27-
* JDK 1.5+ method-level annotation that indicates JMX notifications emitted by
28-
* a bean, containing multiple {@link ManagedNotification ManagedNotifications}
27+
* Type-level annotation that indicates JMX notifications emitted by a bean,
28+
* containing multiple {@link ManagedNotification ManagedNotifications}
2929
*
3030
* @author Rob Harrop
3131
* @since 2.0

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedOperation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2005 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,8 +23,8 @@
2323
import java.lang.annotation.Target;
2424

2525
/**
26-
* JDK 1.5+ method-level annotation that indicates to expose a given method
27-
* as JMX operation, corresponding to the ManagedOperation attribute.
26+
* Method-level annotation that indicates to expose a given method as a
27+
* JMX operation, corresponding to the {@code ManagedOperation} attribute.
2828
* Only valid when used on a method that is not a JavaBean getter or setter.
2929
*
3030
* @author Rob Harrop

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedOperationParameter.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,16 +16,29 @@
1616

1717
package org.springframework.jmx.export.annotation;
1818

19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Repeatable;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
1926
/**
20-
* JDK 1.5+ method-level annotation used to provide metadata about operation
21-
* parameters, corresponding to a {@code ManagedOperationParameter} attribute.
22-
* Used as part of a {@code ManagedOperationParameters} annotation.
27+
* Method-level annotation used to provide metadata about operation parameters,
28+
* corresponding to a {@code ManagedOperationParameter} attribute.
29+
* Used as part of a {@link ManagedOperationParameters} annotation.
30+
*
31+
* <p>As of Spring Framework 4.2.4, this annotation is declared as repeatable.
2332
*
2433
* @author Rob Harrop
2534
* @since 1.2
2635
* @see ManagedOperationParameters#value
2736
* @see org.springframework.jmx.export.metadata.ManagedOperationParameter
2837
*/
38+
@Target(ElementType.METHOD)
39+
@Retention(RetentionPolicy.RUNTIME)
40+
@Documented
41+
@Repeatable(ManagedOperationParameters.class)
2942
public @interface ManagedOperationParameter {
3043

3144
String name();

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedOperationParameters.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,9 +23,8 @@
2323
import java.lang.annotation.Target;
2424

2525
/**
26-
* JDK 1.5+ method-level annotation used to provide metadata about
27-
* operation parameters, corresponding to an array of
28-
* {@code ManagedOperationParameter} attributes.
26+
* Method-level annotation used to provide metadata about operation parameters,
27+
* corresponding to an array of {@code ManagedOperationParameter} attributes.
2928
*
3029
* @author Rob Harrop
3130
* @since 1.2

spring-context/src/main/java/org/springframework/jmx/export/annotation/ManagedResource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
import org.springframework.core.annotation.AliasFor;
2727

2828
/**
29-
* JDK 1.5+ class-level annotation that indicates to register instances of a
30-
* class with a JMX server, corresponding to the ManagedResource attribute.
29+
* Class-level annotation that indicates to register instances of a class
30+
* with a JMX server, corresponding to the {@code ManagedResource} attribute.
3131
*
3232
* <p><b>Note:</b> This annotation is marked as inherited, allowing for generic
3333
* management-aware base classes. In such a scenario, it is recommended to

spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBean.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
55
* use this file except in compliance with the License. You may obtain a copy of
@@ -28,7 +28,7 @@
2828
@ManagedResource(objectName = "bean:name=testBean4", description = "My Managed Bean", log = true,
2929
logFile = "jmx.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200,
3030
persistLocation = "./foo", persistName = "bar.jmx")
31-
@ManagedNotifications({@ManagedNotification(name="My Notification", notificationTypes={"type.foo", "type.bar"})})
31+
@ManagedNotification(name="My Notification", notificationTypes={"type.foo", "type.bar"})
3232
public class AnnotationTestBean implements IJmxTestBean {
3333

3434
private String name;
@@ -91,9 +91,9 @@ public boolean isSuperman() {
9191
}
9292

9393
@Override
94-
@org.springframework.jmx.export.annotation.ManagedOperation(description = "Add Two Numbers Together")
95-
@ManagedOperationParameters({@ManagedOperationParameter(name="x", description="Left operand"),
96-
@ManagedOperationParameter(name="y", description="Right operand")})
94+
@ManagedOperation(description = "Add Two Numbers Together")
95+
@ManagedOperationParameter(name="x", description="Left operand")
96+
@ManagedOperationParameter(name="y", description="Right operand")
9797
public int add(int x, int y) {
9898
return x + y;
9999
}
@@ -117,6 +117,4 @@ public int getCacheEntries() {
117117
return 3;
118118
}
119119

120-
121-
122120
}

0 commit comments

Comments
 (0)