[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
|
integration.repo.dir=${basedir}/../integration-repo
|
||||||
javadoc.exclude.package.names=org/springframework/samples/**
|
javadoc.exclude.package.names=org/springframework/samples/**
|
||||||
javadoc.max.memory=256M
|
javadoc.max.memory=256M
|
||||||
test.vm.args=-XX:MaxPermSize=128M
|
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
|
||||||
compiler.args=-enableJavadoc -warn:none
|
compiler.args=-enableJavadoc -warn:none
|
||||||
|
|
||||||
# For when releasing
|
# For when releasing
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,6 @@ public class GenericBean<T> {
|
||||||
this.customEnum = customEnum;
|
this.customEnum = customEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static GenericBean createInstance(Set<Integer> integerSet) {
|
public static GenericBean createInstance(Set<Integer> integerSet) {
|
||||||
return new GenericBean(integerSet);
|
return new GenericBean(integerSet);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
||||||
|
|
||||||
public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
|
public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
|
||||||
org.springframework.jmx.export.annotation.ManagedAttribute ann =
|
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) {
|
if (ann == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
||||||
|
|
||||||
public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
|
public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
|
||||||
org.springframework.jmx.export.annotation.ManagedMetric ann =
|
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) {
|
if (ann == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
||||||
throw new InvalidMetadataException(
|
throw new InvalidMetadataException(
|
||||||
"The ManagedOperation attribute is not valid for JavaBean properties. Use ManagedAttribute instead.");
|
"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) {
|
if (ann == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
||||||
public ManagedOperationParameter[] getManagedOperationParameters(Method method)
|
public ManagedOperationParameter[] getManagedOperationParameters(Method method)
|
||||||
throws InvalidMetadataException {
|
throws InvalidMetadataException {
|
||||||
|
|
||||||
ManagedOperationParameters params = AnnotationUtils.getAnnotation(method, ManagedOperationParameters.class);
|
ManagedOperationParameters params = AnnotationUtils.findAnnotation(method, ManagedOperationParameters.class);
|
||||||
ManagedOperationParameter[] result = null;
|
ManagedOperationParameter[] result = null;
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
result = new ManagedOperationParameter[0];
|
result = new ManagedOperationParameter[0];
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,32 @@
|
||||||
|
|
||||||
package org.springframework.jmx.export.annotation;
|
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.IJmxTestBean;
|
||||||
import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests;
|
import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests;
|
||||||
import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
||||||
|
|
||||||
/**
|
/** @author Rob Harrop */
|
||||||
* @author Rob Harrop
|
|
||||||
*/
|
|
||||||
public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests {
|
public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests {
|
||||||
|
|
||||||
private static final String OBJECT_NAME = "bean:name=testBean4";
|
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() {
|
protected JmxAttributeSource getAttributeSource() {
|
||||||
return new AnnotationJmxAttributeSource();
|
return new AnnotationJmxAttributeSource();
|
||||||
}
|
}
|
||||||
|
|
@ -36,11 +51,20 @@ public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerT
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IJmxTestBean createJmxTestBean() {
|
protected IJmxTestBean createJmxTestBean() {
|
||||||
return new AnnotationTestBean();
|
return new AnnotationTestSubBean();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getApplicationContextPath() {
|
protected String getApplicationContextPath() {
|
||||||
return "org/springframework/jmx/export/annotation/annotations.xml";
|
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>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestBean">
|
<bean id="testBean" class="org.springframework.jmx.export.annotation.AnnotationTestSubBean">
|
||||||
<property name="name">
|
<property name="name">
|
||||||
<value>TEST</value>
|
<value>TEST</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.jmx.export.assembler;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.management.Descriptor;
|
import javax.management.Descriptor;
|
||||||
import javax.management.MBeanInfo;
|
import javax.management.MBeanInfo;
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ public abstract class AnnotationUtils {
|
||||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||||
A annotation = getAnnotation(method, annotationType);
|
A annotation = getAnnotation(method, annotationType);
|
||||||
Class<?> cl = method.getDeclaringClass();
|
Class<?> cl = method.getDeclaringClass();
|
||||||
|
if(annotation == null) {
|
||||||
|
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||||
|
}
|
||||||
while (annotation == null) {
|
while (annotation == null) {
|
||||||
cl = cl.getSuperclass();
|
cl = cl.getSuperclass();
|
||||||
if (cl == null || cl == Object.class) {
|
if (cl == null || cl == Object.class) {
|
||||||
|
|
@ -109,6 +112,9 @@ public abstract class AnnotationUtils {
|
||||||
try {
|
try {
|
||||||
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||||
annotation = getAnnotation(equivalentMethod, annotationType);
|
annotation = getAnnotation(equivalentMethod, annotationType);
|
||||||
|
if(annotation == null) {
|
||||||
|
annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException ex) {
|
catch (NoSuchMethodException ex) {
|
||||||
// We're done...
|
// We're done...
|
||||||
|
|
@ -117,6 +123,24 @@ public abstract class AnnotationUtils {
|
||||||
return annotation;
|
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
|
* Find a single {@link Annotation} of <code>annotationType</code> from the
|
||||||
* supplied {@link Class}, traversing its interfaces and super classes
|
* supplied {@link Class}, traversing its interfaces and super classes
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,22 @@ public class AnnotationUtilsTests {
|
||||||
assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(Order.class));
|
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 {
|
public static interface AnnotatedInterface {
|
||||||
|
|
||||||
@Order(0)
|
@Order(0)
|
||||||
|
|
@ -286,6 +302,25 @@ public class AnnotationUtilsTests {
|
||||||
public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass {
|
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)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue