Skip to content

Commit 8f6a42b

Browse files
author
Rob Harrop
committed
[SPR-3635] [SPR-5039] [SPR-5813] JMX annotation inheritance fixed
1 parent 7f7173f commit 8f6a42b

File tree

10 files changed

+177
-11
lines changed

10 files changed

+177
-11
lines changed

build.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ivy.cache.dir=${basedir}/../ivy-cache
77
integration.repo.dir=${basedir}/../integration-repo
88
javadoc.exclude.package.names=org/springframework/samples/**
99
javadoc.max.memory=256M
10-
test.vm.args=-XX:MaxPermSize=128M
10+
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
1111
compiler.args=-enableJavadoc -warn:none
1212

1313
# For when releasing

org.springframework.beans/src/test/java/test/beans/GenericBean.java

-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ public void setCustomEnum(CustomEnum customEnum) {
225225
this.customEnum = customEnum;
226226
}
227227

228-
229228
public static GenericBean createInstance(Set<Integer> integerSet) {
230229
return new GenericBean(integerSet);
231230
}

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMeta
6363

6464
public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
6565
org.springframework.jmx.export.annotation.ManagedAttribute ann =
66-
AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class);
66+
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class);
6767
if (ann == null) {
6868
return null;
6969
}
@@ -77,7 +77,7 @@ public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadat
7777

7878
public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
7979
org.springframework.jmx.export.annotation.ManagedMetric ann =
80-
AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class);
80+
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class);
8181
if (ann == null) {
8282
return null;
8383
}
@@ -92,7 +92,7 @@ public ManagedOperation getManagedOperation(Method method) throws InvalidMetadat
9292
throw new InvalidMetadataException(
9393
"The ManagedOperation attribute is not valid for JavaBean properties. Use ManagedAttribute instead.");
9494
}
95-
Annotation ann = AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class);
95+
Annotation ann = AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class);
9696
if (ann == null) {
9797
return null;
9898
}
@@ -104,7 +104,7 @@ public ManagedOperation getManagedOperation(Method method) throws InvalidMetadat
104104
public ManagedOperationParameter[] getManagedOperationParameters(Method method)
105105
throws InvalidMetadataException {
106106

107-
ManagedOperationParameters params = AnnotationUtils.getAnnotation(method, ManagedOperationParameters.class);
107+
ManagedOperationParameters params = AnnotationUtils.findAnnotation(method, ManagedOperationParameters.class);
108108
ManagedOperationParameter[] result = null;
109109
if (params == null) {
110110
result = new ManagedOperationParameter[0];

org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java

+28-4
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,32 @@
1616

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

19+
import javax.management.modelmbean.ModelMBeanInfo;
20+
import javax.management.modelmbean.ModelMBeanAttributeInfo;
21+
import javax.management.modelmbean.ModelMBeanOperationInfo;
22+
1923
import org.springframework.jmx.IJmxTestBean;
2024
import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests;
2125
import org.springframework.jmx.export.metadata.JmxAttributeSource;
2226

23-
/**
24-
* @author Rob Harrop
25-
*/
27+
/** @author Rob Harrop */
2628
public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests {
2729

2830
private static final String OBJECT_NAME = "bean:name=testBean4";
2931

32+
public void testAttributeFromInterface() throws Exception {
33+
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
34+
ModelMBeanAttributeInfo attr = inf.getAttribute("Colour");
35+
assertTrue("The name attribute should be writable", attr.isWritable());
36+
assertTrue("The name attribute should be readable", attr.isReadable());
37+
}
38+
39+
public void testOperationFromInterface() throws Exception {
40+
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
41+
ModelMBeanOperationInfo op = inf.getOperation("fromInterface");
42+
assertNotNull(op);
43+
}
44+
3045
protected JmxAttributeSource getAttributeSource() {
3146
return new AnnotationJmxAttributeSource();
3247
}
@@ -36,11 +51,20 @@ protected String getObjectName() {
3651
}
3752

3853
protected IJmxTestBean createJmxTestBean() {
39-
return new AnnotationTestBean();
54+
return new AnnotationTestSubBean();
4055
}
4156

4257
protected String getApplicationContextPath() {
4358
return "org/springframework/jmx/export/annotation/annotations.xml";
4459
}
4560

61+
@Override
62+
protected int getExpectedAttributeCount() {
63+
return super.getExpectedAttributeCount() + 1;
64+
}
65+
66+
@Override
67+
protected int getExpectedOperationCount() {
68+
return super.getExpectedOperationCount() + 3;
69+
}
4670
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.jmx.export.annotation;
18+
19+
/**
20+
* @author Rob Harrop
21+
*/
22+
public class AnnotationTestSubBean extends AnnotationTestBean implements IAnnotationTestBean {
23+
24+
private String colour;
25+
26+
@Override
27+
public long myOperation() {
28+
return 123L;
29+
}
30+
31+
@Override
32+
public void setAge(int age) {
33+
super.setAge(age);
34+
}
35+
36+
@Override
37+
public int getAge() {
38+
return super.getAge();
39+
}
40+
41+
public String getColour() {
42+
return this.colour;
43+
}
44+
45+
public void setColour(String colour) {
46+
this.colour = colour;
47+
}
48+
49+
public void fromInterface() {
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.jmx.export.annotation;
18+
19+
/**
20+
* @author Rob Harrop
21+
*/
22+
public interface IAnnotationTestBean {
23+
24+
@ManagedAttribute
25+
String getColour();
26+
27+
@ManagedAttribute
28+
void setColour(String colour);
29+
30+
@ManagedOperation
31+
void fromInterface();
32+
}

org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/annotations.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</property>
2020
</bean>
2121

22-
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestBean">
22+
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestSubBean">
2323
<property name="name">
2424
<value>TEST</value>
2525
</property>

org.springframework.context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.HashMap;
2020
import java.util.Map;
21+
import java.util.Arrays;
2122

2223
import javax.management.Descriptor;
2324
import javax.management.MBeanInfo;

org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

+24
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ public static <A extends Annotation> A getAnnotation(Method method, Class<A> ann
101101
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
102102
A annotation = getAnnotation(method, annotationType);
103103
Class<?> cl = method.getDeclaringClass();
104+
if(annotation == null) {
105+
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
106+
}
104107
while (annotation == null) {
105108
cl = cl.getSuperclass();
106109
if (cl == null || cl == Object.class) {
@@ -109,6 +112,9 @@ public static <A extends Annotation> A findAnnotation(Method method, Class<A> an
109112
try {
110113
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
111114
annotation = getAnnotation(equivalentMethod, annotationType);
115+
if(annotation == null) {
116+
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
117+
}
112118
}
113119
catch (NoSuchMethodException ex) {
114120
// We're done...
@@ -117,6 +123,24 @@ public static <A extends Annotation> A findAnnotation(Method method, Class<A> an
117123
return annotation;
118124
}
119125

126+
private static <A extends Annotation> A searchForAnnotationOnInterfaces(Method method, Class<A> annotationType, Class[] ifaces) {
127+
A annotation = null;
128+
for (Class<?> iface : ifaces) {
129+
Method equivalentMethod = null;
130+
try {
131+
equivalentMethod = iface.getDeclaredMethod(method.getName(), method.getParameterTypes());
132+
annotation = getAnnotation(equivalentMethod, annotationType);
133+
}
134+
catch (NoSuchMethodException e) {
135+
// skip this interface - it doesn't have the method
136+
}
137+
if (annotation != null) {
138+
break;
139+
}
140+
}
141+
return annotation;
142+
}
143+
120144
/**
121145
* Find a single {@link Annotation} of <code>annotationType</code> from the
122146
* supplied {@link Class}, traversing its interfaces and super classes

org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java

+35
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ public void testGetDefaultValueFromAnnotationType() throws Exception {
188188
assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(Order.class));
189189
}
190190

191+
@Test
192+
public void testFindAnnotationFromInterface() throws Exception {
193+
194+
Method method = ImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
195+
Order order = findAnnotation(method, Order.class);
196+
assertNotNull(order);
197+
}
198+
199+
@Test
200+
public void testFindAnnotationFromInterfaceOnSuper() throws Exception {
201+
202+
Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
203+
Order order = findAnnotation(method, Order.class);
204+
assertNotNull(order);
205+
}
206+
191207
public static interface AnnotatedInterface {
192208

193209
@Order(0)
@@ -286,6 +302,25 @@ public static class NonInheritedAnnotationClass {
286302
public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass {
287303
}
288304

305+
306+
public static interface InterfaceWithAnnotatedMethod {
307+
308+
@Order
309+
void foo();
310+
}
311+
312+
public static class ImplementsInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod {
313+
314+
public void foo() {
315+
}
316+
}
317+
318+
public static class SubOfImplementsInterfaceWithAnnotatedMethod extends ImplementsInterfaceWithAnnotatedMethod {
319+
320+
public void foo() {
321+
}
322+
}
323+
289324
}
290325

291326
@Retention(RetentionPolicy.RUNTIME)

0 commit comments

Comments
 (0)