Merge remote-tracking branch 'upstream/master' into 4.0.0-WIP
Conflicts: spring-integration-core/src/main/java/org/springframework/integration/channel/registry/ChannelRegistry.java spring-integration-core/src/main/java/org/springframework/integration/channel/registry/LocalChannelRegistry.java spring-integration-core/src/main/java/org/springframework/integration/mapping/AbstractHeaderMapper.java spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java spring-integration-core/src/test/java/org/springframework/integration/channel/registry/LocalChannelRegistryTests.java spring-integration-core/src/test/java/org/springframework/integration/handler/ServiceActivatorDefaultFrameworkMethodTests.java spring-integration-jmx/src/test/java/org/springframework/integration/jmx/ServiceActivatorDefaultFrameworkMethodTests.java spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java Resolved.
This commit is contained in:
@@ -34,6 +34,7 @@ import javax.management.ObjectName;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.util.ClassUtils;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
@@ -68,7 +69,6 @@ public class OperationInvokingMessageHandler extends AbstractReplyProducingMessa
|
||||
|
||||
private volatile String operationName;
|
||||
|
||||
|
||||
/**
|
||||
* Provide a reference to the MBeanServer within which the MBean
|
||||
* target for operation invocation has been registered.
|
||||
@@ -134,7 +134,7 @@ public class OperationInvokingMessageHandler extends AbstractReplyProducingMessa
|
||||
*/
|
||||
value = paramsFromMessage.get("p" + (index + 1));
|
||||
}
|
||||
if (value != null && value.getClass().getName().equals(paramInfo.getType())) {
|
||||
if (value != null && valueTypeMatchesParameterType(value, paramInfo)) {
|
||||
values[index] = value;
|
||||
signature[index] = paramInfo.getType();
|
||||
index++;
|
||||
@@ -151,18 +151,29 @@ public class OperationInvokingMessageHandler extends AbstractReplyProducingMessa
|
||||
}
|
||||
throw new MessagingException(requestMessage, "failed to find JMX operation '"
|
||||
+ operationName + "' on MBean [" + objectName + "] of type [" + mbeanInfo.getClassName()
|
||||
+ "] with " + paramsFromMessage.size() + " parameters: " + paramsFromMessage.keySet());
|
||||
+ "] with " + paramsFromMessage.size() + " parameters: " + paramsFromMessage);
|
||||
}
|
||||
catch (JMException e) {
|
||||
throw new MessageHandlingException(requestMessage, "failed to invoke JMX operation '" +
|
||||
operationName + "' on MBean [" + objectName + "]" + " with " +
|
||||
paramsFromMessage.size() + " parameters: " + paramsFromMessage.keySet(), e);
|
||||
paramsFromMessage.size() + " parameters: " + paramsFromMessage, e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessageHandlingException(requestMessage, "IOException on MBeanServerConnection", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean valueTypeMatchesParameterType(Object value, MBeanParameterInfo paramInfo) {
|
||||
Class<? extends Object> valueClass = value.getClass();
|
||||
if (valueClass.getName().equals(paramInfo.getType())) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Class<?> primitiveType = ClassUtils.resolvePrimitiveType(valueClass);
|
||||
return primitiveType != null && primitiveType.getName().equals(paramInfo.getType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* First checks if defaultObjectName is set, otherwise falls back on {@link JmxHeaders#OBJECT_NAME} header.
|
||||
*/
|
||||
@@ -229,4 +240,4 @@ public class OperationInvokingMessageHandler extends AbstractReplyProducingMessa
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the 'mbean-export' element of the integration JMX namespace.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
@@ -61,7 +61,8 @@ public class MBeanExporterParser extends AbstractSingleBeanDefinitionParser {
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "object-name-static-properties");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "managed-components", "componentNamePatterns");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "shutdown-executor");
|
||||
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "object-naming-strategy", "namingStrategy");
|
||||
|
||||
builder.addPropertyValue("server", mbeanServer);
|
||||
this.registerMBeanExporterHelper(parserContext.getRegistry());
|
||||
}
|
||||
@@ -70,7 +71,7 @@ public class MBeanExporterParser extends AbstractSingleBeanDefinitionParser {
|
||||
BeanDefinitionBuilder mBeanExporterHelperBuilder = BeanDefinitionBuilder.rootBeanDefinition(MBeanExporterHelper.class);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(mBeanExporterHelperBuilder.getBeanDefinition(), registry);
|
||||
}
|
||||
|
||||
|
||||
private Object getMBeanServer(Element element, ParserContext parserContext) {
|
||||
String mbeanServer = element.getAttribute("server");
|
||||
if (StringUtils.hasText(mbeanServer)) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.management.DynamicMBean;
|
||||
@@ -80,6 +81,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.FieldCallback;
|
||||
import org.springframework.util.ReflectionUtils.FieldFilter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -106,6 +109,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Helena Edelson
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ManagedResource
|
||||
public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostProcessor, BeanFactoryAware,
|
||||
@@ -163,7 +167,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
|
||||
private final MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler(attributeSource);
|
||||
|
||||
private final MetadataNamingStrategy namingStrategy = new MetadataNamingStrategy(attributeSource);
|
||||
private final MetadataNamingStrategy defaultNamingStrategy = new MetadataNamingStrategy(attributeSource);
|
||||
|
||||
private String[] componentNamePatterns = { "*" };
|
||||
|
||||
@@ -179,7 +183,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
super();
|
||||
// Shouldn't be necessary, but to be on the safe side...
|
||||
setAutodetect(false);
|
||||
setNamingStrategy(namingStrategy);
|
||||
setNamingStrategy(defaultNamingStrategy);
|
||||
setAssembler(assembler);
|
||||
}
|
||||
|
||||
@@ -206,7 +210,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
*/
|
||||
public void setDefaultDomain(String domain) {
|
||||
this.domain = domain;
|
||||
this.namingStrategy.setDefaultDomain(domain);
|
||||
this.defaultNamingStrategy.setDefaultDomain(domain);
|
||||
}
|
||||
|
||||
public void setComponentNamePatterns(String[] componentNamePatterns) {
|
||||
@@ -217,7 +221,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
super.setBeanFactory(beanFactory);
|
||||
Assert.isTrue(beanFactory instanceof ListableBeanFactory, "A ListableBeanFactory is required.");
|
||||
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory, "A ListableBeanFactory is required.");
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
@@ -246,6 +250,12 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
}
|
||||
|
||||
if (bean instanceof MessageHandler) {
|
||||
if (this.handlerInAnonymousWrapper(bean) != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping " + beanName + " because it wraps another handler");
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
SimpleMessageHandlerMetrics monitor = new SimpleMessageHandlerMetrics((MessageHandler) bean);
|
||||
Object advised = applyHandlerInterceptor(bean, monitor, beanClassLoader);
|
||||
handlers.add(monitor);
|
||||
@@ -282,6 +292,33 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
|
||||
}
|
||||
|
||||
private MessageHandler handlerInAnonymousWrapper(final Object bean) {
|
||||
if (bean != null && bean.getClass().isAnonymousClass()) {
|
||||
final AtomicReference<MessageHandler> wrapped = new AtomicReference<MessageHandler>();
|
||||
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
|
||||
|
||||
@Override
|
||||
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||
field.setAccessible(true);
|
||||
Object handler = field.get(bean);
|
||||
if (handler instanceof MessageHandler) {
|
||||
wrapped.set((MessageHandler) handler);
|
||||
}
|
||||
}
|
||||
}, new FieldFilter() {
|
||||
|
||||
@Override
|
||||
public boolean matches(Field field) {
|
||||
return wrapped.get() == null && field.getName().startsWith("val$");
|
||||
}
|
||||
});
|
||||
return wrapped.get();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy of private method in super class. Needed so we can avoid using the bean factory to extract the bean again,
|
||||
* and risk it being a proxy (which it almost certainly is by now).
|
||||
@@ -987,20 +1024,22 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
String source = "endpoint";
|
||||
Object endpoint = null;
|
||||
|
||||
MessageHandler messageHandler = monitor.getMessageHandler();
|
||||
|
||||
for (String beanName : names) {
|
||||
endpoint = beanFactory.getBean(beanName);
|
||||
Object field = null;
|
||||
try {
|
||||
field = extractTarget(getField(endpoint, "handler"));
|
||||
Object field = extractTarget(getField(endpoint, "handler"));
|
||||
if (field == messageHandler ||
|
||||
this.extractTarget(this.handlerInAnonymousWrapper(field)) == messageHandler) {
|
||||
name = beanName;
|
||||
endpointName = beanName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.trace("Could not get handler from bean = " + beanName);
|
||||
}
|
||||
if (field == monitor.getMessageHandler()) {
|
||||
name = beanName;
|
||||
endpointName = beanName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name != null && endpoint != null && name.startsWith("_org.springframework.integration")) {
|
||||
name = getInternalComponentName(name);
|
||||
@@ -1044,11 +1083,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
if (monitor.getMessageHandler() instanceof NamedComponent) {
|
||||
name = ((NamedComponent) monitor.getMessageHandler()).getComponentName();
|
||||
if (messageHandler instanceof NamedComponent) {
|
||||
name = ((NamedComponent) messageHandler).getComponentName();
|
||||
}
|
||||
if (name == null) {
|
||||
name = monitor.getMessageHandler().toString();
|
||||
name = messageHandler.toString();
|
||||
}
|
||||
source = "handler";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user