INT-3636: JMX Eliminate Channel Metric Proxies

JIRA: https://jira.spring.io/browse/INT-3636

- Add `enableStats()` managed operation
- Delegate to a channel metrics object instead of using a proxy

INT-3636: Polishing; PR Comments

Change field name in `MBeanExporterHelper`.

INT-3636: Polishing
This commit is contained in:
Gary Russell
2015-02-17 13:54:18 +02:00
committed by Artem Bilan
parent 8c81cffd27
commit b07686cdc0
29 changed files with 525 additions and 243 deletions

View File

@@ -26,11 +26,15 @@ import java.util.concurrent.CopyOnWriteArrayList;
import org.springframework.core.OrderComparator;
import org.springframework.core.convert.ConversionService;
import org.springframework.integration.channel.management.ChannelSendMetrics;
import org.springframework.integration.channel.management.MessageChannelMetrics;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
@@ -38,6 +42,7 @@ import org.springframework.messaging.MessagingException;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
/**
@@ -51,8 +56,9 @@ import org.springframework.util.StringUtils;
* @author Gary Russell
* @author Artem Bilan
*/
@ManagedResource
public abstract class AbstractMessageChannel extends IntegrationObjectSupport
implements MessageChannel, TrackableComponent, ChannelInterceptorAware {
implements MessageChannel, TrackableComponent, ChannelInterceptorAware, MessageChannelMetrics {
private final ChannelInterceptorList interceptors = new ChannelInterceptorList();
@@ -66,6 +72,10 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
private volatile MessageConverter messageConverter;
private volatile boolean statsEnabled;
private volatile ChannelSendMetrics channelMetrics;
@Override
public String getComponentType() {
return "channel";
@@ -76,6 +86,16 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
this.shouldTrack = shouldTrack;
}
@Override
public void enableStats(boolean statsEnabled) {
this.statsEnabled = statsEnabled;
}
@Override
public boolean isStatsEnabled() {
return this.statsEnabled;
}
/**
* Specify the Message payload datatype(s) supported by this channel. If a
* payload type does not match directly, but the 'conversionService' is
@@ -192,6 +212,86 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return this.interceptors;
}
@Override
public void reset() {
this.channelMetrics.reset();
}
@Override
public int getSendCount() {
return this.channelMetrics.getSendCount();
}
@Override
public long getSendCountLong() {
return this.channelMetrics.getSendCountLong();
}
@Override
public int getSendErrorCount() {
return this.channelMetrics.getSendErrorCount();
}
@Override
public long getSendErrorCountLong() {
return this.channelMetrics.getSendErrorCountLong();
}
@Override
public double getTimeSinceLastSend() {
return this.channelMetrics.getTimeSinceLastSend();
}
@Override
public double getMeanSendRate() {
return this.channelMetrics.getMeanSendRate();
}
@Override
public double getMeanErrorRate() {
return this.channelMetrics.getMeanErrorRate();
}
@Override
public double getMeanErrorRatio() {
return this.channelMetrics.getMeanErrorRatio();
}
@Override
public double getMeanSendDuration() {
return this.channelMetrics.getMeanSendDuration();
}
@Override
public double getMinSendDuration() {
return this.channelMetrics.getMinSendDuration();
}
@Override
public double getMaxSendDuration() {
return this.channelMetrics.getMaxSendDuration();
}
@Override
public double getStandardDeviationSendDuration() {
return this.channelMetrics.getStandardDeviationSendDuration();
}
@Override
public Statistics getSendDuration() {
return this.channelMetrics.getSendDuration();
}
@Override
public Statistics getSendRate() {
return this.channelMetrics.getSendRate();
}
@Override
public Statistics getErrorRate() {
return this.channelMetrics.getErrorRate();
}
@Override
protected void onInit() throws Exception {
super.onInit();
@@ -205,6 +305,15 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
}
}
}
initMetrics();
}
protected void initMetrics() {
setChannelMetrics(new ChannelSendMetrics(getComponentName()));
}
protected void setChannelMetrics(ChannelSendMetrics channelMetrics) {
this.channelMetrics = channelMetrics;
}
/**
@@ -263,6 +372,8 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
Deque<ChannelInterceptor> interceptorStack = null;
boolean sent = false;
boolean statsProcessed = false;
StopWatch timer = null;
try {
if (this.datatypes.length > 0) {
message = this.convertPayloadIfNecessary(message);
@@ -274,7 +385,14 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return false;
}
}
if (this.statsEnabled) {
timer = this.channelMetrics.beforeSend();
}
sent = this.doSend(message, timeout);
if (this.statsEnabled) {
this.channelMetrics.afterSend(timer, sent);
statsProcessed = true;
}
this.interceptors.postSend(message, this, sent);
if (interceptorStack != null) {
this.interceptors.afterSendCompletion(message, this, sent, null, interceptorStack);
@@ -282,6 +400,9 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return sent;
}
catch (Exception e) {
if (this.statsEnabled && !statsProcessed) {
this.channelMetrics.afterSend(timer, false);
}
if (interceptorStack != null) {
this.interceptors.afterSendCompletion(message, this, sent, e, interceptorStack);
}
@@ -293,6 +414,10 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
}
}
protected ChannelSendMetrics getMetrics() {
return this.channelMetrics;
}
private Message<?> convertPayloadIfNecessary(Message<?> message) {
// first pass checks if the payload type already matches any of the datatypes
for (Class<?> datatype : this.datatypes) {
@@ -309,7 +434,10 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return (Message<?>) converted;
}
else {
return this.getMessageBuilderFactory().withPayload(converted).copyHeaders(message.getHeaders()).build();
return getMessageBuilderFactory()
.withPayload(converted)
.copyHeaders(message.getHeaders())
.build();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -19,6 +19,8 @@ package org.springframework.integration.channel;
import java.util.ArrayDeque;
import java.util.Deque;
import org.springframework.integration.channel.management.ChannelReceiveMetrics;
import org.springframework.integration.channel.management.PollableChannelManagement;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.ChannelInterceptor;
@@ -28,8 +30,41 @@ import org.springframework.messaging.support.ChannelInterceptor;
*
* @author Mark Fisher
* @author Artem Bilan
* @author Gary Russell
*/
public abstract class AbstractPollableChannel extends AbstractMessageChannel implements PollableChannel {
public abstract class AbstractPollableChannel extends AbstractMessageChannel implements PollableChannel,
PollableChannelManagement {
@Override
protected void initMetrics() {
setChannelMetrics(new ChannelReceiveMetrics(this.getComponentName()));
}
@Override
protected ChannelReceiveMetrics getMetrics() {
return (ChannelReceiveMetrics) super.getMetrics();
}
@Override
public int getReceiveCount() {
return getMetrics().getReceiveCount();
}
@Override
public long getReceiveCountLong() {
return getMetrics().getReceiveCountLong();
}
@Override
public int getReceiveErrorCount() {
return getMetrics().getReceiveErrorCount();
}
@Override
public long getReceiveErrorCountLong() {
return getMetrics().getReceiveErrorCountLong();
}
/**
* Receive the first available message from this channel. If the channel
@@ -40,7 +75,7 @@ public abstract class AbstractPollableChannel extends AbstractMessageChannel imp
*/
@Override
public final Message<?> receive() {
return this.receive(-1);
return receive(-1);
}
/**
@@ -58,7 +93,7 @@ public abstract class AbstractPollableChannel extends AbstractMessageChannel imp
*/
@Override
public final Message<?> receive(long timeout) {
ChannelInterceptorList interceptorList = this.getInterceptors();
ChannelInterceptorList interceptorList = getInterceptors();
Deque<ChannelInterceptor> interceptorStack = null;
try {
if (interceptorList.getInterceptors().size() > 0) {
@@ -69,6 +104,9 @@ public abstract class AbstractPollableChannel extends AbstractMessageChannel imp
}
}
Message<?> message = this.doReceive(timeout);
if (isStatsEnabled()) {
getMetrics().afterReceive();
}
message = interceptorList.postReceive(message, this);
if (interceptorStack != null) {
interceptorList.afterReceiveCompletion(message, this, null, interceptorStack);
@@ -76,6 +114,9 @@ public abstract class AbstractPollableChannel extends AbstractMessageChannel imp
return message;
}
catch (RuntimeException e) {
if (isStatsEnabled()) {
getMetrics().afterError();
}
if (interceptorStack != null) {
interceptorList.afterReceiveCompletion(null, this, e, interceptorStack);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2015 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.
@@ -19,40 +19,168 @@ package org.springframework.integration.channel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.integration.channel.management.ChannelSendMetrics;
import org.springframework.integration.channel.management.MessageChannelMetrics;
import org.springframework.integration.support.context.NamedComponent;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import reactor.util.StringUtils;
/**
* A channel implementation that essentially behaves like "/dev/null".
* All receive() calls will return <em>null</em>, and all send() calls
* will return <em>true</em> although no action is performed.
* Note however that the invocations are logged at debug-level.
*
*
* @author Mark Fisher
* @author Gary Russell
*/
public class NullChannel implements PollableChannel {
@ManagedResource
public class NullChannel implements PollableChannel, MessageChannelMetrics, BeanNameAware, NamedComponent {
private final Log logger = LogFactory.getLog(this.getClass());
private volatile ChannelSendMetrics metrics = new ChannelSendMetrics("nullChannel");
private volatile boolean statsEnabled;
private String beanName;
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
this.metrics = new ChannelSendMetrics(getComponentName());
}
@Override
public String getComponentName() {
return StringUtils.hasText(this.beanName) ? this.beanName: "nullChannel";
}
@Override
public String getComponentType() {
return "channel";
}
@Override
public void reset() {
this.metrics.reset();
}
@Override
public void enableStats(boolean statsEnabled) {
this.statsEnabled = statsEnabled;
}
@Override
public boolean isStatsEnabled() {
return this.statsEnabled;
}
@Override
public int getSendCount() {
return this.metrics.getSendCount();
}
@Override
public long getSendCountLong() {
return this.metrics.getSendCountLong();
}
@Override
public int getSendErrorCount() {
return this.metrics.getSendErrorCount();
}
@Override
public long getSendErrorCountLong() {
return this.metrics.getSendErrorCountLong();
}
@Override
public double getTimeSinceLastSend() {
return this.metrics.getTimeSinceLastSend();
}
@Override
public double getMeanSendRate() {
return this.metrics.getMeanSendRate();
}
@Override
public double getMeanErrorRate() {
return this.metrics.getMeanErrorRate();
}
@Override
public double getMeanErrorRatio() {
return this.metrics.getMeanErrorRatio();
}
@Override
public double getMeanSendDuration() {
return this.metrics.getMeanSendDuration();
}
@Override
public double getMinSendDuration() {
return this.metrics.getMinSendDuration();
}
@Override
public double getMaxSendDuration() {
return this.metrics.getMaxSendDuration();
}
@Override
public double getStandardDeviationSendDuration() {
return this.metrics.getStandardDeviationSendDuration();
}
@Override
public Statistics getSendDuration() {
return this.metrics.getSendDuration();
}
@Override
public Statistics getSendRate() {
return this.metrics.getSendRate();
}
@Override
public Statistics getErrorRate() {
return this.metrics.getErrorRate();
}
@Override
public boolean send(Message<?> message) {
if (logger.isDebugEnabled()) {
logger.debug("message sent to null channel: " + message);
}
if (this.statsEnabled) {
this.metrics.afterSend(this.metrics.beforeSend(), true);
}
return true;
}
@Override
public boolean send(Message<?> message, long timeout) {
return this.send(message);
}
@Override
public Message<?> receive() {
if (logger.isDebugEnabled()) {
logger.debug("receive called on null channel");
}
}
return null;
}
@Override
public Message<?> receive(long timeout) {
return this.receive();
}

View File

@@ -47,10 +47,7 @@ public class PublishSubscribeChannel extends AbstractSubscribableChannel {
private volatile Integer maxSubscribers;
@Override
public String getComponentType(){
return "publish-subscribe-channel";
}
/**
* Create a PublishSubscribeChannel that will use an {@link Executor}
* to invoke the handlers. If this is null, each invocation will occur in
@@ -72,6 +69,11 @@ public class PublishSubscribeChannel extends AbstractSubscribableChannel {
}
@Override
public String getComponentType(){
return "publish-subscribe-channel";
}
/**
* Provide an {@link ErrorHandler} strategy for handling Exceptions that
* occur downstream from this channel. This will <i>only</i> be applied if
@@ -144,9 +146,11 @@ public class PublishSubscribeChannel extends AbstractSubscribableChannel {
/**
* Callback method for initialization.
* @throws Exception the exception.
*/
@Override
public final void onInit() {
public final void onInit() throws Exception {
super.onInit();
if (this.executor != null) {
if (!(this.executor instanceof ErrorHandlingTaskExecutor)) {
if (this.errorHandler == null) {

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.springframework.integration.channel.management.QueueChannelManagement;
import org.springframework.integration.core.MessageSelector;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
@@ -40,7 +41,8 @@ import org.springframework.util.Assert;
* @author Gary Russell
* @author Artem Bilan
*/
public class QueueChannel extends AbstractPollableChannel implements QueueChannelOperations {
public class QueueChannel extends AbstractPollableChannel implements QueueChannelOperations,
QueueChannelManagement {
private final Queue<Message<?>> queue;
@@ -76,7 +78,6 @@ public class QueueChannel extends AbstractPollableChannel implements QueueChanne
this(new LinkedBlockingQueue<Message<?>>());
}
@Override
protected boolean doSend(Message<?> message, long timeout) {
Assert.notNull(message, "'message' must not be null");

View File

@@ -14,56 +14,37 @@
* limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.channel.management;
import java.util.concurrent.atomic.AtomicLong;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.support.MetricType;
import org.springframework.messaging.MessageChannel;
/**
* @author Dave Syer
* @author Gary Russell
* @since 2.0
*/
public class PollableChannelMetrics extends DirectChannelMetrics {
public class ChannelReceiveMetrics extends ChannelSendMetrics {
private final AtomicLong receiveCount = new AtomicLong();
private final AtomicLong receiveErrorCount = new AtomicLong();
public PollableChannelMetrics(MessageChannel messageChannel, String name) {
super(messageChannel, name);
public ChannelReceiveMetrics(String name) {
super(name);
}
@Override
protected Object doInvoke(MethodInvocation invocation, String method, MessageChannel channel) throws Throwable {
if ("receive".equals(method)) {
return monitorReceive(invocation, channel);
}
return super.doInvoke(invocation, method, channel);
}
private Object monitorReceive(MethodInvocation invocation, MessageChannel channel) throws Throwable {
public void afterReceive() {
if (logger.isTraceEnabled()) {
logger.trace("Recording receive on channel(" + channel + ") ");
}
try {
Object object = invocation.proceed();
if (object != null) {
this.receiveCount.incrementAndGet();
}
return object;
}
catch (Throwable e) {//NOSONAR - rethrown below
this.receiveErrorCount.incrementAndGet();
throw e;
logger.trace("Recording receive on channel(" + getName() + ") ");
}
this.receiveCount.incrementAndGet();
}
public void afterError() {
this.receiveErrorCount.incrementAndGet();
}
@Override
@@ -74,22 +55,18 @@ public class PollableChannelMetrics extends DirectChannelMetrics {
this.receiveCount.set(0);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Count")
public int getReceiveCount() {
return (int) this.receiveCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Count")
public long getReceiveCountLong() {
return this.receiveCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Error Count")
public int getReceiveErrorCount() {
return (int) this.receiveErrorCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Error Count")
public long getReceiveErrorCountLong() {
return this.receiveErrorCount.get();
}

View File

@@ -11,18 +11,18 @@
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.channel.management;
import java.util.concurrent.atomic.AtomicLong;
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.support.management.ExponentialMovingAverage;
import org.springframework.integration.support.management.ExponentialMovingAverageRate;
import org.springframework.integration.support.management.ExponentialMovingAverageRatio;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.util.StopWatch;
/**
@@ -35,7 +35,7 @@ import org.springframework.util.StopWatch;
* @since 2.0
*/
@ManagedResource
public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMetrics {
public class ChannelSendMetrics {
protected final Log logger = LogFactory.getLog(getClass());
@@ -45,7 +45,6 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
public static final int DEFAULT_MOVING_AVERAGE_WINDOW = 10;
private final ExponentialMovingAverage sendDuration = new ExponentialMovingAverage(
DEFAULT_MOVING_AVERAGE_WINDOW);
@@ -64,11 +63,8 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
private final String name;
private final MessageChannel messageChannel;
public DirectChannelMetrics(MessageChannel messageChannel, String name) {
this.messageChannel = messageChannel;
public ChannelSendMetrics(String name) {
this.name = name;
}
@@ -79,44 +75,27 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
}
}
public MessageChannel getMessageChannel() {
return messageChannel;
}
public String getName() {
return name;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String method = invocation.getMethod().getName();
MessageChannel channel = (MessageChannel) invocation.getThis();
return doInvoke(invocation, method, channel);
}
protected Object doInvoke(MethodInvocation invocation, String method, MessageChannel channel) throws Throwable {
if ("send".equals(method)) {
Message<?> message = (Message<?>) invocation.getArguments()[0];
return monitorSend(invocation, channel, message);
}
return invocation.proceed();
}
private Object monitorSend(MethodInvocation invocation, MessageChannel channel, Message<?> message) throws Throwable {
public StopWatch beforeSend() {
if (logger.isTraceEnabled()) {
logger.trace("Recording send on channel(" + channel + ") : message(" + message + ")");
logger.trace("Recording send on channel(" + this.name + ")");
}
final StopWatch timer = new StopWatch(channel + ".send:execution");
try {
timer.start();
final StopWatch timer = new StopWatch(this.name + ".send:execution");
timer.start();
sendCount.incrementAndGet();
sendRate.increment();
this.sendCount.incrementAndGet();
this.sendRate.increment();
Object result = invocation.proceed();
return timer;
}
public void afterSend(StopWatch timer, boolean result) {
if (timer != null) {
timer.stop();
if ((Boolean)result) {
if (result) {
sendSuccessRatio.success();
sendDuration.append(timer.getTotalTimeMillis());
}
@@ -125,22 +104,12 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
sendErrorCount.incrementAndGet();
sendErrorRate.increment();
}
return result;
}
catch (Throwable e) {//NOSONAR - rethrown below
sendSuccessRatio.failure();
sendErrorCount.incrementAndGet();
sendErrorRate.increment();
throw e;
}
finally {
if (logger.isTraceEnabled()) {
logger.trace(timer);
}
}
}
@Override
public synchronized void reset() {
sendDuration.reset();
sendErrorRate.reset();
@@ -150,77 +119,62 @@ public class DirectChannelMetrics implements MethodInterceptor, MessageChannelMe
sendErrorCount.set(0);
}
@Override
public int getSendCount() {
return (int) sendCount.get();
}
@Override
public long getSendCountLong() {
return sendCount.get();
}
@Override
public int getSendErrorCount() {
return (int) sendErrorCount.get();
}
@Override
public long getSendErrorCountLong() {
return sendErrorCount.get();
}
@Override
public double getTimeSinceLastSend() {
return sendRate.getTimeSinceLastMeasurement();
}
@Override
public double getMeanSendRate() {
return sendRate.getMean();
}
@Override
public double getMeanErrorRate() {
return sendErrorRate.getMean();
}
@Override
public double getMeanErrorRatio() {
return 1 - sendSuccessRatio.getMean();
}
@Override
public double getMeanSendDuration() {
return sendDuration.getMean();
}
@Override
public double getMinSendDuration() {
return sendDuration.getMin();
}
@Override
public double getMaxSendDuration() {
return sendDuration.getMax();
}
@Override
public double getStandardDeviationSendDuration() {
return sendDuration.getStandardDeviation();
}
@Override
public Statistics getSendDuration() {
return sendDuration.getStatistics();
}
@Override
public Statistics getSendRate() {
return sendRate.getStatistics();
}
@Override
public Statistics getErrorRate() {
return sendErrorRate.getStatistics();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -14,8 +14,10 @@
* limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.channel.management;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.support.MetricType;
@@ -25,6 +27,7 @@ import org.springframework.jmx.support.MetricType;
* channel types.
*
* @author Dave Syer
* @author Gary Russell
* @since 2.0
*/
public interface MessageChannelMetrics {
@@ -32,6 +35,12 @@ public interface MessageChannelMetrics {
@ManagedOperation
void reset();
@ManagedOperation
void enableStats(boolean statsEnabled);
@ManagedAttribute
boolean isStatsEnabled();
/**
* @return the number of successful sends
*/

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2015 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.channel.management;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.support.MetricType;
/**
* @author Gary Russell
* @since 4.2
*
*/
public interface PollableChannelManagement extends MessageChannelMetrics {
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Count")
int getReceiveCount();
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Count")
long getReceiveCountLong();
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Error Count")
int getReceiveErrorCount();
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Receive Error Count")
long getReceiveErrorCountLong();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2015 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.
@@ -13,35 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.channel.management;
package org.springframework.integration.monitor;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.support.MetricType;
/**
* @author Dave Syer
* @since 2.0
* @author Gary Russell
* @since 4.2
*
*/
public class QueueChannelMetrics extends PollableChannelMetrics {
private final QueueChannel channel;
public QueueChannelMetrics(QueueChannel channel, String name) {
super(channel, name);
this.channel = channel;
}
public interface QueueChannelManagement extends PollableChannelManagement {
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "QueueChannel Queue Size")
public int getQueueSize() {
return channel.getQueueSize();
}
int getQueueSize();
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "QueueChannel Remaining Capacity")
public int getRemainingCapacity() {
return channel.getRemainingCapacity();
}
int getRemainingCapacity();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2009-2014 the original author or authors.
* Copyright 2009-2015 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
@@ -11,7 +11,9 @@
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
/**
* Cumulative statistics for a series of real numbers with higher weight given to recent data but without storing any

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2009-2014 the original author or authors.
* Copyright 2009-2015 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
@@ -11,7 +11,9 @@
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
/**
* Cumulative statistics for an event rate with higher weight given to recent data but without storing any history.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2009-2014 the original author or authors.
* Copyright 2009-2015 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
@@ -11,7 +11,9 @@
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
/**
* Cumulative statistics for success ratio with higher weight given to recent data but without storing any history.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
/**
* @author Dave Syer

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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
@@ -10,7 +10,7 @@
* 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.monitor;
package org.springframework.integration.support.management;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2015 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.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -23,11 +23,11 @@ import org.junit.Test;
/**
* @author Dave Syer
*
*
*/
public class ExponentialMovingAverageRatioTests {
private ExponentialMovingAverageRatio history = new ExponentialMovingAverageRatio(
private final ExponentialMovingAverageRatio history = new ExponentialMovingAverageRatio(
0.5, 10);
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.monitor;
package org.springframework.integration.support.management;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -28,7 +28,7 @@ import org.junit.Test;
*/
public class ExponentialMovingAverageTests {
private ExponentialMovingAverage history = new ExponentialMovingAverage(10);
private final ExponentialMovingAverage history = new ExponentialMovingAverage(10);
@Test
public void testGetCount() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 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.
@@ -21,12 +21,12 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.integration.config.IntegrationConfigurationInitializer;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
/**
* The JMX Integration infrastructure {@code beanFactory} initializer.
*
* @author Artem Bilan
* @author Gary Russell
* @since 4.0
*/
public class JmxIntegrationConfigurationInitializer implements IntegrationConfigurationInitializer {
@@ -39,10 +39,8 @@ public class JmxIntegrationConfigurationInitializer implements IntegrationConfig
}
private void registerMBeanExporterHelperIfNecessary(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.getBeanNamesForType(IntegrationMBeanExporter.class).length > 0) {
((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(MBEAN_EXPORTER_HELPER_BEAN_NAME,
new RootBeanDefinition(MBeanExporterHelper.class));
}
((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(MBEAN_EXPORTER_HELPER_BEAN_NAME,
new RootBeanDefinition(MBeanExporterHelper.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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
@@ -37,8 +37,12 @@ import org.springframework.util.StringUtils;
* of bean names that will be exported by the IntegrationMBeanExporter and merges it with the list
* of 'excludedBeans' of MBeanExporter so it will not attempt to export them again.
*
* Since 4.2, we unconditionally exclude all channels from standard context exporter (channels
* are now managed resources and would otherwise be picked up).
*
* @author Oleg Zhurakousky
* @author Artem Bilan
* @author Gary Russell
* @since 2.1
*
*/
@@ -50,10 +54,19 @@ class MBeanExporterHelper implements BeanPostProcessor, Ordered, BeanFactoryAwar
private final Set<String> siBeanNames = new HashSet<String>();
/**
* For backwards compatibility, we don't want a context MBeanExporter to export
* integration components that are now managed resources. When there *is* an IMBE,
* *all* managed resources in org.springframework.integration are exluded.
*/
private final Set<String> siBeansToExcludeWhenNoIMBE = new HashSet<String>();
private volatile DefaultListableBeanFactory beanFactory;
private volatile boolean capturedAutoChannelCandidates;
private volatile boolean hasIntegrationExporter;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
Assert.isInstanceOf(DefaultListableBeanFactory.class, beanFactory);
@@ -71,8 +84,16 @@ class MBeanExporterHelper implements BeanPostProcessor, Ordered, BeanFactoryAwar
className = ((StandardMethodMetadata) def.getSource()).getIntrospectedMethod().getReturnType().getName();
}
if (StringUtils.hasText(className)){
if (className.startsWith(SI_ROOT_PACKAGE) && !(className.endsWith(IntegrationMBeanExporter.class.getName()))){
siBeanNames.add(beanName);
if (className.startsWith(SI_ROOT_PACKAGE)
&& !(className.endsWith(IntegrationMBeanExporter.class.getName()))){
this.siBeanNames.add(beanName);
}
if (className.startsWith(SI_ROOT_PACKAGE + "channel.")
&& !(className.endsWith(IntegrationMBeanExporter.class.getName()))){
this.siBeansToExcludeWhenNoIMBE.add(beanName);
}
else if (className.equals(IntegrationMBeanExporter.class.getName())) {
this.hasIntegrationExporter = true;
}
}
}
@@ -88,6 +109,7 @@ class MBeanExporterHelper implements BeanPostProcessor, Ordered, BeanFactoryAwar
Collection<String> autoCreateChannelCandidatesNames =
(Collection<String>) new DirectFieldAccessor(autoCreateChannelCandidates).getPropertyValue("channelNames");
this.siBeanNames.addAll(autoCreateChannelCandidatesNames);
this.siBeansToExcludeWhenNoIMBE.addAll(autoCreateChannelCandidatesNames);
}
this.capturedAutoChannelCandidates = true;
}
@@ -97,9 +119,19 @@ class MBeanExporterHelper implements BeanPostProcessor, Ordered, BeanFactoryAwar
@SuppressWarnings("unchecked")
Set<String> excludedNames = (Set<String>) mbeDfa.getPropertyValue(EXCLUDED_BEANS_PROPERTY_NAME);
if (excludedNames != null) {
siBeanNames.addAll(excludedNames);
excludedNames = new HashSet<String>(excludedNames);
}
mbeDfa.setPropertyValue(EXCLUDED_BEANS_PROPERTY_NAME, siBeanNames);
else {
excludedNames = new HashSet<String>();
}
if (!this.hasIntegrationExporter) {
excludedNames.addAll(this.siBeansToExcludeWhenNoIMBE);
}
else {
excludedNames.addAll(this.siBeanNames);
}
//TODO: SF 4.1.5 and above now has additive exclusions (SPR-12686)
mbeDfa.setPropertyValue(EXCLUDED_BEANS_PROPERTY_NAME, excludedNames);
}
return bean;

View File

@@ -53,6 +53,8 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.channel.management.MessageChannelMetrics;
import org.springframework.integration.channel.management.PollableChannelManagement;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.OrderlyShutdownCapable;
import org.springframework.integration.core.MessageProducer;
@@ -61,6 +63,7 @@ import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.history.MessageHistoryConfigurer;
import org.springframework.integration.support.context.NamedComponent;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.MBeanExporter;
import org.springframework.jmx.export.UnableToRegisterMBeanException;
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
@@ -73,7 +76,6 @@ import org.springframework.jmx.export.naming.MetadataNamingStrategy;
import org.springframework.jmx.support.MetricType;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.PollableChannel;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.ReflectionUtils;
@@ -131,17 +133,17 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
private final Set<Lifecycle> inboundLifecycleMessageProducers = new HashSet<Lifecycle>();
private final Set<DirectChannelMetrics> channels = new HashSet<DirectChannelMetrics>();
private final Set<MessageChannelMetrics> channels = new HashSet<MessageChannelMetrics>();
private final Map<String, Object> exposedBeans = new HashMap<String, Object>();
private final Map<String, DirectChannelMetrics> channelsByName = new HashMap<String, DirectChannelMetrics>();
private final Map<String, MessageChannelMetrics> channelsByName = new HashMap<String, MessageChannelMetrics>();
private final Map<String, MessageHandlerMetrics> handlersByName = new HashMap<String, MessageHandlerMetrics>();
private final Map<String, MessageSourceMetrics> sourcesByName = new HashMap<String, MessageSourceMetrics>();
private final Map<String, DirectChannelMetrics> allChannelsByName = new HashMap<String, DirectChannelMetrics>();
private final Map<String, MessageChannelMetrics> allChannelsByName = new HashMap<String, MessageChannelMetrics>();
private final Map<String, MessageHandlerMetrics> allHandlersByName = new HashMap<String, MessageHandlerMetrics>();
@@ -268,23 +270,11 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
bean = advised;
}
if (bean instanceof MessageChannel) {
DirectChannelMetrics monitor;
MessageChannel target = (MessageChannel) extractTarget(bean);
if (bean instanceof PollableChannel) {
if (target instanceof QueueChannel) {
monitor = new QueueChannelMetrics((QueueChannel) target, beanName);
}
else {
monitor = new PollableChannelMetrics(target, beanName);
}
}
else {
monitor = new DirectChannelMetrics(target, beanName);
}
Object advised = applyChannelInterceptor(bean, monitor, beanClassLoader);
if (bean instanceof MessageChannel && bean instanceof MessageChannelMetrics
&& bean instanceof NamedComponent) {
MessageChannelMetrics monitor = (MessageChannelMetrics) extractTarget(bean);
monitor.enableStats(true);//TODO: INT-3638
channels.add(monitor);
bean = advised;
}
if (bean instanceof MessageProducer && bean instanceof Lifecycle) {
@@ -575,9 +565,9 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
@ManagedOperation
public void stopActiveChannels() {
// Stop any "active" channels (JMS etc).
for (Entry<String, DirectChannelMetrics> entry : this.allChannelsByName.entrySet()) {
DirectChannelMetrics metrics = entry.getValue();
MessageChannel channel = metrics.getMessageChannel();
for (Entry<String, MessageChannelMetrics> entry : this.allChannelsByName.entrySet()) {
MessageChannelMetrics metrics = entry.getValue();
MessageChannel channel = (MessageChannel) metrics;
if (channel instanceof Lifecycle) {
if (logger.isInfoEnabled()) {
logger.info("Stopping channel " + channel);
@@ -648,8 +638,8 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
public int getQueuedMessageCount() {
int count = 0;
for (MessageChannelMetrics monitor : channels) {
if (monitor instanceof QueueChannelMetrics) {
count += ((QueueChannelMetrics) monitor).getQueueSize();
if (monitor instanceof QueueChannel) {
count += ((QueueChannel) monitor).getQueueSize();
}
}
return count;
@@ -686,8 +676,8 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
public long getChannelReceiveCountLong(String name) {
if (channelsByName.containsKey(name)) {
if (channelsByName.get(name) instanceof PollableChannelMetrics) {
return ((PollableChannelMetrics) channelsByName.get(name)).getReceiveCountLong();
if (channelsByName.get(name) instanceof PollableChannelManagement) {
return ((PollableChannelManagement) channelsByName.get(name)).getReceiveCountLong();
}
}
logger.debug("No channel found for (" + name + ")");
@@ -720,8 +710,8 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
}
private void registerChannels() {
for (DirectChannelMetrics monitor : channels) {
String name = monitor.getName();
for (MessageChannelMetrics monitor : channels) {
String name = ((NamedComponent) monitor).getComponentName();
this.allChannelsByName.put(name, monitor);
if (!PatternMatchUtils.simpleMatch(this.componentNamePatterns, name)) {
continue;
@@ -734,12 +724,6 @@ 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,
this.getMonitoredIntegrationObjectBeanKey(bean, name));
}
}
}
}
@@ -830,13 +814,6 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
}
}
private Object applyChannelInterceptor(Object bean, DirectChannelMetrics interceptor, ClassLoader beanClassLoader) {
NameMatchMethodPointcutAdvisor channelsAdvice = new NameMatchMethodPointcutAdvisor(interceptor);
channelsAdvice.addMethodName("send");
channelsAdvice.addMethodName("receive");
return applyAdvice(bean, channelsAdvice, beanClassLoader);
}
private Object applyHandlerInterceptor(Object bean, SimpleMessageHandlerMetrics interceptor,
ClassLoader beanClassLoader) {
NameMatchMethodPointcutAdvisor handlerAdvice = new NameMatchMethodPointcutAdvisor(interceptor);

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.monitor;
import org.springframework.context.Lifecycle;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;

View File

@@ -16,6 +16,7 @@
package org.springframework.integration.monitor;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.support.MetricType;

View File

@@ -23,6 +23,8 @@ import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.support.management.ExponentialMovingAverage;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;

View File

@@ -64,6 +64,7 @@
<value type="java.lang.String">SendCountLong</value>
<value type="java.lang.String">SendErrorCount</value>
<value type="java.lang.String">SendErrorCountLong</value>
<value type="java.lang.String">StatsEnabled</value>
</array>
</constructor-arg>
</bean>

View File

@@ -21,16 +21,15 @@ import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -95,7 +94,6 @@ public class DynamicRouterTests {
}
@Test @DirtiesContext
@Ignore // Requires Spring 3.2.3 TODO: Remove when minimum SF is >= 3.2.3
public void testRouteChangeMapNamedArgs() throws Exception {
routingChannel.send(new GenericMessage<String>("123"));
assertEquals("123", processAChannel.receive(0).getPayload());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 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.
@@ -33,7 +33,6 @@ import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextInitializer;
@@ -42,7 +41,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.integration.test.util.TestUtils;
@@ -54,6 +52,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Artem Bilan
* @author Gary Russell
* @since 4.0
*/
@ContextConfiguration(initializers = EnableMBeanExportTests.EnvironmentApplicationContextInitializer.class)
@@ -73,8 +72,6 @@ public class EnableMBeanExportTests {
@SuppressWarnings("unchecked")
@Test
public void testEnableMBeanExport() throws MalformedObjectNameException, ClassNotFoundException {
assertTrue(AopUtils.isAopProxy(this.beanFactory.getBean(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)));
assertTrue(AopUtils.isAopProxy(this.beanFactory.getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)));
assertSame(this.mBeanServer, this.exporter.getServer());
String[] componentNamePatterns = TestUtils.getPropertyValue(this.exporter, "componentNamePatterns", String[].class);

View File

@@ -34,6 +34,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.context.OrderlyShutdownCapable;
@@ -350,17 +351,12 @@ public class MBeanExporterIntegrationTests {
boolean isStopCalled();
}
public static class ActiveChannelImpl implements MessageChannel, Lifecycle, ActiveChannel {
public static class ActiveChannelImpl extends AbstractMessageChannel implements Lifecycle, ActiveChannel {
private boolean stopCalled;
@Override
public boolean send(Message<?> message) {
return false;
}
@Override
public boolean send(Message<?> message, long timeout) {
protected boolean doSend(Message<?> message, long timeout) {
return false;
}

View File

@@ -1,3 +1,15 @@
/*
* Copyright 2011-2015 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.monitor;
import static org.hamcrest.Matchers.equalTo;
@@ -8,22 +20,23 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.integration.channel.NullChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessagingException;
import org.springframework.integration.channel.NullChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessagingException;
import org.springframework.util.ClassUtils;
/**
* @author Tareq Abedrabbo
* @author Dave Syer
* @author Gary Russell
* @since 2.0.4
*/
public class MessageMetricsAdviceTests {
@@ -72,19 +85,6 @@ public class MessageMetricsAdviceTests {
exported.handleMessage(MessageBuilder.withPayload("test").build());
}
@Test
public void adviceExportedChannel() throws Exception {
Advised advised = (Advised) mBeanExporter.postProcessAfterInitialization(channel, "testChannel");
DummyInterceptor interceptor = new DummyInterceptor();
advised.addAdvice(interceptor);
assertThat(advised.getAdvisors().length, equalTo(2));
((MessageChannel) advised).send(MessageBuilder.withPayload("test").build());
assertThat(interceptor.invoked, is(true));
}
@Test
public void exportAdvisedChannel() throws Exception {
@@ -105,6 +105,7 @@ public class MessageMetricsAdviceTests {
@SuppressWarnings("unused")
boolean invoked = false;
@Override
public void handleMessage(Message<?> message) throws MessagingException {
invoked = true;
}
@@ -114,6 +115,7 @@ public class MessageMetricsAdviceTests {
boolean invoked = false;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
invoked = true;
return invocation.proceed();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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
@@ -13,16 +13,18 @@
package org.springframework.integration_.mbeanexporterhelper;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*
*/
public class INT_2626Tests {
@Test // This context failed to load before the INT-2626 fix was applied
public void testInt2626(){
new ClassPathXmlApplicationContext("INT-2626-config.xml", this.getClass());
new ClassPathXmlApplicationContext("INT-2626-config.xml", this.getClass()).close();
}
}