Skip to content

Commit 4a55fa3

Browse files
artembilangaryrussell
authored andcommitted
Fix IntegrationMBeanExporter logic for endpoints
Related to https://stackoverflow.com/questions/72851234/error-in-startup-application-when-using-serviceactivator-in-spring-cloud-stream The `MessagingAnnotationPostProcessor` register an `endpoint` bean for Messaging Annotation on POJO methods. The `IntegrationMBeanExporter` post-process such a bean and registers respective MBean. It does this not in optimal way scanning all the `IntegrationConsumer` beans for requested `MessageHandler` which may cause a `BeanCurrentlyInCreationException`. * Rework the logic of the `IntegrationMBeanExporter.postProcessAbstractEndpoint()` to propagate provided endpoint for the monitor registration to bypass application context scanning for matched name. * Swap `equals()` for `monitor` since an `extractTarget()` may return `null` * Some other code clean in the `IntegrationMBeanExporter` * Change one of the `@ServiceActivator` in the configuration for the `ScatterGatherHandlerIntegrationTests` to POJO method. However, this didn't fail for me with original code unlike in the sample application provided in the mentioned SO thread. **Cherry-pick to `main`**
1 parent 733eb40 commit 4a55fa3

File tree

2 files changed

+39
-45
lines changed

2 files changed

+39
-45
lines changed

spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ private void postProcessAbstractEndpoint(Object bean) {
334334
MessageHandler handler = integrationConsumer.getHandler();
335335
MessageHandler monitor = (MessageHandler) extractTarget(handler);
336336
if (monitor instanceof IntegrationManagement) {
337-
registerHandler((IntegrationManagement) monitor);
337+
registerHandler((IntegrationManagement) monitor, integrationConsumer);
338338
this.handlers.put(((IntegrationManagement) monitor).getComponentName(),
339339
(IntegrationManagement) monitor);
340340
this.runtimeBeans.add(monitor);
@@ -656,8 +656,12 @@ private void registerHandlers() {
656656

657657
}
658658

659-
private void registerHandler(IntegrationManagement monitor2) {
660-
IntegrationManagement monitor = enhanceHandlerMonitor(monitor2);
659+
private void registerHandler(IntegrationManagement monitor) {
660+
registerHandler(monitor, null);
661+
}
662+
663+
private void registerHandler(IntegrationManagement monitor2, @Nullable IntegrationConsumer consumer) {
664+
IntegrationManagement monitor = enhanceHandlerMonitor(monitor2, consumer);
661665
String name = monitor.getComponentName();
662666
if (!this.objectNames.containsKey(monitor2) && matches(this.componentNamePatterns, name)) {
663667
String beanKey = getHandlerBeanKey(monitor);
@@ -809,44 +813,47 @@ private String getStaticNames() {
809813
.collect(Collectors.joining(","));
810814
}
811815

812-
@SuppressWarnings("unlikely-arg-type")
813-
private IntegrationManagement enhanceHandlerMonitor(IntegrationManagement monitor2) {
816+
private IntegrationManagement enhanceHandlerMonitor(IntegrationManagement monitor,
817+
@Nullable IntegrationConsumer consumer) {
814818

815-
if (monitor2.getManagedName() != null && monitor2.getManagedType() != null) {
816-
return monitor2;
819+
if (monitor.getManagedName() != null && monitor.getManagedType() != null) {
820+
return monitor;
817821
}
818822

819-
// Assignment algorithm and bean id, with bean id pulled reflectively out of enclosing endpoint if possible
820-
String[] names = this.applicationContext.getBeanNamesForType(IntegrationConsumer.class);
821-
822-
String name = null;
823823
String endpointName = null;
824824
String source = "endpoint";
825-
IntegrationConsumer endpoint = null;
825+
IntegrationConsumer endpoint = consumer;
826826

827-
for (String beanName : names) {
828-
endpoint = this.applicationContext.getBean(beanName, IntegrationConsumer.class);
829-
try {
830-
MessageHandler handler = endpoint.getHandler();
831-
if (handler.equals(monitor2) ||
832-
extractTarget(handlerInAnonymousWrapper(handler)).equals(monitor2)) {
833-
name = beanName;
834-
endpointName = beanName;
835-
break;
827+
if (endpoint == null) {
828+
// Assignment algorithm and bean id, with bean id pulled reflectively out of enclosing endpoint if possible
829+
String[] names = this.applicationContext.getBeanNamesForType(IntegrationConsumer.class);
830+
831+
for (String beanName : names) {
832+
endpoint = this.applicationContext.getBean(beanName, IntegrationConsumer.class);
833+
try {
834+
MessageHandler handler = endpoint.getHandler();
835+
if (handler.equals(monitor) || monitor.equals(extractTarget(handlerInAnonymousWrapper(handler)))) {
836+
endpointName = beanName;
837+
break;
838+
}
839+
}
840+
catch (Exception ex) {
841+
logger.trace("Could not get handler from bean = " + beanName, ex);
842+
endpoint = null;
836843
}
837-
}
838-
catch (Exception e) {
839-
logger.trace("Could not get handler from bean = " + beanName, e);
840-
endpoint = null;
841844
}
842845
}
846+
else {
847+
endpointName = endpoint.getBeanName();
848+
}
843849

844850
IntegrationManagement messageHandlerMetrics =
845-
buildMessageHandlerMetrics(monitor2, name, source, endpoint);
851+
buildMessageHandlerMetrics(monitor, endpointName, source, endpoint);
846852
if (endpointName != null) {
847853
this.endpointsByMonitor.put(messageHandlerMetrics, endpointName);
848854
}
849855
return messageHandlerMetrics;
856+
850857
}
851858

852859
private IntegrationManagement buildMessageHandlerMetrics(
@@ -869,7 +876,7 @@ private IntegrationManagement buildMessageHandlerMetrics(
869876
}
870877

871878
if (managedName == null) {
872-
managedName = ((NamedComponent) monitor2).getComponentName();
879+
managedName = monitor2.getComponentName();
873880
if (managedName == null) {
874881
managedName = monitor2.toString();
875882
}
@@ -902,7 +909,6 @@ private String getInternalComponentName(String name) {
902909
}
903910

904911
private IntegrationInboundManagement enhanceSourceMonitor(IntegrationInboundManagement source2) {
905-
906912
if (source2.getManagedName() != null) {
907913
return source2;
908914
}
@@ -958,8 +964,8 @@ private IntegrationInboundManagement buildMessageSourceMetricsIfAny(
958964
try {
959965
target = targetSource.getTarget();
960966
}
961-
catch (Exception e) {
962-
logger.error("Could not get handler from bean = " + managedName);
967+
catch (Exception ex) {
968+
logger.error("Could not get handler from bean = " + managedName, ex);
963969
}
964970
}
965971

spring-integration-jmx/src/test/java/org/springframework/integration/monitor/ScatterGatherHandlerIntegrationTests.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -333,21 +333,9 @@ public MessageChannel serviceChannel2() {
333333
return new DirectChannel();
334334
}
335335

336-
@Bean
337-
@ServiceActivator(inputChannel = "serviceChannel2")
338-
public MessageHandler service2() {
339-
return new AbstractReplyProducingMessageHandler() {
340-
341-
{
342-
setOutputChannel(gatherChannel());
343-
}
344-
345-
@Override
346-
protected Object handleRequestMessage(Message<?> requestMessage) {
347-
return Math.random();
348-
}
349-
350-
};
336+
@ServiceActivator(inputChannel = "serviceChannel2", outputChannel = "gatherChannel")
337+
public double service2() {
338+
return Math.random();
351339
}
352340

353341
}

0 commit comments

Comments
 (0)