GH-2748: Add bean definition info into exceptions (#2986)
* GH-2748: Add bean definition info into exceptions Fixes https://github.com/spring-projects/spring-integration/issues/2748 In many cases Spring Integration stack traces doesn't contain any relations to end-user code. Just because a target project code mostly contains only a configuration for out-of-the-box components without any custom code. When exception is thrown from such an out-of-the-box component, it is hard from the stack trace to determine a configuration source for those components. * Add a logic into the `IntegrationObjectSupport` to obtain a its own `BeanDefinition` from the `BeanFactory` to include a `resource` and `source` (if any) into the `toString()` representation, as well as add a new `getBeanDescription()` to get such an info at runtime * The `toString()` is simply used by `this` reference in the message for `MessagingException` thrown from the `IntegrationObjectSupport` implementations * Modify an exception message for the `MessageTransformingHandler` and `MessageFilter` to make it based on `this`. The `AbstractMessageHandler` already includes `this` into its exception message * Modify a `AbstractConsumerEndpointParser` and `AbstractAmqpInboundAdapterParser` (as a sample) to include a `resource` and `source` into a `MessageHandler` `BeanDefinition`. * Include an `IntegrationFlow` `BeanDefinition` `resource` (`@Configuration` class) and its bean method as a `source` into all child beans declared during flow parsing in the `IntegrationFlowBeanPostProcessor` * Add `IntegrationFlowRegistrationBuilder.setSource()` for manually registered flows: there is no configuration parsing phase to extract such an info from `BeanFactory` * Propagate that `source` into all the child beans provided by the `IntegrationFlow` * Modify a `LambdaMessageProcessor` exception message to include a method info in case of `InvocationTargetException` * Do not cast explicitly for `ConfigurableListableBeanFactory` in the `IntegrationObjectSupport` to avoid tests modifications for mocking directly into `ConfigurableListableBeanFactory`. Use `instanceof` instead in the `getBeanDescription()` * * Fix Checkstyle issues * * Fix `IntegrationGraphServer` and `IntegrationMBeanExporter` to rely on the `NamedComponent` for channel names instead of always call `toString()` which is now much more than just a bean name * Don't describe a `componentName` if it is the same as a `beanName` * Check for parent `BeanDefinition` in the `IntegrationFlowBeanPostProcessor` before calling its meta-info * Fix tests according new `IntegrationObjectSupport.toString()` behavior
This commit is contained in:
committed by
Gary Russell
parent
ebb22c2ed4
commit
c712416b63
@@ -22,6 +22,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.support.context.NamedComponent;
|
||||
import org.springframework.integration.support.management.BaseHandlerMetrics;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Dave Syer
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@@ -54,28 +56,27 @@ public class ChannelIntegrationTests {
|
||||
@Autowired
|
||||
private IntegrationMBeanExporter messageChannelsMonitor;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testMessageChannelStatistics() throws Exception {
|
||||
public void testMessageChannelStatistics() {
|
||||
this.requests.send(new GenericMessage<>("foo"));
|
||||
|
||||
requests.send(new GenericMessage<String>("foo"));
|
||||
|
||||
String intermediateChannelName = "" + intermediate;
|
||||
String intermediateChannelName = ((NamedComponent) this.intermediate).getBeanName();
|
||||
|
||||
assertThat(messageChannelsMonitor.getChannelSendCount(intermediateChannelName)).isEqualTo(1);
|
||||
|
||||
double rate = messageChannelsMonitor.getChannelSendRate("" + requests).getMean();
|
||||
assertThat(rate >= 0).as("No statistics for requests channel").isTrue();
|
||||
double rate =
|
||||
messageChannelsMonitor.getChannelSendRate(((NamedComponent) this.requests).getBeanName()).getMean();
|
||||
assertThat(rate).as("No statistics for requests channel").isGreaterThanOrEqualTo(0);
|
||||
|
||||
rate = messageChannelsMonitor.getChannelSendRate(intermediateChannelName).getMean();
|
||||
assertThat(rate >= 0).as("No statistics for intermediate channel").isTrue();
|
||||
assertThat(rate).as("No statistics for intermediate channel").isGreaterThanOrEqualTo(0);
|
||||
|
||||
assertThat(intermediate.receive(100L)).isNotNull();
|
||||
assertThat(messageChannelsMonitor.getChannelReceiveCount(intermediateChannelName)).isEqualTo(1);
|
||||
|
||||
requests.send(new GenericMessage<String>("foo"));
|
||||
requests.send(new GenericMessage<>("foo"));
|
||||
try {
|
||||
requests.send(new GenericMessage<String>("foo"));
|
||||
requests.send(new GenericMessage<>("foo"));
|
||||
}
|
||||
catch (@SuppressWarnings("unused") MessageDeliveryException e) {
|
||||
}
|
||||
@@ -94,9 +95,8 @@ public class ChannelIntegrationTests {
|
||||
|
||||
assertThat(this.sourceChannel.receive(10000)).isNotNull();
|
||||
|
||||
assertThat(messageChannelsMonitor.getSourceMessageCount("source") > 0).isTrue();
|
||||
assertThat(messageChannelsMonitor.getSourceMetrics("source").getMessageCount() > 0).isTrue();
|
||||
|
||||
assertThat(messageChannelsMonitor.getSourceMessageCount("source")).isGreaterThan(0);
|
||||
assertThat(messageChannelsMonitor.getSourceMetrics("source").getMessageCount()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
*/
|
||||
public class HandlerMonitoringIntegrationTests {
|
||||
|
||||
private static Log logger = LogFactory.getLog(HandlerMonitoringIntegrationTests.class);
|
||||
private static final Log logger = LogFactory.getLog(HandlerMonitoringIntegrationTests.class);
|
||||
|
||||
private MessageChannel channel;
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.channel.interceptor.WireTap;
|
||||
import org.springframework.integration.support.context.NamedComponent;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
@@ -48,7 +50,7 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
|
||||
private static Log logger = LogFactory.getLog(MessageChannelsMonitorIntegrationTests.class);
|
||||
|
||||
private MessageChannel channel;
|
||||
private AbstractMessageChannel channel;
|
||||
|
||||
private Service service;
|
||||
|
||||
@@ -75,7 +77,7 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
@Test
|
||||
public void testRates() throws Exception {
|
||||
try (ClassPathXmlApplicationContext context = createContext("anonymous-channel.xml")) {
|
||||
this.channel = context.getBean("anonymous", MessageChannel.class);
|
||||
this.channel = context.getBean("anonymous", AbstractMessageChannel.class);
|
||||
int before = service.getCounter();
|
||||
CountDownLatch latch = new CountDownLatch(50);
|
||||
service.setLatch(latch);
|
||||
@@ -87,9 +89,9 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
assertThat(service.getCounter()).isEqualTo(before + 50);
|
||||
|
||||
// The handler monitor is registered under the endpoint id (since it is explicit)
|
||||
int sends = messageChannelsMonitor.getChannelSendRate("" + channel).getCount();
|
||||
int sends = messageChannelsMonitor.getChannelSendRate(this.channel.getBeanName()).getCount();
|
||||
assertThat(sends).as("No send statistics for input channel").isEqualTo(50);
|
||||
long sendsLong = messageChannelsMonitor.getChannelSendRate("" + channel).getCountLong();
|
||||
long sendsLong = messageChannelsMonitor.getChannelSendRate(this.channel.getBeanName()).getCountLong();
|
||||
assertThat(sends).as("No send statistics for input channel").isEqualTo(sendsLong);
|
||||
|
||||
}
|
||||
@@ -98,7 +100,7 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
@Test
|
||||
public void testErrors() throws Exception {
|
||||
try (ClassPathXmlApplicationContext context = createContext("anonymous-channel.xml")) {
|
||||
this.channel = context.getBean("anonymous", MessageChannel.class);
|
||||
this.channel = context.getBean("anonymous", AbstractMessageChannel.class);
|
||||
int before = service.getCounter();
|
||||
CountDownLatch latch = new CountDownLatch(10);
|
||||
service.setLatch(latch);
|
||||
@@ -120,9 +122,9 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
assertThat(service.getCounter()).isEqualTo(before + 10);
|
||||
|
||||
// The handler monitor is registered under the endpoint id (since it is explicit)
|
||||
int sends = messageChannelsMonitor.getChannelSendRate("" + channel).getCount();
|
||||
int sends = messageChannelsMonitor.getChannelSendRate(this.channel.getBeanName()).getCount();
|
||||
assertThat(sends).as("No send statistics for input channel").isEqualTo(11);
|
||||
int errors = messageChannelsMonitor.getChannelErrorRate("" + channel).getCount();
|
||||
int errors = messageChannelsMonitor.getChannelErrorRate(this.channel.getBeanName()).getCount();
|
||||
assertThat(errors).as("No error statistics for input channel").isEqualTo(1);
|
||||
}
|
||||
}
|
||||
@@ -130,7 +132,7 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
@Test
|
||||
public void testQueues() throws Exception {
|
||||
try (ClassPathXmlApplicationContext context = createContext("queue-channel.xml")) {
|
||||
this.channel = context.getBean("queue", MessageChannel.class);
|
||||
this.channel = context.getBean("queue", AbstractMessageChannel.class);
|
||||
int before = service.getCounter();
|
||||
CountDownLatch latch = new CountDownLatch(10);
|
||||
service.setLatch(latch);
|
||||
@@ -152,18 +154,18 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
assertThat(service.getCounter()).isEqualTo(before + 10);
|
||||
|
||||
// The handler monitor is registered under the endpoint id (since it is explicit)
|
||||
int sends = messageChannelsMonitor.getChannelSendRate("" + channel).getCount();
|
||||
int sends = messageChannelsMonitor.getChannelSendRate(this.channel.getBeanName()).getCount();
|
||||
assertThat(sends).as("No send statistics for input channel").isEqualTo(11);
|
||||
int receives = messageChannelsMonitor.getChannelReceiveCount("" + channel);
|
||||
int receives = messageChannelsMonitor.getChannelReceiveCount(this.channel.getBeanName());
|
||||
assertThat(receives).as("No send statistics for input channel").isEqualTo(11);
|
||||
int errors = messageChannelsMonitor.getChannelErrorRate("" + channel).getCount();
|
||||
int errors = messageChannelsMonitor.getChannelErrorRate(this.channel.getBeanName()).getCount();
|
||||
assertThat(errors).as("Expect no errors for input channel (handler fails)").isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void doTest(String config, String channelName) throws Exception {
|
||||
try (ClassPathXmlApplicationContext context = createContext(config)) {
|
||||
this.channel = context.getBean(channelName, MessageChannel.class);
|
||||
MessageChannel channel = context.getBean(channelName, MessageChannel.class);
|
||||
int before = service.getCounter();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
service.setLatch(latch);
|
||||
@@ -172,7 +174,7 @@ public class MessageChannelsMonitorIntegrationTests {
|
||||
assertThat(service.getCounter()).isEqualTo(before + 1);
|
||||
|
||||
// The handler monitor is registered under the endpoint id (since it is explicit)
|
||||
int sends = messageChannelsMonitor.getChannelSendRate("" + channel).getCount();
|
||||
int sends = messageChannelsMonitor.getChannelSendRate(((NamedComponent) channel).getBeanName()).getCount();
|
||||
assertThat(sends).as("No statistics for input channel").isEqualTo(1);
|
||||
|
||||
assertThat(channel).isInstanceOf(InterceptableChannel.class);
|
||||
|
||||
Reference in New Issue
Block a user