INT-4569: Disallow beans override in DSL (#2664)
* INT-4569: Disallow beans override in DSL JIRA: https://jira.spring.io/browse/INT-4569 * Thorw `BeanDefinitionOverrideException` from the `IntegrationFlowBeanPostProcessor` when it detects existing bean and it is not the same object we try to register from the DSL * Document limitations about `prototype` beans * Some polishing in the DSL chapter of the docs * * Fix algorithm in the `IntegrationFlowBeanPostProcessor.noBeanPresentForComponent()` * * Polishing dsl.adoc * Call `BeanFactory.initializeBean()` for existing beans if they are `prototype` * * Code formatting in the `ManualFlowTests`
This commit is contained in:
committed by
Gary Russell
parent
65df35bfd1
commit
3dd8b63576
@@ -115,28 +115,38 @@ The endpoints are automatically wired together by using direct channels.
|
||||
|
||||
[[java-dsl-class-cast]]
|
||||
.Lambdas And `Message<?>` Arguments
|
||||
IMPORTANT: When using lambdas in EIP methods, the "input" argument is generally the message payload.
|
||||
[IMPORTANT]
|
||||
====
|
||||
When using lambdas in EIP methods, the "input" argument is generally the message payload.
|
||||
If you wish to access the entire message, use one of the overloaded methods that take a `Class<?>` as the first parameter.
|
||||
For example, this won't work:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
.<Message<?>, Foo>transform(m -> newFooFromMessage(m))
|
||||
----
|
||||
====
|
||||
|
||||
This will fail at runtime with a `ClassCastException` because the lambda doesn't retain the argument type and the framework will attempt to cast the payload to a `Message<?>`.
|
||||
|
||||
Instead, use:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
.(Message.class, m -> newFooFromMessage(m))
|
||||
----
|
||||
====
|
||||
|
||||
[[bean-definitions-override]]
|
||||
.Bean Definitions override
|
||||
[IMPORTANT]
|
||||
====
|
||||
The Java DSL can register beans for the object defined in-line in the flow definition, as well as can reuse existing, injected beans.
|
||||
In case of the same bean name defined for in-line object and existing bean definition, a `BeanDefinitionOverrideException` is thrown indicating that such a configuration is wrong.
|
||||
However when you deal with `prototype` beans, there is no way to detect from the integration flow processor an existing bean definition because every time we call a `prototype` bean from the `BeanFactory` we get a new instance.
|
||||
This way a provided instance is used in the `IntegrationFlow` as is without any bean registration and any possible check against existing `prototype` bean definition.
|
||||
However `BeanFactory.initializeBean()` is called for this object if it has an explicit `id` and bean definition for this name is in `prototype` scope.
|
||||
====
|
||||
|
||||
[[java-dsl-channels]]
|
||||
=== Message Channels
|
||||
|
||||
@@ -316,7 +326,7 @@ It avoids inconvenient coding using setters and makes the flow definition more s
|
||||
Note that you can use `Transformers` to declare target `Transformer` instances as `@Bean` instances and, again, use them from `IntegrationFlow` definition as bean methods.
|
||||
Nevertheless, the DSL parser takes care of bean declarations for inline objects, if they are not yet defined as beans.
|
||||
|
||||
See [https://docs.spring.io/spring-integration/api/org/springframework/integration/dsl/Transformers.html] in the Javadoc for more information and supported factory methods.
|
||||
See https://docs.spring.io/spring-integration/api/org/springframework/integration/dsl/Transformers.html[Transformers] in the Javadoc for more information and supported factory methods.
|
||||
|
||||
Also see <<java-dsl-class-cast>>.
|
||||
|
||||
@@ -789,15 +799,18 @@ public IntegrationFlow evenFlow() {
|
||||
}
|
||||
----
|
||||
|
||||
{empty} +
|
||||
In this case, when you need to receive a reply from such a sub-flow and continue the main flow, this `IntegrationFlow` bean reference (or its input channel) has to be wrapped with a `.gateway()` as shown in the preceding example.
|
||||
The `oddFlow()` reference in the preceding example is not wrapped to the `.gateway()`.
|
||||
Therefore, we do not expect a reply from this routing branch.
|
||||
Otherwise, you end up with an exception similar to the following:
|
||||
|
||||
[source]
|
||||
----
|
||||
Caused by: org.springframework.beans.factory.BeanCreationException: The 'currentComponent' (org.springframework.integration.router.MethodInvokingRouter@7965a51c) is a one-way 'MessageHandler' and it isn't appropriate to configure 'outputChannel'. This is the end of the integration flow.
|
||||
----
|
||||
....
|
||||
Caused by: org.springframework.beans.factory.BeanCreationException:
|
||||
The 'currentComponent' (org.springframework.integration.router.MethodInvokingRouter@7965a51c)
|
||||
is a one-way 'MessageHandler' and it isn't appropriate to configure 'outputChannel'.
|
||||
This is the end of the integration flow.
|
||||
....
|
||||
|
||||
When you configure a sub-flow as a lambda, the framework handles the request-reply interaction with the sub-flow and a gateway is not needed.
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user