spring-projects / spring-integration

Spring Integration provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns (EIP)
http://projects.spring.io/spring-integration/
Apache License 2.0
1.54k stars 1.11k forks source link

Consider to Support Extentions with BaseIntegrationFlowDefinition/IntegrationFlowDefinition as base classes #3155

Closed sirimamilla closed 4 years ago

sirimamilla commented 4 years ago

Affects Version(s): \ 5.2.3

Enhancement

Currently BaseIntegrationFlowDefinition & IntegrationFlowDefinition classes have private constructors making custom extenstions to these classes impossible.

Can we consider make these protected so developers can implement custom extensions to IntegratioFlowDefinition?

Regards, Jayadev

artembilan commented 4 years ago

I'm curious how you going to use such an extension. There is just no access to instances of those classes as top-level API. You only can use them from the IntegrationFlows factory and as a callback from the IntegrationFlow lambda. So, any your extension is not going to give value for the rest of the API.

In fact I tried to have an extension for Kotlin DSL, but then I have been advised to go direct Kotlin API without any Java extension to avoid conflicts in the runtime: https://github.com/spring-projects/spring-integration-extensions/tree/master/spring-integration-kotlin-dsl

So, please, elaborate more how that protected ctor is going to be useful in general.

Thanks

sirimamilla commented 4 years ago

Hi @artembilan ,

In our application, we have usecases where in we can implement some usecases with ease, when we have access to extend the IntegrationFlowDefinition. Example for, I want to implement, conditional messageGateway, where in a condition will be tested before calling the underlying channel by messaging gateway. This provision is not available, so we are using ScatterGather with single conditional channel and defaultOutputChannel to handle this scenario. It would greatly simplify the application code, if We are able to provide conditional Gateway as an extension.

We have some more scenario's which we are solving as complex application code, rather than framework.

artembilan commented 4 years ago

Sounds like you can reach your requirements with filter endpoint or channel interceptor. I don’t think that so high level API as flow definition could be responsible for something as condition. And still: I don’t see yet how such an extension can be used. I may agree about some custom MessageHandler, but still can be use from an existing handle(). Please, share some sample how you are going to use an extension - not how to write it, but definitely it usage.

I may agree with you in the end as it was with scatter-gather, but you don’t provide convincing arguments yet 😉

Thanks

sirimamilla commented 4 years ago

HI @artembilan,

Issue https://github.com/spring-projects/spring-integration/issues/3156 reported as enhancement request can be one of the example. If the example do not qualify as the base requirement, can be a custom extension handled by developers to make code very much fluent.

Original intent of creating SI Java DSL is to create a create a fluent API.

This is inline with providing the fluent extensions to the existing EAI patterns.

artembilan commented 4 years ago

Thank you for reporting a specific use-case!

Will take a look there later.

This is inline with providing the fluent extensions to the existing EAI patterns.

That's OK and that's exactly what we do in the framework.

Only the point is that there is no way to support extensions of those classes.

Try to extend an existing IntegrationFlowDefinition and it is going to be out of use because IntegrationFlows is compiled in with the existing IntegrationFlowDefinition. The IntegrationFlow functional interface is also compiled in with that IntegrationFlowDefinition. So, any of your extends is going to be out of use in the framework and no one will get benefit from such a possibility.

Meanwhile we can really discuss improvements to existing IntegrationFlowDefinition, but I fully don't see the point in the hierarchy way...

sirimamilla commented 4 years ago

For Example my request for extending the Gateway with filter functionality doesn't fit to be part of the Spring Framework, but it will be great fit for application frameworks, simple few line extension to the spring framework as application framework, can save a great deal of time for the developers.

We have 100's of microservices written with spring Integration and more coming our way in near future. Given this way of extending framework will open up new ways for application frameworks to handle application specific patterns/scenarios.

As I can see this is not a deviation from Spring framework standards, as we are able extend other spring frameworks as and when necessary.

artembilan commented 4 years ago

I'm open for suggestions, but as I see currently it is just not possible. The high-level API in the framework is factory IntegrationFlows and IntegrationFlow functional interface. So, any extends IntegrationFlowDefinition is just not going to be visible for other API. Let's just imagine we make its ctor as protected! What next you going to do? How you are going to use that new API?

We probably can do something with the IntegrationFlowAdapter though, but it doesn't look like is what you want to have.

The point is that you are free to extend any single block and use it in combination with many others, but high-level DSL is really for hiding instantiation of those block via fluent API. I don't know any DSL which could be extended with new operators without changes in the framework which provides for us that DSL.

sirimamilla commented 4 years ago

I will try to see the ways to open up the possibility of extending the IntegrationFlowDefinition & other Base API components and will come back to you.

As per my analysis, this will open up a lot of possibilities for end application simplicity and fluency.

artembilan commented 4 years ago

Technically what you are asking about I did in the mentioned Kotlin DSL. It indeed comes with its own extensions, but as you see I have had to introduce many other components to really make it as fluent high-level API:

https://github.com/spring-projects/spring-integration-extensions/blob/master/spring-integration-kotlin-dsl/src/main/kotlin/org/springframework/integration/dsl/kotlin/KotlinIntegrationFlowDefinition.kt https://github.com/spring-projects/spring-integration-extensions/blob/master/spring-integration-kotlin-dsl/src/main/kotlin/org/springframework/integration/dsl/kotlin/IntegrationFlowDsl.kt

But again: this is only that particular project and cannot be extended with anything custom in the target use-case.

sirimamilla commented 4 years ago

Yes, I am expecting to build similar extension to spring framework to build composite EIP flows that would greatly simplify the application development time.

sirimamilla commented 4 years ago

Hi @artembilan, can spring Integration be made extensible similar to Kaitlin? It would be great help in simplifying many composite message patterns as application framework

artembilan commented 4 years ago

I'm OK with any suggestions. So far what you have proposed is not going to have a value when you declare a regular IntegrationFlow via existing IntegrationFlows factory or IntegrationFlow lambda callback. What I did in the Kotlin DSL is its own high-level integrationFlow() global functions, essentially a special variant of the IntegrationFlows factory. It's not so easy to provide and support that API for any arbitrary extension.

As said the possible simple hook might be done with the IntegrationFlowAdapter.

I can make the mentioned ctor for the IntegrationFlowDefinition as protected, but I'm afraid that is not enough to cover all the possibility to use an extended API and existing one together. More over I believe that any composite use-cases can be achieved using existing canonical EIP implementations in the framework. We really don't encourage to overcomplicate with custom components.

The way you ask could be achieved with a standalone IntegrationFlow called from other flows and so on.

I'm still opened for suggestions how to proceed.

Thanks

sirimamilla commented 4 years ago

I have tried making the constructor, register methods protected.. that is not sufficient.. I had to create my own custom Integration flow functional Interface. It is not registering the Custom Integration Flow. As the integraion bean post processor is not able to recognise the custom bean. I was exploring alternative ways to write a post processor that can detect these custom Integration Flows.

artembilan commented 4 years ago

Sounds good! Please, take your time and share your experience whenever you can!

I don't think this issue is urgent, so I can't tackle it right now...