[SPR-3635] [SPR-5039] [SPR-5813] JMX annotation inheritance fixed
This commit is contained in:
parent
7f7173f790
commit
8f6a42bf64
|
@ -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
|
||||
|
|
|
@ -225,7 +225,6 @@ public class GenericBean<T> {
|
|||
this.customEnum = customEnum;
|
||||
}
|
||||
|
||||
|
||||
public static GenericBean createInstance(Set<Integer> integerSet) {
|
||||
return new GenericBean(integerSet);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue