From f01e2b85533c16b9a962255cbeb6352adb4d1aa4 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 23 Jan 2023 14:22:42 -0500 Subject: [PATCH] GH-3994: Register native hints for Graph model (#3996) Fixes https://github.com/spring-projects/spring-integration/issues/3994 Essentially, migrate those hints from Spring Boot Actuator: an `IntegrationGraphServer` can be used without Spring Boot * Introduce `IntegrationGraphRuntimeHints` - implementation of `RuntimeHintsRegistrar` to register reflection hints for `Graph` and top-level `IntegrationNode` types. * Use `@ImportRuntimeHints` on the `IntegrationGraphServer` to make those hints conditional. --- .../graph/IntegrationGraphRuntimeHints.java | 48 +++++++++++++++++++ .../graph/IntegrationGraphServer.java | 4 +- .../graph/IntegrationGraphServerTests.java | 9 +++- .../IntegrationGraphControllerTests.java | 6 ++- 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java new file mode 100644 index 0000000000..084da6f4b0 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 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 + * + * https://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.graph; + +import org.springframework.aot.hint.BindingReflectionHintsRegistrar; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +/** + * The {@link RuntimeHintsRegistrar} implementation for {@link Graph} + * (and related types) reflection hints registration. + * + * @author Artem Bilan + * + * @since 6.0.3 + */ +class IntegrationGraphRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + new BindingReflectionHintsRegistrar() + .registerReflectionHints(hints.reflection(), + Graph.class, + ErrorCapableCompositeMessageHandlerNode.class, + ErrorCapableDiscardingMessageHandlerNode.class, + ErrorCapableMessageHandlerNode.class, + ErrorCapableRoutingNode.class, + MessageGatewayNode.class, + MessageProducerNode.class, + MessageSourceNode.class, + PollableChannelNode.class); + } + +} 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 5086fe63f7..2ae968f7ad 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2023 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. @@ -34,6 +34,7 @@ import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.integration.core.MessageSource; import org.springframework.integration.endpoint.IntegrationConsumer; @@ -64,6 +65,7 @@ import org.springframework.messaging.PollableChannel; * @since 4.3 * */ +@ImportRuntimeHints(IntegrationGraphRuntimeHints.class) public class IntegrationGraphServer implements ApplicationContextAware, ApplicationListener { private static final float GRAPH_VERSION = 1.2f; diff --git a/spring-integration-core/src/test/java/org/springframework/integration/graph/IntegrationGraphServerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/graph/IntegrationGraphServerTests.java index cab590adb6..bad3e01da0 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/graph/IntegrationGraphServerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/graph/IntegrationGraphServerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2023 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. @@ -33,11 +33,13 @@ import net.minidev.json.JSONArray; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.annotation.Filter; import org.springframework.integration.annotation.InboundChannelAdapter; @@ -91,6 +93,9 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; @DirtiesContext public class IntegrationGraphServerTests { + @Autowired + private ListableBeanFactory beanFactory; + @Autowired private IntegrationGraphServer server; @@ -238,6 +243,8 @@ public class IntegrationGraphServerTests { assertThat(serviceActivator) .containsEntry("integrationPatternType", "service_activator") .containsEntry("integrationPatternCategory", "messaging_endpoint"); + + assertThat(this.beanFactory.findAnnotationOnBean("server", ImportRuntimeHints.class)).isNotNull(); } @Test 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 5571636937..4097c5540b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2023 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. @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -77,6 +78,8 @@ public class IntegrationGraphControllerTests { @Test public void testIntegrationGraphGet() throws Exception { + assertThat(this.wac.findAnnotationOnBean("integrationGraphServer", ImportRuntimeHints.class)).isNotNull(); + this.mockMvc.perform(get("/testIntegration") .header(HttpHeaders.ORIGIN, "https://foo.bar.com") .accept(MediaType.APPLICATION_JSON)) @@ -96,6 +99,7 @@ public class IntegrationGraphControllerTests { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( "IntegrationGraphControllerParserTests-context.xml", getClass()); + assertThat(context.findAnnotationOnBean("integrationGraphServer", ImportRuntimeHints.class)).isNotNull(); HandlerMapping handlerMapping = context.getBean(RequestMappingHandlerMapping.class.getName(), HandlerMapping.class);