/* * Copyright 2002-2017 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.handler; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.springframework.core.Ordered; import org.springframework.integration.context.IntegrationObjectSupport; import org.springframework.integration.context.Orderable; import org.springframework.integration.history.MessageHistory; import org.springframework.integration.support.management.AbstractMessageHandlerMetrics; import org.springframework.integration.support.management.ConfigurableMetricsAware; import org.springframework.integration.support.management.DefaultMessageHandlerMetrics; import org.springframework.integration.support.management.IntegrationManagedResource; import org.springframework.integration.support.management.MessageHandlerMetrics; import org.springframework.integration.support.management.MetricsContext; import org.springframework.integration.support.management.Statistics; import org.springframework.integration.support.management.TrackableComponent; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.MessagingException; import org.springframework.util.Assert; /** * Base class for MessageHandler implementations that provides basic validation * and error handling capabilities. Asserts that the incoming Message is not * null and that it does not contain a null payload. Converts checked exceptions * into runtime {@link MessagingException}s. * * @author Mark Fisher * @author Oleg Zhurakousky * @author Gary Russell */ @IntegrationManagedResource public abstract class AbstractMessageHandler extends IntegrationObjectSupport implements MessageHandler, MessageHandlerMetrics, ConfigurableMetricsAware<AbstractMessageHandlerMetrics>, TrackableComponent, Orderable, Subscriber<Message<?>> { private volatile boolean shouldTrack = false; private volatile int order = Ordered.LOWEST_PRECEDENCE; private volatile AbstractMessageHandlerMetrics handlerMetrics = new DefaultMessageHandlerMetrics(); private volatile boolean statsEnabled; private volatile boolean countsEnabled; private volatile String managedName; private volatile String managedType; private volatile boolean loggingEnabled = true; @Override public boolean isLoggingEnabled() { return this.loggingEnabled; } @Override public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; } @Override public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } @Override public String getComponentType() { return "message-handler"; } @Override public void setShouldTrack(boolean shouldTrack) { this.shouldTrack = shouldTrack; } @Override public void configureMetrics(AbstractMessageHandlerMetrics metrics) { Assert.notNull(metrics, "'metrics' must not be null"); this.handlerMetrics = metrics; } @Override protected void onInit() throws Exception { if (this.statsEnabled) { this.handlerMetrics.setFullStatsEnabled(true); } } @Override public void handleMessage(Message<?> message) { Assert.notNull(message, "Message must not be null"); Assert.notNull(message.getPayload(), "Message payload must not be null"); //NOSONAR - false positive if (this.loggingEnabled && this.logger.isDebugEnabled()) { this.logger.debug(this + " received message: " + message); } MetricsContext start = null; boolean countsEnabled = this.countsEnabled; AbstractMessageHandlerMetrics handlerMetrics = this.handlerMetrics; try { if (this.shouldTrack) { message = MessageHistory.write(message, this, this.getMessageBuilderFactory()); } if (countsEnabled) { start = handlerMetrics.beforeHandle(); } this.handleMessageInternal(message); if (countsEnabled) { handlerMetrics.afterHandle(start, true); } } catch (Exception e) { if (countsEnabled) { handlerMetrics.afterHandle(start, false); } if (e instanceof MessagingException) { throw (MessagingException) e; } throw new MessageHandlingException(message, "error occurred in message handler [" + this + "]", e); } } @Override public void onSubscribe(Subscription subscription) { Assert.notNull(subscription, "'subscription' must not be null"); subscription.request(Long.MAX_VALUE); } @Override public void onNext(Message<?> message) { handleMessage(message); } @Override public void onError(Throwable throwable) { } @Override public void onComplete() { } protected abstract void handleMessageInternal(Message<?> message) throws Exception; @Override public void reset() { this.handlerMetrics.reset(); } @Override public long getHandleCountLong() { return this.handlerMetrics.getHandleCountLong(); } @Override public int getHandleCount() { return this.handlerMetrics.getHandleCount(); } @Override public int getErrorCount() { return this.handlerMetrics.getErrorCount(); } @Override public long getErrorCountLong() { return this.handlerMetrics.getErrorCountLong(); } @Override public double getMeanDuration() { return this.handlerMetrics.getMeanDuration(); } @Override public double getMinDuration() { return this.handlerMetrics.getMinDuration(); } @Override public double getMaxDuration() { return this.handlerMetrics.getMaxDuration(); } @Override public double getStandardDeviationDuration() { return this.handlerMetrics.getStandardDeviationDuration(); } @Override public int getActiveCount() { return this.handlerMetrics.getActiveCount(); } @Override public long getActiveCountLong() { return this.handlerMetrics.getActiveCountLong(); } @Override public Statistics getDuration() { return this.handlerMetrics.getDuration(); } @Override public void setStatsEnabled(boolean statsEnabled) { if (statsEnabled) { this.countsEnabled = true; } this.statsEnabled = statsEnabled; if (this.handlerMetrics != null) { this.handlerMetrics.setFullStatsEnabled(statsEnabled); } } @Override public boolean isStatsEnabled() { return this.statsEnabled; } @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; if (!countsEnabled) { this.statsEnabled = false; } } @Override public boolean isCountsEnabled() { return this.countsEnabled; } @Override public void setManagedName(String managedName) { this.managedName = managedName; } @Override public String getManagedName() { return this.managedName; } @Override public void setManagedType(String managedType) { this.managedType = managedType; } @Override public String getManagedType() { return this.managedType; } }