[SPR-3635] [SPR-5039] [SPR-5813] JMX annotation inheritance fixed

This commit is contained in:
Rob Harrop 2009-09-08 21:37:02 +00:00
parent 7f7173f790
commit 8f6a42bf64
10 changed files with 177 additions and 11 deletions

View File

@ -7,7 +7,7 @@ ivy.cache.dir=${basedir}/../ivy-cache
integration.repo.dir=${basedir}/../integration-repo
javadoc.exclude.package.names=org/springframework/samples/**
javadoc.max.memory=256M
test.vm.args=-XX:MaxPermSize=128M
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
compiler.args=-enableJavadoc -warn:none
# For when releasing

View File

@ -225,7 +225,6 @@ public class GenericBean<T> {
this.customEnum = customEnum;
}
public static GenericBean createInstance(Set<Integer> integerSet) {
return new GenericBean(integerSet);
}

View File

@ -63,7 +63,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
org.springframework.jmx.export.annotation.ManagedAttribute ann =
AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class);
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class);
if (ann == null) {
return null;
}
@ -77,7 +77,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
org.springframework.jmx.export.annotation.ManagedMetric ann =
AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class);
AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class);
if (ann == null) {
return null;
}
@ -92,7 +92,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
throw new InvalidMetadataException(
"The ManagedOperation attribute is not valid for JavaBean properties. Use ManagedAttribute instead.");
}
Annotation ann = AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class);
Annotation ann = AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class);
if (ann == null) {
return null;
}
@ -104,7 +104,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
public ManagedOperationParameter[] getManagedOperationParameters(Method method)
throws InvalidMetadataException {
ManagedOperationParameters params = AnnotationUtils.getAnnotation(method, ManagedOperationParameters.class);
ManagedOperationParameters params = AnnotationUtils.findAnnotation(method, ManagedOperationParameters.class);
ManagedOperationParameter[] result = null;
if (params == null) {
result = new ManagedOperationParameter[0];

View File

@ -16,17 +16,32 @@
package org.springframework.jmx.export.annotation;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import org.springframework.jmx.IJmxTestBean;
import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
/**
* @author Rob Harrop
*/
/** @author Rob Harrop */
public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests {
private static final String OBJECT_NAME = "bean:name=testBean4";
public void testAttributeFromInterface() throws Exception {
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
ModelMBeanAttributeInfo attr = inf.getAttribute("Colour");
assertTrue("The name attribute should be writable", attr.isWritable());
assertTrue("The name attribute should be readable", attr.isReadable());
}
public void testOperationFromInterface() throws Exception {
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
ModelMBeanOperationInfo op = inf.getOperation("fromInterface");
assertNotNull(op);
}
protected JmxAttributeSource getAttributeSource() {
return new AnnotationJmxAttributeSource();
}
@ -36,11 +51,20 @@ public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerT
}
protected IJmxTestBean createJmxTestBean() {
return new AnnotationTestBean();
return new AnnotationTestSubBean();
}
protected String getApplicationContextPath() {
return "org/springframework/jmx/export/annotation/annotations.xml";
}
@Override
protected int getExpectedAttributeCount() {
return super.getExpectedAttributeCount() + 1;
}
@Override
protected int getExpectedOperationCount() {
return super.getExpectedOperationCount() + 3;
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2002-2009 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
*
* http://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.export.annotation;
/**
* @author Rob Harrop
*/
public class AnnotationTestSubBean extends AnnotationTestBean implements IAnnotationTestBean {
private String colour;
@Override
public long myOperation() {
return 123L;
}
@Override
public void setAge(int age) {
super.setAge(age);
}
@Override
public int getAge() {
return super.getAge();
}
public String getColour() {
return this.colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public void fromInterface() {
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2002-2009 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
*
* http://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.export.annotation;
/**
* @author Rob Harrop
*/
public interface IAnnotationTestBean {
@ManagedAttribute
String getColour();
@ManagedAttribute
void setColour(String colour);
@ManagedOperation
void fromInterface();
}

View File

@ -19,7 +19,7 @@
</property>
</bean>
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestBean">
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestSubBean">
<property name="name">
<value>TEST</value>
</property>

View File

@ -18,6 +18,7 @@ package org.springframework.jmx.export.assembler;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import javax.management.Descriptor;
import javax.management.MBeanInfo;

View File

@ -101,6 +101,9 @@ public abstract class AnnotationUtils {
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
A annotation = getAnnotation(method, annotationType);
Class<?> cl = method.getDeclaringClass();
if(annotation == null) {
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
}
while (annotation == null) {
cl = cl.getSuperclass();
if (cl == null || cl == Object.class) {
@ -109,6 +112,9 @@ public abstract class AnnotationUtils {
try {
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
annotation = getAnnotation(equivalentMethod, annotationType);
if(annotation == null) {
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
}
}
catch (NoSuchMethodException ex) {
// We're done...
@ -117,6 +123,24 @@ public abstract class AnnotationUtils {
return annotation;
}
private static <A extends Annotation> A searchForAnnotationOnInterfaces(Method method, Class<A> annotationType, Class[] ifaces) {
A annotation = null;
for (Class<?> iface : ifaces) {
Method equivalentMethod = null;
try {
equivalentMethod = iface.getDeclaredMethod(method.getName(), method.getParameterTypes());
annotation = getAnnotation(equivalentMethod, annotationType);
}
catch (NoSuchMethodException e) {
// skip this interface - it doesn't have the method
}
if (annotation != null) {
break;
}
}
return annotation;
}
/**
* Find a single {@link Annotation} of <code>annotationType</code> from the
* supplied {@link Class}, traversing its interfaces and super classes

View File

@ -188,6 +188,22 @@ public class AnnotationUtilsTests {
assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(Order.class));
}
@Test
public void testFindAnnotationFromInterface() throws Exception {
Method method = ImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
Order order = findAnnotation(method, Order.class);
assertNotNull(order);
}
@Test
public void testFindAnnotationFromInterfaceOnSuper() throws Exception {
Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
Order order = findAnnotation(method, Order.class);
assertNotNull(order);
}
public static interface AnnotatedInterface {
@Order(0)
@ -286,6 +302,25 @@ public class AnnotationUtilsTests {
public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass {
}
public static interface InterfaceWithAnnotatedMethod {
@Order
void foo();
}
public static class ImplementsInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod {
public void foo() {
}
}
public static class SubOfImplementsInterfaceWithAnnotatedMethod extends ImplementsInterfaceWithAnnotatedMethod {
public void foo() {
}
}
}
@Retention(RetentionPolicy.RUNTIME)