-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Poller fixed-delay and fixed-rate support for Duration syntax #8625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The XML configuration is not in priority these days: it is recommended to move Spring Integration configuration to Java DSL, especially with Spring Boot. We have there a However I think we indeed need to do anything to fix the
I guess one day they are going to be removed from there either way. So, let's see if we can come up with a |
I addition, I think our |
I do wish that XML configuration were not de-prioritized as it has a lot of
advantages over DSL and Annotation-based.
I realize that this is not the place to debate it, but I do not want to
miss the opportunity to let you know that there are still some in the
Spring community who prefer XML configuration.
…On Wed, May 17, 2023 at 3:23 PM Artem Bilan ***@***.***> wrote:
I addition, I think our @poller parser in the
MessagingAnnotationPostProcessor logic does not support Duration, too.
—
Reply to this email directly, view it on GitHub
<#8625 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF7U5MYE3NKNC3EESWEGV3XGTGLPANCNFSM6AAAAAAYEYK7SM>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
No, that is the right place to debate. Give us, please, some hint what advantages you find over Java DSL? |
A number of things:
…-- Names of beans in MessageHistory and in logs are much clearer from the
XML configuration
-- can reference beans by name whereas with DSL you'll need to inject the
bean in either the Class constructor or the Bean method
-- much easier to navigate in IntelliJ from a bean reference to the bean
implementation with XML configuration
-- easier to compartmentalize aspects within a given .xml file .. this
makes for easier testing and reuse, whereas more difficult to
compartmentalize Java classes
I've pushed myself into using DSL configuration to try to better use it,
and I'm still learning how best to do this, but I have found it that it
nowhere as convenient as XML
On Wed, May 17, 2023 at 3:34 PM Artem Bilan ***@***.***> wrote:
No, that is the right place to debate.
Give us, please, some hint what advantages you find over Java DSL?
—
Reply to this email directly, view it on GitHub
<#8625 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF7U5IN2PPBT7RWGRIUJADXGTHXVANCNFSM6AAAAAAYEYK7SM>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
I also think that Spring Integration is probably one of the Spring projects where XML configuration (using namespaces) is much better than the Java counterpart (another example is probably Spring Security). Another difficulty I find in these Java DSLs (I have the same difficulty with Spring Security) is to understand what a method call is supposed to return, in order to understand which calls I should chain at which point to achieve what I want. On the contrary, the XML namespace is really clear: elements with attributes, possibly with subelements when something relates to the parent element; then, other elements, bound to the previous ones through channels or in a chain: very simple. I know XML config is no more in fashion these days, but I think that if something works well for a given task, it shouldn't be replaced just because the trend goes somewhere else. If I had to think of another example where XML config has been replaced, I can think of Gradle vs Maven. There, however, they have built a Groovy DSL which is really effective and can really make a difference. Gradle build scripts are for the most part really easy to read: however, I just had a quick look at Spring Integration Groovy DSL, but it's nothing near to the clearness of Gradle one, it seems like it's just an extension of the Java DSL to use Groovy language constructs. And plain Java, to write a DSL, is not quite adequate IMHO... Just my 2 cents. Regarding this issue: I didn't know about the |
Good! Thank you for feedback. Let me come up with some answers for you!
Java DSL endpoint definitions also come with an
There are overloaded DSL operators which accepts bean names:
This is out of this project scope.
No one said you that you have to compose all your logic in a single
Fully agreed. But this doesn't mean that we don't have similar problem with any design. See my previous comment: no one makes you to put everything into a single flow definition. You simply can have all the channel adapters declared in a separate methods and just references to them from the flow.
Not sure how this could be treated as a DSL problem. You get same outcome with plain Java
Sure! That's why we always have freedom to extract that logic into methods and use them as reference:
That's why I said before that you simply can declare something like The most closer variant for what you talk about wiring with channels are messaging annotations where you configure a
I cannot agree with this since (even if I like Gradle and Groovy by itself) it is hard to determine what and how to write in that Gradle config, especially for plugin configurations.
I'm not sure what you see here as a difference with Gradle style... Sorry for a lengthy , but I tried to cover all your questions. Of course, we are opened for suggestions to improve an API to make your developer life easier. The As we agreed here, the Thank you for your time again! |
I'll give the id() option a shot for bean names.
I believe that there is no bean name overload for "transform()" hence I end
up with a SpEL expression like ***@***.***(#root)" which
works reasonably well.
thanks
…On Wed, May 17, 2023 at 5:35 PM Artem Bilan ***@***.***> wrote:
Good! Thank you for feedback.
Let me come up with some answers for you!
Names of beans in MessageHistory and in logs are much clearer from the
XML configuration
Java DSL endpoint definitions also come with an id() option:
https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl-endpoints
You probably will end up with the same result in a history if you don't
specify an id on XML components.
can reference beans by name whereas with DSL you'll need to inject the
bean in either the Class constructor or the Bean method
There are overloaded DSL operators which accepts bean names:
/**
* Populate a ***@***.*** ServiceActivatingHandler} for the
* ***@***.*** org.springframework.integration.handler.MethodInvokingMessageProcessor}
* to invoke the ***@***.*** method} for provided ***@***.*** bean} at runtime.
* @param beanName the bean name to use.
* @param methodName the method to invoke.
* @return the current ***@***.*** BaseIntegrationFlowDefinition}.
*/
public B handle(String beanName, @nullable String methodName) {
much easier to navigate in IntelliJ from a bean reference to the bean
implementation with XML configuration
This is out of this project scope.
You need to thank to your IDE to have that navigation support for an XML
config.
It just doesn't support such a feature for Java "config by names" 😄 .
It also annoys when I try to auto-wire JdbcTemplate from
auto-configuration: the IDE just doesn't see those beans coming from Spring
Boot.
easier to compartmentalize aspects within a given .xml file
No one said you that you have to compose all your logic in a single
IntegrationFlow. You always can come up with independent components which
you can reuse in other places.
See some samples of this decomposition in my Microservices Patterns
project:
https://github.com/artembilan/microservices-patterns-spring-integration/blob/main/outbox/src/main/java/org/springframework/integration/microservices/outbox/OutboxApplication.java
becomes a little more complicated it's really really hard to read its
definition
Fully agreed. But this doesn't mean that we don't have similar problem
with any design. See my previous comment: no one makes you to put
everything into a single flow definition. You simply can have all the
channel adapters declared in a separate methods and just references to them
from the flow.
The Circuit Breaker sample should give some clue how that could be
configured:
https://github.com/artembilan/microservices-patterns-spring-integration/blob/main/circuit-breaker/src/main/java/org/springframework/integration/microservices/circuitbreaker/CircuitBreakerApplication.java
.
I doubt that it is going to be much easier with an XML.
Java code formatting may not match the requirements to properly "indent"
Not sure how this could be treated as a DSL problem. You get same outcome
with plain Java Stream API or Reactor Flux.
lambda expressions allow for a more compact syntax, but may distract you
by mixing runtime logic with actual flow definition.
Sure! That's why we always have freedom to extract that logic into methods
and use them as reference: handle(this::myBusinessLogic).
You probably still use SpEL with an XML configuration though, so, I don't
see technical difference with those lambdas in Java DSL...
elements with attributes, possibly with subelements
That's why I said before that you simply can declare something like
Http.inboundChannelAdapter() as a top-level bean and just reference to it
from flow definition.
The IntegrationFlow is essentially a mimic of a <chain> in XML where we
don't care what channels are between those endpoints.
The most closer variant for what you talk about wiring with channels are
messaging annotations where you configure a @serviceactivator on a
business method with channel attributes and so on in other method with
other messaging annotations to connect them:
https://docs.spring.io/spring-integration/docs/current/reference/html/configuration.html#annotations
Sometime I find it really difficult to navigate an XML from endpoint to
endpoint just because they are connected through those channels. Same for
these messaging annotations.
Where with an IntegationFlow we have everything wired directly by those
EIP-methods. We also have from(IntegrationFlow) and to(IntegrationFlow)
to be able to divide logic between different (or even reusable) flows which
simply can be navigated from IDE:
https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#integration-flows-composition
I just had a quick look at Spring Integration Groovy DSL, but it's nothing
near to the clearness of Gradle one
I cannot agree with this since (even if I like Gradle and Groovy by
itself) it is hard to determine what and how to write in that Gradle
config, especially for plugin configurations.
We really designed Groovy DSL similar way to Gradle style, despite it is
just wrapper around Java DSL:
@bean
someFlow() {
integrationFlow { 'test' }
{
log LoggingHandler.Level.WARN, 'test.category'
channel { queue 'pollerResultChannel' }
}
}
I'm not sure what you see here as a difference with Gradle style...
And thanks to @CompileStatic and @DelegatesTo we have a good IDE support
for suggestions, unlike with Gradle 😄
Sorry for a lengthy , but I tried to cover all your questions.
Of course, we are opened for suggestions to improve an API to make your
developer life easier.
The ref attribute is definitely documented:
https://docs.spring.io/spring-integration/docs/current/reference/html/endpoint.html#endpoint-namespace
.
As we agreed here, the Duration support will be added to <poller>
configuration as a task for this issue.
Thank you for your time again!
—
Reply to this email directly, view it on GitHub
<#8625 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF7U5KXXNG3UIZ767RHJQLXGTV4DANCNFSM6AAAAAAYEYK7SM>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Yeah... I see.
But only the first variant for Please, raise a new GH issue. Thank you for the pointer! |
Added issue:
#8626
…On Wed, May 17, 2023 at 6:16 PM Artem Bilan ***@***.***> wrote:
I believe that there is no bean name overload for "transform()"
Yeah... I see.
Right, we have something like this for splitter:
public B split(String expression) {
split(String beanName, @nullable String methodName) {
But only the first variant for transform().
I think I don't see a problem adding transform(String beanName, @nullable
String methodName) variant.
Please, raise a new GH issue.
Thank you for the pointer!
—
Reply to this email directly, view it on GitHub
<#8625 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF7U5PGHWXK24AOKPYVGK3XGT2UBANCNFSM6AAAAAAYEYK7SM>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Hi Artem,
You're right. But SpEL expressions should be short and they are put into attributes, so they are in some way confined. You have to use them sparingly. In Java code you're free to do anything. Yes, you can decompose things to improve readability, but still you end up with code describing something, rather than with an actual description of that thing. It's hard for me to explain, I hope you at least get the concept...
I'm not sure I can fully follow you. I use annotations sparingly and only to avoid the use of interfaces or to describe "singleton" components in my integration flows. The main flow description is written in XML and channels are declared in XML as well. I agree with you that when you start to mix XML and annotations it can become a mess.
Documentation is of course essential. XML has the benefit to guide you with a schema, a Groovy DSL does not have a schema and often the IDE is not really helpful (that's the case for Gradle Groovy DSL too, at least in Eclipse), however that is not the point.
What disturbs me are all those methods with multiple parameters. Why a "{" block after The following is pure description instead, although it's actually mapped to method calls under the hood: publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifactId 'myartifact'
}
}
repositories {
maven {
url 'myRepoUrl'
credentials {
username = 'myUserName'
password = 'myPassword'
}
allowInsecureProtocol = true
}
}
} So you have just blocks describing components (just like XML elements), properties (just like XML attributes) and nesting of blocks to describe nested components.
You're right, sorry, I was looking at the wrong place: |
Ok, this is clear now, thanks a lot for pointing that out!
Because here you loose parameter names, which describe what are you doing. In this example it's quite clear what myUserName and myPassword are, but in other context that may not be the case.
I believe that
As I said, I think the problem is just Java. Which I love and I think it's great, but it's not the best solution for this problem. As always, IMHO.
Given that XML works and its support is very good in Spring Integration, I'll try to reverse the question: why is XML so bad that is somewhat being deprecated? :-) |
Yeah...
Is what you are talking about descriptive style. But others are really different and not so readable. Like this sample for the splitter:
where it is not clear what are those This one does look well, too:
Although it has some visibility level. Well, that something to think and play with. Feel free to raise an new GH issue about this Groovy DSL concern. Thank you for feedback and contribution is welcome! |
Fixes spring-projects#8625 The duration can be represented in a ISO 8601 format, e.g. `PT10S`, `P1D` etc. The `<poller>` and `@Poller` don't support such a format. * Introduce a `PeriodicTriggerFactoryBean` to accept string values for trigger options and parse them manually before creating the target `PeriodicTrigger` * Use this `PeriodicTriggerFactoryBean` in the `PollerParser` and `AbstractMethodAnnotationPostProcessor` where we parse options for the `PeriodicTrigger` * Modify tests to ensure that feature works * Document the duration option * Add more cross-links into polling docs * Fix typos in the affected doc files * Add `-parameters` for compiler options since SF 6.1 does not support `-debug` anymore for method parameter names discovery
* GH-8625: Add Duration support for `<poller>` Fixes #8625 The duration can be represented in a ISO 8601 format, e.g. `PT10S`, `P1D` etc. The `<poller>` and `@Poller` don't support such a format. * Introduce a `PeriodicTriggerFactoryBean` to accept string values for trigger options and parse them manually before creating the target `PeriodicTrigger` * Use this `PeriodicTriggerFactoryBean` in the `PollerParser` and `AbstractMethodAnnotationPostProcessor` where we parse options for the `PeriodicTrigger` * Modify tests to ensure that feature works * Document the duration option * Add more cross-links into polling docs * Fix typos in the affected doc files * Add `-parameters` for compiler options since SF 6.1 does not support `-debug` anymore for method parameter names discovery * Fix typos Co-authored-by: Gary Russell <[email protected]> --------- Co-authored-by: Gary Russell <[email protected]>
The concern has been driven by the discussion from: spring-projects#8625 The point is that Java method arguments are not so descriptive when we read the code. Therefore, it is better to design DSL the way it would be cleaner from reading perspective. Plus less choice of methods to chain would give a better end-user experience from coding. * Add a `HeaderFilterSpec` which can accept `headersToRemove` and `patternMatch` as individual options instead of top-level deprecated `headerFilter(headersToRemove, patternMatch)` `IntegrationFlow` method. This way Kotlin and Groovy DSLs get a gain from their "inner section" style. * Such a `Consumer<HeaderFilterSpec>` way to configure an endpoint is similar to already existing `aggregate(Consumer<AggregatorSpec>)`, `resequence(Consumer<ResequencerSpec>)` etc. In other words those components which has a dedicated `ConsumerEndpointSpec` extension are OK from an idiomatic DSL style perspective * Expose a `HeaderFilter.setHeadersToRemove()` to make it working smoothly with this new DSL requirements * Apply a new `headerFilter()` style into Kotlin and Groovy DSLs This is just an initial work to surface an idea. If it is OK, I'll slow continue with others to realign and simplify the paradox of choice.
Hi @mauromol ! If you don't mind, please, take a look into this PR: #8636. Essentially what I did is something like this in Groovy DSL:
Kinda exactly what we discussed with you before about an I understand that you might be interested in something more in Groovy style which would mimic an XML configuration, probably fully without that |
* Introduce HeaderFilterSpec to streamline DSL API The concern has been driven by the discussion from: #8625 The point is that Java method arguments are not so descriptive when we read the code. Therefore, it is better to design DSL the way it would be cleaner from reading perspective. Plus less choice of methods to chain would give a better end-user experience from coding. * Add a `HeaderFilterSpec` which can accept `headersToRemove` and `patternMatch` as individual options instead of top-level deprecated `headerFilter(headersToRemove, patternMatch)` `IntegrationFlow` method. This way Kotlin and Groovy DSLs get a gain from their "inner section" style. * Such a `Consumer<HeaderFilterSpec>` way to configure an endpoint is similar to already existing `aggregate(Consumer<AggregatorSpec>)`, `resequence(Consumer<ResequencerSpec>)` etc. In other words those components which has a dedicated `ConsumerEndpointSpec` extension are OK from an idiomatic DSL style perspective * Expose a `HeaderFilter.setHeadersToRemove()` to make it working smoothly with this new DSL requirements * Apply a new `headerFilter()` style into Kotlin and Groovy DSLs This is just an initial work to surface an idea. If it is OK, I'll slow continue with others to realign and simplify the paradox of choice. * * Fix asterisk imports in the `KotlinIntegrationFlowDefinition`
Expected Behavior
It would be nice and useful (from a configuration point of view) if
<int:poller>
attributesfixed-delay
andfixed-rate
supported thejava.time.Duration
syntax, with support for resolvable configuration values (via aStringValueResolver
) just like@Scheduled
/ScheduledAnnotationBeanPostProcessor
do.Current Behavior
fixed-delay
andfixed-rate
attributes in<int:poller>
must be integer values, interpreted as milliseconds or amount oftime-unit
units. Resolvable configuration values are supported, but configuration must then specify these values as milliseconds, or provide two distinct configuration values for delay/rate and time unit.Context
Using Spring Integration with Spring Boot 2.7.10. Duration syntax is nicely supported in a lot of places, but not in
<int:poller>
tag.The alternative to have maximum flexibility is to leave
fixed-delay
/fixed-rate
in milliseconds and externalize them in configuration. But milliseconds are not so readable when resolutions of minutes or hours is needed.The text was updated successfully, but these errors were encountered: