INT-2431 Improve 'Dispatcher Has No Subscribers'
Add channel name to MessageDeliveryException
'Dispatcher has no subscribers'.
In a large integration flow, it can be difficult to track
down which subscribable channel has no subscribers.
This commit adds to the message text in the form
for channel someChannelName
to the exception message. For example:
"Dispatcher has no subscribers for channel myChannel."
Also
for amqp-channel someAmqpChannelName
for jms-channel someJMSChannelName
for redis-channel someJMSChannelName
INT-2431 Polishing
Make component type and name immutable once set to avoid
channels further down the stack frame claiming ownership.
INT-2431 Polishing
* PR Comments - use a new Exception type
* Add support for Redis
* Add WARN logs for AMQP/JMS pub-sub channels
INT-2431 Polishing
PR Comments: tighten up isPubSub field in AMQP-backed channel.
INT-2431 Polishing
Ensure channel name is not 'null' or empty string.
This commit is contained in:
committed by
Oleg Zhurakousky
parent
0b649abfaa
commit
f75dc53ab0
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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;
|
||||
|
||||
import org.springframework.integration.dispatcher.MessageDispatcher;
|
||||
|
||||
/**
|
||||
* Exception that indicates an internal error occurred within
|
||||
* a {@link MessageDispatcher} preventing message delivery.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageDispatchingException extends MessageDeliveryException {
|
||||
|
||||
public MessageDispatchingException(String description) {
|
||||
super(description);
|
||||
}
|
||||
|
||||
public MessageDispatchingException(Message<?> undeliveredMessage,
|
||||
String description, Throwable cause) {
|
||||
super(undeliveredMessage, description, cause);
|
||||
}
|
||||
|
||||
public MessageDispatchingException(Message<?> undeliveredMessage,
|
||||
String description) {
|
||||
super(undeliveredMessage, description);
|
||||
}
|
||||
|
||||
public MessageDispatchingException(Message<?> undeliveredMessage) {
|
||||
super(undeliveredMessage);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -20,11 +20,14 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageDispatchingException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.SubscribableChannel;
|
||||
import org.springframework.integration.dispatcher.MessageDispatcher;
|
||||
import org.springframework.integration.dispatcher.UnicastingDispatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base implementation of {@link MessageChannel} that invokes the subscribed
|
||||
@@ -32,6 +35,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class AbstractSubscribableChannel extends AbstractMessageChannel implements SubscribableChannel {
|
||||
|
||||
@@ -58,7 +62,15 @@ public abstract class AbstractSubscribableChannel extends AbstractMessageChannel
|
||||
|
||||
@Override
|
||||
protected boolean doSend(Message<?> message, long timeout) {
|
||||
return this.getRequiredDispatcher().dispatch(message);
|
||||
try {
|
||||
return this.getRequiredDispatcher().dispatch(message);
|
||||
}
|
||||
catch (MessageDispatchingException e) {
|
||||
String componentName = this.getComponentName();
|
||||
componentName = StringUtils.hasText(componentName) ? componentName : "unknown";
|
||||
throw new MessageDeliveryException(message, e.getMessage()
|
||||
+ " for channel " + componentName + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageDispatcher getRequiredDispatcher() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageDispatchingException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
@@ -40,6 +41,8 @@ import org.springframework.integration.support.MessageBuilder;
|
||||
*/
|
||||
public class BroadcastingDispatcher extends AbstractDispatcher {
|
||||
|
||||
private final boolean requireSubscribers;
|
||||
|
||||
private volatile boolean ignoreFailures;
|
||||
|
||||
private volatile boolean applySequence;
|
||||
@@ -47,10 +50,19 @@ public class BroadcastingDispatcher extends AbstractDispatcher {
|
||||
private final Executor executor;
|
||||
|
||||
public BroadcastingDispatcher() {
|
||||
this.executor = null;
|
||||
this(null, false);
|
||||
}
|
||||
|
||||
public BroadcastingDispatcher(Executor executor) {
|
||||
this(executor, false);
|
||||
}
|
||||
|
||||
public BroadcastingDispatcher(boolean requireSubscribers) {
|
||||
this(null, requireSubscribers);
|
||||
}
|
||||
|
||||
public BroadcastingDispatcher(Executor executor, boolean requireSubscribers) {
|
||||
this.requireSubscribers = requireSubscribers;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@@ -80,6 +92,9 @@ public class BroadcastingDispatcher extends AbstractDispatcher {
|
||||
boolean dispatched = false;
|
||||
int sequenceNumber = 1;
|
||||
List<MessageHandler> handlers = this.getHandlers();
|
||||
if (this.requireSubscribers && handlers.size() == 0) {
|
||||
throw new MessageDispatchingException(message, "Dispatcher has no subscribers");
|
||||
}
|
||||
int sequenceSize = handlers.size();
|
||||
for (final MessageHandler handler : handlers) {
|
||||
final Message<?> messageToSend = (!this.applySequence) ? message : MessageBuilder.fromMessage(message)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2002-2010 the original author or authors.
|
||||
/* Copyright 2002-2012 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.
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageDispatchingException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
|
||||
@@ -105,7 +106,7 @@ public class UnicastingDispatcher extends AbstractDispatcher {
|
||||
boolean success = false;
|
||||
Iterator<MessageHandler> handlerIterator = this.getHandlerIterator(message);
|
||||
if (!handlerIterator.hasNext()) {
|
||||
throw new MessageDeliveryException(message, "Dispatcher has no subscribers.");
|
||||
throw new MessageDispatchingException(message, "Dispatcher has no subscribers");
|
||||
}
|
||||
List<RuntimeException> exceptions = new ArrayList<RuntimeException>();
|
||||
while (success == false && handlerIterator.hasNext()) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<channel id="subscribedChannel" />
|
||||
|
||||
<bridge input-channel="subscribedChannel" output-channel="noSubscribersChannel" />
|
||||
|
||||
<channel id="noSubscribersChannel" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DispatcherHasNoSubscribersTests {
|
||||
|
||||
@Autowired
|
||||
MessageChannel noSubscribersChannel;
|
||||
|
||||
@Autowired
|
||||
MessageChannel subscribedChannel;
|
||||
|
||||
@Test
|
||||
public void oneChannel() {
|
||||
try {
|
||||
noSubscribersChannel.send(new GenericMessage<String>("Hello, world!"));
|
||||
fail("Exception expected");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Dispatcher has no subscribers for channel noSubscribersChannel.", e.getMessage());
|
||||
assertEquals("Dispatcher has no subscribers for channel noSubscribersChannel.", e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stackedChannels() {
|
||||
try {
|
||||
subscribedChannel.send(new GenericMessage<String>("Hello, world!"));
|
||||
fail("Exception expected");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Dispatcher has no subscribers for channel noSubscribersChannel.", e.getMessage());
|
||||
assertEquals("Dispatcher has no subscribers for channel noSubscribersChannel.", e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user