Skip to content

Commit f0545dd

Browse files
authored
Disable requiresReply for Transformer (#10749)
* Disable `requiresReply` for Transformer The Transformer pattern was never about letting the null result pass down into a reply message. Or perform filter-like logic via transformation. The service activator was always advertised for a logic to deal with a null result. Plus, after adopting NullAway, the `AbstractMessageProcessingTransformer` now throws `MessageTransformationException` when the processing result is null. * Fix `MessageTransformingHandler` to disallow changing `requiresReply` to avoid a false impression that a null result could lead to something but an exception. More info in: https://stackoverflow.com/questions/79871975/best-practices-for-error-handling-in-synchronous-spring-integration-flows * Add `@since 7.1` to the overridden method in the MTH * Replace `Its` with `The service activator's` in the `transformer.adoc`
1 parent 6995060 commit f0545dd

4 files changed

Lines changed: 26 additions & 13 deletions

File tree

spring-integration-core/src/main/java/org/springframework/integration/config/TransformerFactoryBean.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,41 +39,36 @@
3939
*/
4040
public class TransformerFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
4141

42-
@SuppressWarnings("this-escape")
43-
public TransformerFactoryBean() {
44-
setRequiresReply(true);
45-
}
46-
4742
@Override
4843
protected MessageHandler createMethodInvokingHandler(Object targetObject, @Nullable String targetMethodName) {
4944
Assert.notNull(targetObject, "targetObject must not be null");
50-
Transformer transformer = null;
45+
Transformer transformer;
5146
if (targetObject instanceof Transformer castTransformer) {
5247
transformer = castTransformer;
5348
}
5449
else {
55-
this.checkForIllegalTarget(targetObject, targetMethodName);
50+
checkForIllegalTarget(targetObject, targetMethodName);
5651
if (StringUtils.hasText(targetMethodName)) {
5752
transformer = new MethodInvokingTransformer(targetObject, targetMethodName);
5853
}
5954
else {
6055
transformer = new MethodInvokingTransformer(targetObject);
6156
}
6257
}
63-
return this.createHandler(transformer);
58+
return createHandler(transformer);
6459
}
6560

6661
@Override
6762
protected MessageHandler createExpressionEvaluatingHandler(Expression expression) {
6863
Transformer transformer = new ExpressionEvaluatingTransformer(expression);
69-
MessageTransformingHandler handler = this.createHandler(transformer);
64+
MessageTransformingHandler handler = createHandler(transformer);
7065
handler.setPrimaryExpression(expression);
7166
return handler;
7267
}
7368

7469
protected MessageTransformingHandler createHandler(Transformer transformer) {
7570
MessageTransformingHandler handler = new MessageTransformingHandler(transformer);
76-
this.postProcessReplyProducer(handler);
71+
postProcessReplyProducer(handler);
7772
return handler;
7873
}
7974

spring-integration-core/src/main/java/org/springframework/integration/transformer/MessageTransformingHandler.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public class MessageTransformingHandler extends AbstractReplyProducingMessageHan
5252
*/
5353
@SuppressWarnings("this-escape")
5454
public MessageTransformingHandler() {
55-
setRequiresReply(true);
55+
super.setRequiresReply(true);
5656
}
5757

5858
/**
@@ -76,6 +76,17 @@ public void setTransformer(Transformer transformer) {
7676
this.transformer = transformer;
7777
}
7878

79+
/**
80+
* Overridden to throw an {@link UnsupportedOperationException} since transformer must never return null
81+
* and {@code requiresReply == true} by default.
82+
* @param requiresReply never used.
83+
* @since 7.1
84+
*/
85+
@Override
86+
public void setRequiresReply(boolean requiresReply) {
87+
throw new UnsupportedOperationException("Transformer always requires a non-null reply payload.");
88+
}
89+
7990
@Override
8091
public String getComponentType() {
8192
return (this.transformer instanceof NamedComponent namedComponent)

src/reference/antora/modules/ROOT/pages/transformer.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ As of Spring Integration 2.0, a message transformer's transformation method can
124124
Returning `null` results in an exception (a `MessageTransformationException` to be precise), because a message transformer should always be expected to transform each source message into a valid target message.
125125
In other words, a message transformer should not be used as a message filter, because there is a dedicated `<filter>` option for that.
126126
However, if you do need this type of behavior (where a component might return `null` and that should not be considered an error), you could use a service activator.
127-
Its `requires-reply` value is `false` by default, but that can be set to `true` in order to have exceptions thrown for `null` return values, as with the transformer.
127+
The service activator's `requiresReply` value is `false` by default, but that can be set to `true` in order to have exceptions thrown for `null` return values, as with the transformer.
128+
The transformer's `requiresReply` property cannot be modified: it is always `true` since the transformer pattern definition does not allow nulls for replies.
128129

129130
[[transformers-and-spring-expression-language-spel]]
130131
== Transformers and Spring Expression Language (SpEL)

src/reference/antora/modules/ROOT/pages/whats-new.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ For more details, see the https://github.com/spring-projects/spring-integration/
1414
In general, the project has been moved to the latest dependency versions.
1515
Java 17 is still the baseline, but Java 25 is supported.
1616

17-
[[x7.0-web-services-changes]]
17+
[[x7.1-general-changes]]
18+
=== General Changes
19+
20+
The `MessageTransformingHandler.requiresReply` flag cannot be modified: an `UnsupportedOperationException` is thrown from the overridden `setRequiresReply()` method to indicate the transformer pattern cannot produce nulls for replies.
21+
See xref:transformer.adoc[] for more information.
22+
23+
[[x7.1-web-services-changes]]
1824
=== Web Services Support Changes
1925

2026
The Web Services Outbound Gateway now can rely on the provided `WebServiceTemplate.defaultUri`.

0 commit comments

Comments
 (0)