Introduce parseAnnotations property to @EnableIntegration.#11026
Conversation
this allows disabling method-level annotation parsing when applications rely exclusively on the Java DSL. - Add `EnableIntegrationTests` to demonstrate startup performance improvement. - Remove `@MessagingGateway` in `FileTests`, and migrate it to the DSL approach. - Update several module DSL configuration classes to use `@EnableIntegration(parseAnnotations = false)`. Fixes: spring-projects#11024 Signed-off-by: Jiandong Ma <jiandong.ma.cn@gmail.com>
artembilan
left a comment
There was a problem hiding this comment.
Looks promising!
I believe this deserves a whats-new.adoc entry and some wording about new attribute in the annotations.adoc & overview.adoc, too.
| public @interface EnableIntegration { | ||
|
|
||
| /** | ||
| * Indicate whether to parse method-level annotations such as {@code @Filter}, {@code Router}, |
There was a problem hiding this comment.
Well, this is not just only about methods.
See @MessageEndpoint or @MessagingGateway.
So, say here, please, more context-related matter:
* Indicate whether to process messaging annotations such as {@code @MessagingGateway}, {@code @Filter}, {@code Router},
| * @see GatewayProxyInstantiationPostProcessor | ||
| * @since 7.1 | ||
| */ | ||
| boolean parseAnnotations() default true; |
There was a problem hiding this comment.
We discussed this a bit with @cppwfs and decided to name this as processAnnotations.
Yes, we keep this as true by default in this version but lean to false in the next one.
For now we just introduce this option for awareness, and in the next version we switch the plug to make apps starting better 😄
And I also wonder if need another option for DSL respectively:
boolean processIntegrationFlows() default true;
WDYT?
There was a problem hiding this comment.
for DSL IntegrationFlowBeanPostProcessor, looks only instanceof check, I think its quick, prefer not add.
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof StandardIntegrationFlow standardIntegrationFlow) {
return processStandardIntegrationFlow(standardIntegrationFlow, beanName);
}
else if (bean instanceof IntegrationFlow integrationFlow) {
return processIntegrationFlowImpl(integrationFlow, beanName);
}
if (bean instanceof IntegrationComponentSpec<?, ?> integrationComponentSpec) {
processIntegrationComponentSpec(beanName, integrationComponentSpec);
}
return bean;
}| /** | ||
| * Indicate whether to parse method-level annotations such as {@code @Filter}, {@code Router}, | ||
| * {@code @ServiceActivator}, {@code InboundChannelAdapter}, etc. | ||
| * <p> Can be set to {@code false} if the application exclusively uses the Java DSL. |
There was a problem hiding this comment.
This is really not only about Java DSL.
You see: we also have Kotlin and Groovy DSL which do exactly the same but in their own coding style.
So, let's consider to change wording to the exclusively uses the {@code IntengrationFlow} definitions.
| AnnotationAttributes enableIntegration = AnnotationAttributes.fromMap( | ||
| importingClassMetadata.getAnnotationAttributes(EnableIntegration.class.getName())); | ||
|
|
||
| if (enableIntegration != null && enableIntegration.containsKey("parseAnnotations")) { |
There was a problem hiding this comment.
According to our @EnableIntegration definition, that attribute is primitive and therefore always there, so we don't need this containsKey check.
There was a problem hiding this comment.
I didn't add this containsKey in the first, but few test failed because it pass a mock AnnotationMetadata to this method.
new IntegrationRegistrar().registerBeanDefinitions(mock(), context.getDefaultListableBeanFactory()).
eventually, the returned a object AnnotationAttributes is not null and is a empty map, and the getBoolean() method will throw IllegalArgumentException because it requires the attribute exists
There was a problem hiding this comment.
So, that is the test problem.
It is not fair to adapt our prod code for test expectations .
I don’t belive into TDD since it leads to traps like this.
| long startupTimeWhenParseAnnotationsDisabled; | ||
| try (GenericApplicationContext context = new GenericApplicationContext()) { | ||
| AnnotationConfigUtils.registerAnnotationConfigProcessors(context); | ||
| AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context); |
There was a problem hiding this comment.
I think we can simply (or let's say shorten) the test code using new AnnotationConfigApplicationContext(ConfigWithParseAnnotationsEnabled.class) instead.
And StopWatch around the whole try..catch.
Plus, take a look if reusing same StopWatch would make sense for our logic.
I mean we can start/stop it several times to gather statistics for different scenarios.
See MethodInvokingMessageProcessorTests.testPerformanceSpelVersusInvocable()
|
After looking into this deeper I think we need to be careful. To avoid that we might go with something like "disabled by default and use It is probably too late for the current Just some my thoughts. Thanks |
|
A thought if we offer an "opt-in" model we probably want to wait for a major release to do that. Spring Batch did something similar and it confused many users that required a lot of messaging, to help them along. |
My thought for this is our final goal is (by default) disabling messaging annotations processing, so no matter how many
True, this like a middle stage that can not avoid, but the attribute only control whether to register the messaging annotations post processors, we can document if user want to explicitly disable this annotations processing, in this middle stage, they have to ensure only one
I see Spring Boot auto-configuration will active this
I will try this approach as well.
can't wait to be merged 😊 |
|
Another thought before I go to sleep. Even if it is crazy and could be discarded and I’ll definitely change my mind in the morning 😜. We can introduce This way no breaking changes but there is an option for optimization. The we still need to think how to be with Spring Boot and unfortunately they don’t accept new features after RC. we may look into the respective global property to introduce for disabling annotations: https://docs.spring.io/spring-integration/reference/configuration/global-properties.html. Some interim solution before we incorporate new feature into Spring Boot. I might come with more thoughts tomorrow . thanks |
this allows disabling method-level annotation parsing when applications rely exclusively on the Java DSL.
EnableIntegrationTeststo demonstrate startup performance improvement.@MessagingGatewayinFileTests, and migrate it to the DSL approach.@EnableIntegration(parseAnnotations = false).Fixes: #11024