INT-1675: work a bit harder to expose existing handlers if they are @ManagedResources
This commit is contained in:
@@ -66,7 +66,7 @@ public class LoggingHandler extends AbstractMessageHandler {
|
||||
this.evaluationContext = evaluationContext;
|
||||
this.expression = EXPRESSION_PARSER.parseExpression("payload");
|
||||
}
|
||||
|
||||
|
||||
public void setExpression(String expressionString) {
|
||||
this.expression = EXPRESSION_PARSER.parseExpression(expressionString);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,17 @@
|
||||
package org.springframework.integration.history;
|
||||
|
||||
import org.springframework.integration.context.NamedComponent;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
@ManagedResource
|
||||
public interface TrackableComponent extends NamedComponent {
|
||||
|
||||
@ManagedOperation
|
||||
void setShouldTrack(boolean shouldTrack);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,5 +32,5 @@ public class ExpressionEvaluatingRouter extends AbstractMessageProcessingRouter
|
||||
public ExpressionEvaluatingRouter(Expression expression) {
|
||||
super(new ExpressionEvaluatingMessageProcessor<Object>(expression));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,18 @@ public class MBeanExporterParser extends AbstractSingleBeanDefinitionParser {
|
||||
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-domain");
|
||||
builder.addPropertyValue("server", mbeanServer);
|
||||
// if (!parserContext.getRegistry().containsBeanDefinition(MBEAN_EXPORTER_NAME)) {
|
||||
// /*
|
||||
// * Vanilla MBeanExporter not yet registered - need to hack this in to ensure if it is subsequently
|
||||
// * registered, then it gets initialized before the IntegrationMBeanExporter.
|
||||
// */
|
||||
// BeanDefinitionBuilder dummy = BeanDefinitionBuilder.genericBeanDefinition(String.class);
|
||||
// dummy.addConstructorArgValue("Dummy " + MBEAN_EXPORTER_NAME
|
||||
// + " will be overridden by a <context:mbean-export/>");
|
||||
// parserContext.getRegistry().registerBeanDefinition(MBEAN_EXPORTER_NAME, dummy.getBeanDefinition());
|
||||
// }
|
||||
// // Force vanilla MBeanExporter to initialize first if it exists to prevent problems with Proxies
|
||||
// builder.getRawBeanDefinition().setDependsOn(new String[] { MBEAN_EXPORTER_NAME });
|
||||
}
|
||||
|
||||
private Object getMBeanServer(Element element, ParserContext parserContext) {
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
@@ -63,8 +62,11 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
|
||||
|
||||
private final String name;
|
||||
|
||||
private final MessageChannel messageChannel;
|
||||
|
||||
public DirectChannelMetrics(String name) {
|
||||
|
||||
public DirectChannelMetrics(MessageChannel messageChannel, String name) {
|
||||
this.messageChannel = messageChannel;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -75,6 +77,10 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
|
||||
}
|
||||
}
|
||||
|
||||
public MessageChannel getMessageChannel() {
|
||||
return messageChannel;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -196,4 +202,5 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
|
||||
public String toString() {
|
||||
return String.format("MessageChannelMonitor: [name=%s, sends=%d]", name, sendCount.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.JMException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.modelmbean.ModelMBean;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -46,6 +51,7 @@ import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.export.UnableToRegisterMBeanException;
|
||||
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedMetric;
|
||||
@@ -104,6 +110,8 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
|
||||
private Set<DirectChannelMetrics> channels = new HashSet<DirectChannelMetrics>();
|
||||
|
||||
private Map<String, Object> exposedBeans = new HashMap<String, Object>();
|
||||
|
||||
private Map<String, DirectChannelMetrics> channelsByName = new HashMap<String, DirectChannelMetrics>();
|
||||
|
||||
private Map<String, MessageHandlerMetrics> handlersByName = new HashMap<String, MessageHandlerMetrics>();
|
||||
@@ -122,14 +130,24 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
|
||||
private String domain = DEFAULT_DOMAIN;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private final Map<String, String> objectNameStaticProperties = new HashMap<String, String>();
|
||||
|
||||
private final MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler(attributeSource);
|
||||
|
||||
private final MetadataNamingStrategy namingStrategy = new MetadataNamingStrategy(attributeSource);
|
||||
|
||||
private final Set<MBeanExporter> mbeanExporters = new HashSet<MBeanExporter>();
|
||||
|
||||
private final Set<String> excludedBeansForOtherExporters = new HashSet<String>();
|
||||
|
||||
public IntegrationMBeanExporter() {
|
||||
super();
|
||||
// Shouldn't be necessary, but to be on the safe side...
|
||||
setAutodetect(false);
|
||||
setNamingStrategy(new MetadataNamingStrategy(attributeSource));
|
||||
setAssembler(new MetadataMBeanInfoAssembler(attributeSource));
|
||||
setNamingStrategy(namingStrategy);
|
||||
setAssembler(assembler);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,6 +173,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
*/
|
||||
public void setDefaultDomain(String domain) {
|
||||
this.domain = domain;
|
||||
this.namingStrategy.setDefaultDomain(domain);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
@@ -164,6 +183,12 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
collectMBeanExporters();
|
||||
}
|
||||
|
||||
if (bean instanceof Advised) {
|
||||
for (Advisor advisor : ((Advised) bean).getAdvisors()) {
|
||||
Advice advice = advisor.getAdvice();
|
||||
@@ -179,40 +204,97 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
SimpleMessageHandlerMetrics monitor = new SimpleMessageHandlerMetrics((MessageHandler) bean);
|
||||
Object advised = applyHandlerInterceptor(bean, monitor, beanClassLoader);
|
||||
handlers.add(monitor);
|
||||
excludeBeanInOtherExporters(beanName);
|
||||
return advised;
|
||||
} else if (bean instanceof MessageSource<?>) {
|
||||
}
|
||||
|
||||
if (bean instanceof MessageSource<?>) {
|
||||
SimpleMessageSourceMetrics monitor = new SimpleMessageSourceMetrics((MessageSource<?>) bean);
|
||||
Object advised = applySourceInterceptor(bean, monitor, beanClassLoader);
|
||||
sources.add(monitor);
|
||||
excludeBeanInOtherExporters(beanName);
|
||||
return advised;
|
||||
}
|
||||
|
||||
if (bean instanceof MessageChannel) {
|
||||
DirectChannelMetrics monitor;
|
||||
MessageChannel target = (MessageChannel) extractTarget(bean);
|
||||
if (bean instanceof PollableChannel) {
|
||||
Object target = extractTarget(bean);
|
||||
if (target instanceof QueueChannel) {
|
||||
monitor = new QueueChannelMetrics((QueueChannel) target, beanName);
|
||||
} else {
|
||||
monitor = new PollableChannelMetrics(beanName);
|
||||
monitor = new PollableChannelMetrics(target, beanName);
|
||||
}
|
||||
} else {
|
||||
monitor = new DirectChannelMetrics(beanName);
|
||||
monitor = new DirectChannelMetrics(target, beanName);
|
||||
}
|
||||
Object advised = applyChannelInterceptor(bean, monitor, beanClassLoader);
|
||||
channels.add(monitor);
|
||||
excludeBeanInOtherExporters(beanName);
|
||||
return advised;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
/**
|
||||
* Make sure the named bean is not exposed in any other MBean exporters in the context. Called for beans that are
|
||||
* being directly monitored by this exporter, but are wrapped in a proxy so cannot be directly exposed by a normal
|
||||
* exporter.
|
||||
*
|
||||
* @param beanName the bean name to exclude
|
||||
*/
|
||||
private void excludeBeanInOtherExporters(String beanName) {
|
||||
excludedBeansForOtherExporters.add(beanName);
|
||||
String[] excluded = excludedBeansForOtherExporters.toArray(new String[0]);
|
||||
for (MBeanExporter exporter : mbeanExporters) {
|
||||
exporter.setExcludedBeans(excluded);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerBeans() {
|
||||
// Completely disable super class registration to avoid duplicates
|
||||
/**
|
||||
* 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).
|
||||
*
|
||||
* @param bean the bean instance to register
|
||||
* @param beanKey the bean name or human readable version if autogenerated
|
||||
* @return the JMX object name of the MBean that was registered
|
||||
*/
|
||||
private ObjectName registerBeanInstance(Object bean, String beanKey) {
|
||||
try {
|
||||
ObjectName objectName = getObjectName(bean, beanKey);
|
||||
Object mbeanToExpose = null;
|
||||
if (isMBean(bean.getClass())) {
|
||||
mbeanToExpose = bean;
|
||||
} else {
|
||||
DynamicMBean adaptedBean = adaptMBeanIfPossible(bean);
|
||||
if (adaptedBean != null) {
|
||||
mbeanToExpose = adaptedBean;
|
||||
}
|
||||
}
|
||||
if (mbeanToExpose != null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Located MBean '" + beanKey + "': registering with JMX server as MBean [" + objectName
|
||||
+ "]");
|
||||
}
|
||||
doRegister(mbeanToExpose, objectName);
|
||||
} else {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Located managed bean '" + beanKey + "': registering with JMX server as MBean ["
|
||||
+ objectName + "]");
|
||||
}
|
||||
ModelMBean mbean = createAndConfigureMBean(bean, beanKey);
|
||||
doRegister(mbean, objectName);
|
||||
// injectNotificationPublisherIfNecessary(bean, mbean, objectName);
|
||||
}
|
||||
return objectName;
|
||||
} catch (JMException e) {
|
||||
throw new UnableToRegisterMBeanException("Unable to register MBean [" + bean + "] with key '" + beanKey
|
||||
+ "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public final boolean isAutoStartup() {
|
||||
@@ -285,14 +367,18 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
registerSources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
/*
|
||||
* Force early initialization of other MBeanExporters. Workaround for possible bug in Spring (see INT-1675) for
|
||||
* more details.
|
||||
*/
|
||||
beanFactory.getBeansOfType(MBeanExporter.class);
|
||||
/**
|
||||
* Force early initialization of other MBean exporters and collect them for later use to ensure that they don't try
|
||||
* to register the same beans that this exporter is covering.
|
||||
*/
|
||||
private void collectMBeanExporters() {
|
||||
String[] beanNames = beanFactory.getBeanNamesForType(MBeanExporter.class, false, false);
|
||||
for (String beanName : beanNames) {
|
||||
MBeanExporter bean = beanFactory.getBean(beanName, MBeanExporter.class);
|
||||
if (bean != this) {
|
||||
mbeanExporters.add((MBeanExporter) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -381,6 +467,14 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerBeans() {
|
||||
if (!exposedBeans.isEmpty()) {
|
||||
super.setBeans(exposedBeans);
|
||||
super.registerBeans();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerChannels() {
|
||||
for (DirectChannelMetrics monitor : channels) {
|
||||
String name = monitor.getName();
|
||||
@@ -392,6 +486,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
channelsByName.put(name, monitor);
|
||||
}
|
||||
registerBeanNameOrInstance(monitor, beanKey);
|
||||
// Expose the raw bean if it is managed
|
||||
MessageChannel bean = monitor.getMessageChannel();
|
||||
if (assembler.includeBean(bean.getClass(), monitor.getName())) {
|
||||
registerBeanInstance(bean, monitor.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,6 +506,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
handlersByName.put(name, monitor);
|
||||
}
|
||||
registerBeanNameOrInstance(monitor, beanKey);
|
||||
// Expose the raw bean if it is managed
|
||||
MessageHandler bean = source.getMessageHandler();
|
||||
if (assembler.includeBean(bean.getClass(), source.getName())) {
|
||||
registerBeanInstance(bean, monitor.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,6 +526,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
sourcesByName.put(name, monitor);
|
||||
}
|
||||
registerBeanNameOrInstance(monitor, beanKey);
|
||||
// Expose the raw bean if it is managed
|
||||
MessageSource<?> bean = source.getMessageSource();
|
||||
if (assembler.includeBean(bean.getClass(), source.getName())) {
|
||||
registerBeanInstance(bean, monitor.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -472,6 +581,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
|
||||
} else {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
proxyFactory.addAdvisor(advisor);
|
||||
/**
|
||||
* N.B. it's not a good idea to use proxyFactory.setProxyTargetClass(true) here because it forces all
|
||||
* the integration components to be cglib proxyable (i.e. have a default constructor etc.), which they
|
||||
* are not in general (usually for good reason).
|
||||
*/
|
||||
return proxyFactory.getProxy(beanClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.integration.monitor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.jmx.export.annotation.ManagedMetric;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
@@ -36,14 +35,10 @@ public class PollableChannelMetrics extends DirectChannelMetrics {
|
||||
private final AtomicInteger receiveErrorCount = new AtomicInteger();
|
||||
|
||||
|
||||
/**
|
||||
* @param name
|
||||
*/
|
||||
public PollableChannelMetrics(String name) {
|
||||
super(name);
|
||||
public PollableChannelMetrics(MessageChannel messageChannel, String name) {
|
||||
super(messageChannel, name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doInvoke(MethodInvocation invocation, String method, MessageChannel channel) throws Throwable {
|
||||
if ("receive".equals(method)) {
|
||||
|
||||
@@ -29,16 +29,11 @@ public class QueueChannelMetrics extends PollableChannelMetrics {
|
||||
private final QueueChannel channel;
|
||||
|
||||
|
||||
/**
|
||||
* @param channel
|
||||
* @param name
|
||||
*/
|
||||
public QueueChannelMetrics(QueueChannel channel, String name) {
|
||||
super(name);
|
||||
super(channel, name);
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
|
||||
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "QueueChannel Queue Size")
|
||||
public int getQueueSize() {
|
||||
return channel.getQueueSize();
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context" xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean class="java.lang.String" depends-on="router">
|
||||
<constructor-arg value="dummy" />
|
||||
</bean>
|
||||
|
||||
<context:mbean-server id="mbs" />
|
||||
|
||||
<context:mbean-export server="mbs" default-domain="test.MBeanAutoDetectFirst" />
|
||||
|
||||
<bean id="router" class="org.springframework.integration.config.RouterFactoryBean">
|
||||
<property name="expressionString" value="payload instanceof String ? 'stringChannel' : 'intChannel'" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context" xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:mbean-server id="mbs" />
|
||||
|
||||
<context:mbean-export server="mbs" default-domain="test.MBeanAutoDetectFirst" />
|
||||
|
||||
<bean id="router" class="org.springframework.integration.config.RouterFactoryBean">
|
||||
<property name="expressionString" value="payload instanceof String ? 'stringChannel' : 'intChannel'" />
|
||||
</bean>
|
||||
|
||||
<bean class="java.lang.String" depends-on="router">
|
||||
<constructor-arg value="dummy" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.integration.jmx.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MBeanAutoDetectTests {
|
||||
|
||||
private MBeanServer server;
|
||||
|
||||
private ClassPathXmlApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRouterMBeanExistsWhenDefinedFirst() throws Exception {
|
||||
context = new ClassPathXmlApplicationContext("MBeanAutoDetectFirstTests-context.xml", getClass());
|
||||
server = context.getBean(MBeanServer.class);
|
||||
// System.err.println(server.queryNames(new ObjectName("test.MBeanAutoDetectFirst:*"), null));
|
||||
Set<ObjectName> names = server.queryNames(
|
||||
new ObjectName("test.MBeanAutoDetectFirst:type=ExpressionEvaluatingRouter,*"), null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // Fails because the MBeanExporter is created before the router
|
||||
public void testRouterMBeanExistsWhenDefinedSecond() throws Exception {
|
||||
context = new ClassPathXmlApplicationContext("MBeanAutoDetectSecondTests-context.xml", getClass());
|
||||
server = context.getBean(MBeanServer.class);
|
||||
// System.err.println(server.queryNames(new ObjectName("test.MBeanAutoDetectFirst:*"), null));
|
||||
Set<ObjectName> names = server.queryNames(
|
||||
new ObjectName("test.MBeanAutoDetectFirst:type=ExpressionEvaluatingRouter,*"), null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context" xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/jmx
|
||||
http://www.springframework.org/schema/integration/jmx/spring-integration-jmx.xsd">
|
||||
|
||||
<int:channel id="testChannel" />
|
||||
<int:channel id="intChannel" />
|
||||
<int:channel id="stringChannel" />
|
||||
|
||||
<int:gateway id="gateway" service-interface="org.springframework.integration.jmx.config.RouterMBeanTests$Service"
|
||||
default-request-channel="testChannel" />
|
||||
|
||||
<int:router id="ptRouter" input-channel="testChannel" expression="payload instanceof String ? 'stringChannel' : 'intChannel'" />
|
||||
|
||||
<context:mbean-server id="mbs" />
|
||||
|
||||
<context:mbean-export server="mbs" default-domain="test.RouterMBean" />
|
||||
|
||||
<jmx:mbean-export server="mbs" default-domain="test.RouterMBean" />
|
||||
|
||||
</beans>
|
||||
@@ -14,11 +14,15 @@
|
||||
package org.springframework.integration.jmx.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
@@ -48,9 +52,10 @@ public class RouterMBeanTests {
|
||||
@Parameters
|
||||
public static List<Object[]> getParameters() {
|
||||
return Arrays.asList(
|
||||
new Object[] { RouterMBeanTests.class.getSimpleName() + "-context.xml" },
|
||||
new Object[] { RouterMBeanTests.class.getSimpleName() + "None-context.xml" },
|
||||
new Object[] { RouterMBeanTests.class.getSimpleName() + "Switch-context.xml" });
|
||||
new Object[] { "RouterMBeanTests-context.xml" },
|
||||
new Object[] { "RouterMBeanGatewayTests-context.xml" },
|
||||
new Object[] { "RouterMBeanNoneTests-context.xml" },
|
||||
new Object[] { "RouterMBeanSwitchTests-context.xml" });
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -68,11 +73,50 @@ public class RouterMBeanTests {
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputChannelMBeanExists() throws Exception {
|
||||
// System.err.println(server.queryNames(new ObjectName("test.RouterMBean:type=MessageChannel,*"), null));
|
||||
Set<ObjectName> names = server.queryNames(
|
||||
new ObjectName("test.RouterMBean:type=MessageChannel,name=testChannel,*"), null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorChannelMBeanExists() throws Exception {
|
||||
Set<ObjectName> names = server.queryNames(
|
||||
new ObjectName("test.RouterMBean:type=MessageChannel,name=errorChannel,*"), null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRouterMBeanOnlyRegisteredOnce() throws Exception {
|
||||
// System.err.println(server.queryNames(new ObjectName("*:type=MessageHandler,*"), null));
|
||||
// The errorLogger and the router
|
||||
assertEquals(2, server.queryNames(new ObjectName("test.RouterMBean:type=MessageHandler,*"), null).size());
|
||||
Set<ObjectName> names = server.queryNames(new ObjectName("test.RouterMBean:type=MessageHandler,name=ptRouter,*"), null);
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRouterMBeanHasTrackableComponent() throws Exception {
|
||||
// System.err.println(server.queryNames(new ObjectName("test.RouterMBean:*"), null));
|
||||
Set<ObjectName> names = server.queryNames(new ObjectName("test.RouterMBean:type=ExpressionEvaluatingRouter,*"), null);
|
||||
Map<String,MBeanOperationInfo> infos = new HashMap<String, MBeanOperationInfo>();
|
||||
for (MBeanOperationInfo info : server.getMBeanInfo(names.iterator().next()).getOperations()) {
|
||||
infos.put(info.getName(), info);
|
||||
}
|
||||
// System.err.println(infos);
|
||||
assertNotNull(infos.get("setShouldTrack"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVanillaRouterMBeanRegistration() throws Exception {
|
||||
// System.err.println(server.queryNames(new ObjectName("test.RouterMBean:*"), null));
|
||||
Set<ObjectName> names = server.queryNames(new ObjectName("test.RouterMBean:type=ExpressionEvaluatingRouter,*"), null);
|
||||
// The router is exposed...
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
public static interface Service {
|
||||
void send(String input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context" xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:jmx="http://www.springframework.org/schema/integration/jmx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/jmx
|
||||
http://www.springframework.org/schema/integration/jmx/spring-integration-jmx.xsd">
|
||||
|
||||
<int:channel id="testChannel" />
|
||||
<int:channel id="intChannel" />
|
||||
<int:channel id="stringChannel" />
|
||||
|
||||
<int:router id="ptRouter" input-channel="testChannel" expression="payload instanceof String ? 'stringChannel' : 'intChannel'"/>
|
||||
|
||||
<context:mbean-server id="mbs" />
|
||||
|
||||
<context:mbean-export server="mbs" default-domain="test.RouterMBeanVanilla" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.integration.jmx.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class RouterMBeanVanillaTests {
|
||||
|
||||
@Autowired
|
||||
private MBeanServer server;
|
||||
|
||||
@Test
|
||||
public void testHandlerMBeanRegistration() throws Exception {
|
||||
// System.err.println(server.queryNames(new ObjectName("test.RouterMBeanVanilla:*"), null));
|
||||
Set<ObjectName> names = server.queryNames(new ObjectName("test.RouterMBeanVanilla:type=ExpressionEvaluatingRouter,*"), null);
|
||||
// The router is exposed...
|
||||
assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
public static class Source {
|
||||
public String get() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user