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:
Gary Russell
2013-11-01 18:19:02 -04:00
65 changed files with 2126 additions and 909 deletions

View File

@@ -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;
}
}
}

View File

@@ -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)) {

View File

@@ -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";
}