diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConfigUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConfigUtils.java index a00ce08c711..f1e0366dbc8 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConfigUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConfigUtils.java @@ -35,9 +35,6 @@ public final class IntegrationConfigUtils { public static final String HANDLER_ALIAS_SUFFIX = ".handler"; - // TODO: Boot constant - move to Spring Framework? - public static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType"; - public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, String className, String methodSignature) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java index a92be496fc4..14f171064e1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java @@ -23,8 +23,8 @@ import java.util.Map.Entry; import java.util.Set; -import org.springframework.beans.BeanMetadataAttribute; import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -176,9 +176,7 @@ else if (StringUtils.hasText(asyncExecutor)) { gatewayProxyBuilder.addConstructorArgValue(serviceInterface); AbstractBeanDefinition beanDefinition = gatewayProxyBuilder.getBeanDefinition(); - beanDefinition.addMetadataAttribute(new BeanMetadataAttribute(IntegrationConfigUtils.FACTORY_BEAN_OBJECT_TYPE, - serviceInterface)); - + beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, serviceInterface); return new BeanDefinitionHolder(beanDefinition, id); } @@ -188,7 +186,7 @@ else if (StringUtils.hasText(asyncExecutor)) { * @param importingClassMetadata The importing class metadata * @return The captured values. */ - private static List> captureMetaAnnotationValues( + private static List> captureMetaAnnotationValues( AnnotationMetadata importingClassMetadata) { Set directAnnotations = importingClassMetadata.getAnnotationTypes(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java index 5e384464850..40365cb585f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java @@ -48,6 +48,7 @@ import org.springframework.integration.router.RecipientListRouterManagement; import org.springframework.integration.support.context.NamedComponent; import org.springframework.integration.support.management.MappingMessageRouterManagement; +import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; @@ -65,7 +66,7 @@ */ public class IntegrationGraphServer implements ApplicationContextAware, ApplicationListener { - private static final float GRAPH_VERSION = 1.1f; + private static final float GRAPH_VERSION = 1.2f; private static MicrometerNodeEnhancer micrometerEnhancer; @@ -377,7 +378,7 @@ MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) { } @Nullable - String channelToBeanName(MessageChannel messageChannel) { + private String channelToBeanName(MessageChannel messageChannel) { return messageChannel instanceof NamedComponent ? ((NamedComponent) messageChannel).getBeanName() : Objects.toString(messageChannel, null); @@ -396,7 +397,7 @@ MessageSourceNode sourceNode(String name, SourcePollingChannelAdapter adapter) { String nameToUse = name; MessageSource source = adapter.getMessageSource(); if (source instanceof NamedComponent) { - nameToUse = ((NamedComponent) source).getComponentName(); + nameToUse = IntegrationUtils.obtainComponentName((NamedComponent) source); } MessageSourceNode node = new MessageSourceNode(this.nodeId.incrementAndGet(), nameToUse, source, outputChannel, errorChannel); @@ -412,7 +413,7 @@ MessageHandlerNode handlerNode(String nameArg, IntegrationConsumer consumer) { MessageHandlerNode node; String name = nameArg; if (handler instanceof NamedComponent) { - name = ((NamedComponent) handler).getComponentName(); + name = IntegrationUtils.obtainComponentName((NamedComponent) handler); } if (handler instanceof CompositeMessageHandler) { node = compositeHandler(name, consumer, (CompositeMessageHandler) handler, outputChannelName, null, @@ -448,7 +449,7 @@ MessageHandlerNode polledHandlerNode(String nameArg, PollingConsumer consumer) { MessageHandlerNode node; String name = nameArg; if (handler instanceof NamedComponent) { - name = ((NamedComponent) handler).getComponentName(); + name = IntegrationUtils.obtainComponentName((NamedComponent) handler); } if (handler instanceof CompositeMessageHandler) { node = compositeHandler(name, consumer, (CompositeMessageHandler) handler, outputChannelName, @@ -487,7 +488,7 @@ MessageHandlerNode compositeHandler(String name, IntegrationConsumer consumer, .map(NamedComponent.class::cast) .map(named -> new CompositeMessageHandlerNode.InnerHandler( - named.getComponentName(), + IntegrationUtils.obtainComponentName(named), named.getComponentType())) .collect(Collectors.toList()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/utils/IntegrationUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/support/utils/IntegrationUtils.java index 6a3bf199704..b12d0e745d1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/utils/IntegrationUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/utils/IntegrationUtils.java @@ -24,8 +24,11 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.core.convert.ConversionService; +import org.springframework.integration.config.IntegrationConfigUtils; import org.springframework.integration.support.DefaultMessageBuilderFactory; import org.springframework.integration.support.MessageBuilderFactory; +import org.springframework.integration.support.context.NamedComponent; +import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.MessageHandlingException; @@ -44,18 +47,19 @@ */ public final class IntegrationUtils { - private static final Log logger = LogFactory.getLog(IntegrationUtils.class); + private static final Log LOGGER = LogFactory.getLog(IntegrationUtils.class); + + private static final String INTERNAL_COMPONENT_PREFIX = '_' + IntegrationConfigUtils.BASE_PACKAGE; public static final String INTEGRATION_CONVERSION_SERVICE_BEAN_NAME = "integrationConversionService"; public static final String INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME = "messageBuilderFactory"; - /** * Should be set to TRUE on CI plans and framework developer systems. */ public static final boolean fatalWhenNoBeanFactory = - Boolean.valueOf(System.getenv("SI_FATAL_WHEN_NO_BEANFACTORY")); + Boolean.parseBoolean(System.getenv("SI_FATAL_WHEN_NO_BEANFACTORY")); private IntegrationUtils() { super(); @@ -75,7 +79,7 @@ public static ConversionService getConversionService(BeanFactory beanFactory) { * @param beanFactory The bean factory. * @return The message builder factory. */ - public static MessageBuilderFactory getMessageBuilderFactory(BeanFactory beanFactory) { + public static MessageBuilderFactory getMessageBuilderFactory(@Nullable BeanFactory beanFactory) { MessageBuilderFactory messageBuilderFactory = null; if (beanFactory != null) { try { @@ -83,8 +87,8 @@ public static MessageBuilderFactory getMessageBuilderFactory(BeanFactory beanFac INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME, MessageBuilderFactory.class); } catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("No MessageBuilderFactory with name '" + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("No MessageBuilderFactory with name '" + INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME + "' found: " + e.getMessage() + ", using default."); @@ -92,9 +96,7 @@ public static MessageBuilderFactory getMessageBuilderFactory(BeanFactory beanFac } } else { - if (logger.isDebugEnabled()) { - logger.debug("No 'beanFactory' supplied; cannot find MessageBuilderFactory, using default."); - } + LOGGER.debug("No 'beanFactory' supplied; cannot find MessageBuilderFactory, using default."); if (fatalWhenNoBeanFactory) { throw new IllegalStateException("All Message creators need a BeanFactory"); } @@ -193,4 +195,18 @@ public static RuntimeException wrapInHandlingExceptionIfNecessary(Message mes return runtimeException; } + /** + * Obtain a component name from the provided {@link NamedComponent}. + * @param component the {@link NamedComponent} source for component name. + * @return the component name + * @since 5.3 + */ + public static String obtainComponentName(NamedComponent component) { + String name = component.getComponentName(); + if (name.charAt(0) == '_' && name.startsWith(INTERNAL_COMPONENT_PREFIX)) { + name = name.substring((INTERNAL_COMPONENT_PREFIX).length() + 1); + } + return name; + } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/GatewayParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/GatewayParserTests.java index 0b48adb5901..04b1f6067b5 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/GatewayParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/GatewayParserTests.java @@ -35,6 +35,7 @@ import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; @@ -42,7 +43,6 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.expression.Expression; import org.springframework.integration.channel.QueueChannel; -import org.springframework.integration.config.IntegrationConfigUtils; import org.springframework.integration.gateway.GatewayMethodMetadata; import org.springframework.integration.gateway.GatewayProxyFactoryBean; import org.springframework.integration.gateway.RequestReplyExchanger; @@ -177,16 +177,16 @@ public void testAsyncDisabledGateway() throws Exception { @Test public void testFactoryBeanObjectTypeWithServiceInterface() { ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory(); - Object attribute = beanFactory.getMergedBeanDefinition("&oneWay").getAttribute( - IntegrationConfigUtils.FACTORY_BEAN_OBJECT_TYPE); + Object attribute = + beanFactory.getMergedBeanDefinition("&oneWay").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE); assertThat(attribute).isEqualTo(TestService.class.getName()); } @Test public void testFactoryBeanObjectTypeWithNoServiceInterface() { ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory(); - Object attribute = beanFactory.getMergedBeanDefinition("&defaultConfig").getAttribute( - IntegrationConfigUtils.FACTORY_BEAN_OBJECT_TYPE); + Object attribute = + beanFactory.getMergedBeanDefinition("&defaultConfig").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE); assertThat(attribute).isEqualTo(RequestReplyExchanger.class.getName()); } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/management/IntegrationGraphControllerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/management/IntegrationGraphControllerTests.java index a1e0981685b..77dbe9d74ad 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/management/IntegrationGraphControllerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/management/IntegrationGraphControllerTests.java @@ -24,9 +24,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; @@ -43,8 +42,7 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @@ -62,8 +60,7 @@ * * @since 4.3 */ -@RunWith(SpringRunner.class) -@WebAppConfiguration +@SpringJUnitWebConfig @TestPropertySource(properties = "spring.application.name:testApplication") @DirtiesContext public class IntegrationGraphControllerTests { @@ -73,7 +70,7 @@ public class IntegrationGraphControllerTests { private MockMvc mockMvc; - @Before + @BeforeEach public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @@ -88,8 +85,7 @@ public void testIntegrationGraphGet() throws Exception { .andExpect(handler().handlerType(IntegrationGraphController.class)) .andExpect(handler().methodName("getGraph")) .andExpect(jsonPath("$.nodes..name") - .value(Matchers.containsInAnyOrder("nullChannel", "errorChannel", - "_org.springframework.integration.errorLogger"))) + .value(Matchers.containsInAnyOrder("nullChannel", "errorChannel", "errorLogger"))) // .andDo(print()) .andExpect(jsonPath("$.contentDescriptor.name").value("testApplication")) .andExpect(jsonPath("$.links").exists()); @@ -154,9 +150,7 @@ public void testIntegrationGraphControllerParser() throws Exception { @Configuration @EnableWebMvc @EnableIntegration - @EnableIntegrationManagement(statsEnabled = "_org.springframework.integration.errorLogger.handler", - countsEnabled = "!*", - defaultLoggingEnabled = "false") + @EnableIntegrationManagement(defaultLoggingEnabled = "false") @EnableIntegrationGraphController(path = "/testIntegration", allowedOrigins = "https://foo.bar.com") public static class ContextConfiguration { diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java index cefd25fe7f4..4e8e47aa344 100644 --- a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java @@ -43,6 +43,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.Lifecycle; import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.config.IntegrationConfigUtils; import org.springframework.integration.config.IntegrationManagementConfigurer; import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.context.OrderlyShutdownCapable; @@ -111,9 +112,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements ApplicationContextAware, DestructionAwareBeanPostProcessor { - private static final String SI_PACKAGE = "org.springframework.integration"; - - public static final String DEFAULT_DOMAIN = SI_PACKAGE; + public static final String DEFAULT_DOMAIN = IntegrationConfigUtils.BASE_PACKAGE; private final IntegrationJmxAttributeSource attributeSource = new IntegrationJmxAttributeSource(); @@ -827,7 +826,7 @@ private void registerEndpoint(AbstractEndpoint endpoint) { String beanKey; String name = endpoint.getComponentName(); String source; - if (name.startsWith('_' + SI_PACKAGE)) { + if (name.startsWith('_' + IntegrationConfigUtils.BASE_PACKAGE)) { name = getInternalComponentName(name); source = "internal"; } @@ -881,7 +880,7 @@ private Object extractTarget(Object bean) { private String getChannelBeanKey(String channel) { String extra = ""; - if (channel.startsWith(SI_PACKAGE)) { + if (channel.startsWith(IntegrationConfigUtils.BASE_PACKAGE)) { extra = ",source=anonymous"; } return String.format(this.domain + ":type=MessageChannel,name=%s%s" + getStaticNames(), @@ -979,11 +978,11 @@ private org.springframework.integration.support.management.MessageHandlerMetrics String managedType = source; String managedName = name; - if (managedName != null && managedName.startsWith('_' + SI_PACKAGE)) { + if (managedName != null && managedName.startsWith('_' + IntegrationConfigUtils.BASE_PACKAGE)) { managedName = getInternalComponentName(managedName); managedType = "internal"; } - if (managedName != null && name.startsWith(SI_PACKAGE)) { + if (managedName != null && name.startsWith(IntegrationConfigUtils.BASE_PACKAGE)) { MessageChannel inputChannel = endpoint.getInputChannel(); if (inputChannel != null) { managedName = buildAnonymousManagedName(this.anonymousHandlerCounters, inputChannel); @@ -1058,7 +1057,7 @@ private String buildAnonymousManagedName(Map anonymousCache, } private String getInternalComponentName(String name) { - return name.substring(('_' + SI_PACKAGE).length() + 1); + return name.substring(('_' + IntegrationConfigUtils.BASE_PACKAGE).length() + 1); } private org.springframework.integration.support.management.MessageSourceMetrics enhanceSourceMonitor( @@ -1075,7 +1074,7 @@ private org.springframework.integration.support.management.MessageSourceMetrics if (endpoint != null) { endpointName = endpoint.getBeanName(); } - if (endpointName != null && endpointName.startsWith('_' + SI_PACKAGE)) { + if (endpointName != null && endpointName.startsWith('_' + IntegrationConfigUtils.BASE_PACKAGE)) { endpointName = getInternalComponentName(endpointName); source = "internal"; } @@ -1115,7 +1114,7 @@ private org.springframework.integration.support.management.MessageSourceMetrics String managedType = source; String managedName = name; - if (managedName != null && managedName.startsWith(SI_PACKAGE)) { + if (managedName != null && managedName.startsWith(IntegrationConfigUtils.BASE_PACKAGE)) { Object target = endpoint; if (endpoint instanceof Advised) { TargetSource targetSource = ((Advised) endpoint).getTargetSource(); diff --git a/src/reference/asciidoc/graph.adoc b/src/reference/asciidoc/graph.adoc index 52b5f88d6ac..b36ec20b89f 100644 --- a/src/reference/asciidoc/graph.adoc +++ b/src/reference/asciidoc/graph.adoc @@ -80,7 +80,7 @@ A Spring Integration application with only the default components would expose a "max" : 0.0 } }, - "name" : "_org.springframework.integration.errorLogger" + "name" : "errorLogger" } ], "links" : [ { "from" : 2, @@ -143,29 +143,7 @@ The `nodes` graph element is perhaps the most interesting, because its elements Node elements contain various properties that are generally self-explanatory. For example, expression-based components include the `expression` property that contains the primary expression string for the component. To enable the metrics, add an `@EnableIntegrationManagement` to a `@Configuration` class or add an `` element to your XML configuration. -You can control exactly which components in the framework collect statistics. See <<./metrics.adoc#metrics-management,Metrics and Management>> for complete information. -See the `stats` attribute from the `o.s.i.errorLogger` component in the JSON example shown earlier. -In this case, The `nullChannel` and `errorChannel` do not provide statistics information, because the configuration for this example was as follows: - -==== -[source,java] ----- -@Configuration -@EnableIntegration -@EnableIntegrationManagement(statsEnabled = "_org.springframework.integration.errorLogger.handler", - countsEnabled = "!*", - defaultLoggingEnabled = "false") -public class ManagementConfiguration { - - @Bean - public IntegrationGraphServer integrationGraphServer() { - return new IntegrationGraphServer(); - } - -} ----- -==== The `nodeId` represents a unique incremental identifier to let you distinguish one component from another. It is also used in the `links` element to represent a relationship (connection) of this component to others, if any. diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index e960db2f0ea..57e885df825 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -26,3 +26,7 @@ See its JavaDocs and <<./graph.adoc#integration-graph,Integration Graph>> for mo The gateway proxy now doesn't proxy `default` methods by default. see <<./gateway.adoc/gateway-calling-default-methods,Invoking `default` Methods>> for more information. + + +Internal components (such as `_org.springframework.integration.errorLogger`) now have a shortened name when they are represented in the integration graph. +See <<./graph.adoc#integration-graph,Integration Graph>> for more information.