GH-3615: Make log() as non-terminal in DSL

Fixes https://github.com/spring-projects/spring-integration/issues/3615

The `log()` operator for Java DSL in the end of flow causes a confusion
for its different behavior and, therefore, inconsistency with expectations

* Populate a `bridge()` in the end of flow instead of `nullChannel` when
the current component is `WireTapSpec` (relevant to `wireTap()` and `log()`)
* Deprecate a `logAndReply()` operator since its behavior is now included into the `log()` in the end if flow
* Fix tests to use just `log()` in the end from now on
* Fix `dsl.adoc` for the new `log()` behaviour in the end of flow
This commit is contained in:
Artem Bilan
2022-04-07 14:38:59 -04:00
committed by Gary Russell
parent 802d217a9a
commit 10ea577549
5 changed files with 41 additions and 51 deletions

View File

@@ -2182,9 +2182,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* logging level and {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category.
* <p> The full request {@link Message} will be logged.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @return the current {@link BaseIntegrationFlowDefinition}.
* @see #wireTap(WireTapSpec)
*/
@@ -2198,9 +2195,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* logging level and {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category.
* <p> The full request {@link Message} will be logged.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @return the current {@link BaseIntegrationFlowDefinition}.
* @see #wireTap(WireTapSpec)
@@ -2214,9 +2208,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided logging category
* and {@code INFO} logging level.
* <p> The full request {@link Message} will be logged.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param category the logging category to use.
* @return the current {@link BaseIntegrationFlowDefinition}.
* @see #wireTap(WireTapSpec)
@@ -2230,9 +2221,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided
* {@link LoggingHandler.Level} logging level and logging category.
* <p> The full request {@link Message} will be logged.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param category the logging category to use.
* @return the current {@link BaseIntegrationFlowDefinition}.
@@ -2247,9 +2235,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided
* {@link LoggingHandler.Level} logging level, logging category
* and SpEL expression for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param category the logging category.
* @param logExpression the SpEL expression to evaluate logger message at runtime
@@ -2267,9 +2252,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the {@code INFO} logging level,
* the {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category and {@link Function} for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param function the function to evaluate logger message at runtime
* @param <P> the expected payload type.
* against the request {@link Message}.
@@ -2287,9 +2269,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* the {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category and SpEL expression to evaluate
* logger message at runtime against the request {@link Message}.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
* @return the current {@link BaseIntegrationFlowDefinition}.
@@ -2306,9 +2285,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* the {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category and SpEL expression to evaluate
* logger message at runtime against the request {@link Message}.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
@@ -2325,9 +2301,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* {@link LoggingHandler.Level} logging level,
* the provided logging category and SpEL expression to evaluate
* logger message at runtime against the request {@link Message}.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param category the logging category.
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
@@ -2344,9 +2317,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* {@link LoggingHandler.Level} logging level,
* the {@code org.springframework.integration.handler.LoggingHandler}
* as a default logging category and {@link Function} for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param function the function to evaluate logger message at runtime
* @param <P> the expected payload type.
@@ -2363,9 +2333,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided
* {@link LoggingHandler.Level} logging level,
* the provided logging category and {@link Function} for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param category the logging category.
* @param function the function to evaluate logger message at runtime
* @param <P> the expected payload type.
@@ -2382,9 +2349,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided
* {@link LoggingHandler.Level} logging level, logging category
* and {@link Function} for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param category the logging category.
* @param function the function to evaluate logger message at runtime
@@ -2403,9 +2367,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* with the {@link LoggingHandler} subscriber for the provided
* {@link LoggingHandler.Level} logging level, logging category
* and SpEL expression for the log message.
* <p> When this operator is used in the end of flow, it is treated
* as one-way handler without any replies to continue.
* The {@link #logAndReply()} should be used for request-reply configuration.
* @param level the {@link LoggingHandler.Level}.
* @param category the logging category.
* @param logExpression the {@link Expression} to evaluate logger message at runtime
@@ -2441,9 +2402,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* if the {@code replyChannel} header is present.
* <p> This operator can be used only in the end of flow.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply() {
return logAndReply(LoggingHandler.Level.INFO);
}
@@ -2459,9 +2422,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* <p> This operator can be used only in the end of flow.
* @param level the {@link LoggingHandler.Level}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(LoggingHandler.Level level) {
return logAndReply(level, (String) null);
}
@@ -2476,9 +2441,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* <p> This operator can be used only in the end of flow.
* @param category the logging category to use.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(String category) {
return logAndReply(LoggingHandler.Level.INFO, category);
}
@@ -2494,9 +2461,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param level the {@link LoggingHandler.Level}.
* @param category the logging category to use.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(LoggingHandler.Level level, String category) {
return logAndReply(level, category, (Expression) null);
}
@@ -2514,9 +2483,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param logExpression the SpEL expression to evaluate logger message at runtime
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(LoggingHandler.Level level, String category, String logExpression) {
Assert.hasText(logExpression, "'logExpression' must not be empty");
return logAndReply(level, category, PARSER.parseExpression(logExpression));
@@ -2534,9 +2505,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param <P> the expected payload type.
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public <P> IntegrationFlow logAndReply(Function<Message<P>, Object> function) {
Assert.notNull(function, FUNCTION_MUST_NOT_BE_NULL);
return logAndReply(new FunctionExpression<>(function));
@@ -2554,9 +2527,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(Expression logExpression) {
return logAndReply(LoggingHandler.Level.INFO, logExpression);
}
@@ -2575,9 +2550,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(LoggingHandler.Level level, Expression logExpression) {
return logAndReply(level, null, logExpression);
}
@@ -2595,9 +2572,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(String category, Expression logExpression) {
return logAndReply(LoggingHandler.Level.INFO, category, logExpression);
}
@@ -2616,9 +2595,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param <P> the expected payload type.
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public <P> IntegrationFlow logAndReply(LoggingHandler.Level level, Function<Message<P>, Object> function) {
return logAndReply(level, null, function);
}
@@ -2636,9 +2617,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param <P> the expected payload type.
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public <P> IntegrationFlow logAndReply(String category, Function<Message<P>, Object> function) {
return logAndReply(LoggingHandler.Level.INFO, category, function);
}
@@ -2657,9 +2640,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param <P> the expected payload type.
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public <P> IntegrationFlow logAndReply(LoggingHandler.Level level, String category,
Function<Message<P>, Object> function) {
@@ -2680,9 +2665,11 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
* @param logExpression the {@link Expression} to evaluate logger message at runtime
* against the request {@link Message}.
* @return an {@link IntegrationFlow} instance based on this builder.
* @deprecated since 6.0 in favor of {@link #log} in the end of flow.
* @see #log()
* @see #bridge()
*/
@Deprecated
public IntegrationFlow logAndReply(LoggingHandler.Level level, String category, Expression logExpression) {
return log(level, category, logExpression)
.bridge()
@@ -3103,7 +3090,7 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
.stream()
.reduce((first, second) -> second);
if (lastComponent.get() instanceof WireTapSpec) {
channel(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
bridge();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +82,8 @@ public class IntegrationFlowExtensionTests {
.channel("innerChannel")
.customAggregate(customAggregatorSpec ->
customAggregatorSpec.expireGroupsUponCompletion(true))
.logAndReply();
.log()
.get();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -127,7 +127,7 @@ public class FlowServiceTests {
@Bean
public IntegrationFlow testGateway() {
return f -> f.gateway("processChannel", g -> g.replyChannel("replyChannel"))
.logAndReply();
.log();
}
@Bean
@@ -152,7 +152,8 @@ public class FlowServiceTests {
.log(LoggingHandler.Level.ERROR, m -> {
resultOverLoggingHandler.set(m.getPayload());
return m;
});
})
.nullChannel();
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 the original author or authors.
* Copyright 2017-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -297,7 +297,8 @@ public class TransformerTests {
.propertyFunction("date", m -> new Date())
.headerExpression("foo", "payload['name']")
)
.logAndReply();
.log()
.get();
}
@Bean
@@ -463,7 +464,7 @@ public class TransformerTests {
throw new RuntimeException("intentional");
},
e -> e.advice(expressionAdvice()))
.logAndReply();
.log();
}
}

View File

@@ -656,9 +656,9 @@ The following example shows how to use `LoggingHandler`:
In the preceding example, an `id` header is logged at the `ERROR` level onto `test.category` only for messages that passed the filter and before routing.
When this operator is used at the end of a flow, it is a one-way handler and the flow ends.
To make it as a reply-producing flow, you can either use a simple `bridge()` after the `log()` or, starting with version 5.1, you can use a `logAndReply()` operator instead.
`logAndReply` can only be used at the end of a flow.
Starting with version 6.0, the behavior of this operator in the end of flow is aligned with its usage in the middle.
In other words the behavior of the flow remains the same even if the `log()` operator is removed.
So, if a reply is not expected to be produced in the end of the flow, the `nullChannel()` is recommended to be used after the last `log()`.
[[java-dsl-intercept]]
=== Operator intercept()