11/*
2- * Copyright 2002-2018 the original author or authors.
2+ * Copyright 2002-2019 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616
1717package org .springframework .integration .handler .advice ;
1818
19+ import org .springframework .beans .factory .BeanFactory ;
1920import org .springframework .expression .EvaluationContext ;
2021import org .springframework .expression .Expression ;
21- import org .springframework .expression .spel .standard .SpelExpressionParser ;
2222import org .springframework .expression .spel .support .StandardEvaluationContext ;
2323import org .springframework .integration .core .MessagingTemplate ;
2424import org .springframework .integration .expression .ExpressionUtils ;
25+ import org .springframework .integration .expression .FunctionExpression ;
2526import org .springframework .integration .message .AdviceMessage ;
27+ import org .springframework .lang .Nullable ;
2628import org .springframework .messaging .Message ;
2729import org .springframework .messaging .MessageChannel ;
2830import org .springframework .messaging .MessagingException ;
31+ import org .springframework .messaging .core .DestinationResolver ;
2932import org .springframework .messaging .support .ErrorMessage ;
33+ import org .springframework .util .StringUtils ;
3034
3135/**
3236 * Used to advise {@link org.springframework.messaging.MessageHandler}s.
3640 * containing the evaluation result in its payload and the {@code inputMessage} property containing
3741 * the original message that was sent to the endpoint.
3842 * The failure expression is NOT evaluated if the success expression throws an exception.
43+ * <p>
44+ * When expressions are not configured, but channels are, the default expression is evaluated
45+ * just into a {@code payload} from the message.
3946 *
4047 * @author Gary Russell
4148 * @author Artem Bilan
49+ *
4250 * @since 2.2
4351 *
4452 */
4553public class ExpressionEvaluatingRequestHandlerAdvice extends AbstractRequestHandlerAdvice {
4654
47- private volatile Expression onSuccessExpression ;
55+ private static final Expression DEFAULT_EXPRESSION = new FunctionExpression <Message <?>>(Message ::getPayload );
56+
57+ private final MessagingTemplate messagingTemplate = new MessagingTemplate ();
4858
49- private volatile MessageChannel successChannel ;
59+ private Expression onSuccessExpression ;
5060
51- private volatile String successChannelName ;
61+ private MessageChannel successChannel ;
5262
53- private volatile Expression onFailureExpression ;
63+ private String successChannelName ;
5464
55- private volatile MessageChannel failureChannel ;
65+ private Expression onFailureExpression ;
5666
57- private volatile String failureChannelName ;
67+ private MessageChannel failureChannel ;
5868
59- private final MessagingTemplate messagingTemplate = new MessagingTemplate () ;
69+ private String failureChannelName ;
6070
61- private volatile boolean trapException = false ;
71+ private boolean trapException = false ;
6272
63- private volatile boolean returnFailureExpressionResult = false ;
73+ private boolean returnFailureExpressionResult = false ;
6474
65- private volatile boolean propagateOnSuccessEvaluationFailures ;
75+ private boolean propagateOnSuccessEvaluationFailures ;
6676
67- private volatile EvaluationContext evaluationContext ;
77+ private EvaluationContext evaluationContext ;
6878
6979 /**
7080 * Set the expression to evaluate against the message after a successful
7181 * handler invocation.
82+ * Defaults to {@code payload}, if {@code successChannel} is configured.
7283 * @param onSuccessExpression the SpEL expression.
7384 * @since 4.3.7
7485 */
7586 public void setOnSuccessExpressionString (String onSuccessExpression ) {
76- this . onSuccessExpression = new SpelExpressionParser () .parseExpression (onSuccessExpression );
87+ setOnSuccessExpression ( EXPRESSION_PARSER .parseExpression (onSuccessExpression ) );
7788 }
7889
7990 /**
8091 * Set the expression to evaluate against the message after a successful
8192 * handler invocation.
93+ * Defaults to {@code payload}, if {@code successChannel} is configured.
8294 * @param onSuccessExpression the SpEL expression.
8395 * @since 5.0
8496 */
85- public void setOnSuccessExpression (Expression onSuccessExpression ) {
97+ public void setOnSuccessExpression (@ Nullable Expression onSuccessExpression ) {
8698 this .onSuccessExpression = onSuccessExpression ;
8799 }
88100
@@ -94,26 +106,28 @@ public void setOnSuccessExpression(Expression onSuccessExpression) {
94106 */
95107 @ Deprecated
96108 public void setExpressionOnSuccess (Expression onSuccessExpression ) {
97- this . onSuccessExpression = onSuccessExpression ;
109+ setOnSuccessExpression ( onSuccessExpression ) ;
98110 }
99111
100112 /**
101113 * Set the expression to evaluate against the root message after a failed
102- * handler invocation. The exception is available as the variable {@code #exception}
114+ * handler invocation. The exception is available as the variable {@code #exception}.
115+ * Defaults to {@code payload}, if {@code failureChannel} is configured.
103116 * @param onFailureExpression the SpEL expression.
104117 * @since 4.3.7
105118 */
106119 public void setOnFailureExpressionString (String onFailureExpression ) {
107- this . onFailureExpression = new SpelExpressionParser () .parseExpression (onFailureExpression );
120+ setOnFailureExpression ( EXPRESSION_PARSER .parseExpression (onFailureExpression ) );
108121 }
109122
110123 /**
111124 * Set the expression to evaluate against the root message after a failed
112- * handler invocation. The exception is available as the variable {@code #exception}
125+ * handler invocation. The exception is available as the variable {@code #exception}.
126+ * Defaults to {@code payload}, if {@code failureChannel} is configured.
113127 * @param onFailureExpression the SpEL expression.
114128 * @since 5.0
115129 */
116- public void setOnFailureExpression (Expression onFailureExpression ) {
130+ public void setOnFailureExpression (@ Nullable Expression onFailureExpression ) {
117131 this .onFailureExpression = onFailureExpression ;
118132 }
119133
@@ -125,7 +139,7 @@ public void setOnFailureExpression(Expression onFailureExpression) {
125139 */
126140 @ Deprecated
127141 public void setExpressionOnFailure (Expression onFailureExpression ) {
128- this . onFailureExpression = onFailureExpression ;
142+ setOnFailureExpression ( onFailureExpression ) ;
129143 }
130144
131145 /**
@@ -178,7 +192,6 @@ public void setTrapException(boolean trapException) {
178192 /**
179193 * If true, the result of evaluating the onFailureExpression will
180194 * be returned as the result of AbstractReplyProducingMessageHandler.handleRequestMessage(Message).
181- *
182195 * @param returnFailureExpressionResult true to return the result of the evaluation.
183196 */
184197 public void setReturnFailureExpressionResult (boolean returnFailureExpressionResult ) {
@@ -200,24 +213,39 @@ public void setPropagateEvaluationFailures(boolean propagateOnSuccessEvaluationF
200213 @ Override
201214 protected void onInit () {
202215 super .onInit ();
203- if (this .getBeanFactory () != null ) {
204- this .messagingTemplate .setBeanFactory (this .getBeanFactory ());
216+ BeanFactory beanFactory = getBeanFactory ();
217+ if (beanFactory != null ) {
218+ this .messagingTemplate .setBeanFactory (beanFactory );
219+ }
220+
221+ if (this .onSuccessExpression == null
222+ && (this .successChannel != null || StringUtils .hasText (this .successChannelName ))) {
223+
224+ this .onSuccessExpression = DEFAULT_EXPRESSION ;
225+ }
226+
227+ if (this .onFailureExpression == null
228+ && (this .failureChannel != null || StringUtils .hasText (this .failureChannelName ))) {
229+
230+ this .onFailureExpression = DEFAULT_EXPRESSION ;
205231 }
206232 }
207233
208234 @ Override
209- protected Object doInvoke (ExecutionCallback callback , Object target , Message <?> message ) throws Exception {
235+ protected Object doInvoke (ExecutionCallback callback , Object target , Message <?> message )
236+ throws Exception { // NOSONAR
237+
210238 try {
211239 Object result = callback .execute ();
212240 if (this .onSuccessExpression != null ) {
213- this . evaluateSuccessExpression (message );
241+ evaluateSuccessExpression (message );
214242 }
215243 return result ;
216244 }
217245 catch (Exception e ) {
218- Exception actualException = this . unwrapExceptionIfNecessary (e );
246+ Exception actualException = unwrapExceptionIfNecessary (e );
219247 if (this .onFailureExpression != null ) {
220- Object evalResult = this . evaluateFailureExpression (message , actualException );
248+ Object evalResult = evaluateFailureExpression (message , actualException );
221249 if (this .returnFailureExpressionResult ) {
222250 return evalResult ;
223251 }
@@ -229,68 +257,69 @@ protected Object doInvoke(ExecutionCallback callback, Object target, Message<?>
229257 }
230258 }
231259
232- private void evaluateSuccessExpression (Message <?> message ) throws Exception {
260+ private void evaluateSuccessExpression (Message <?> message ) throws Exception { // NOSONAR
233261 Object evalResult ;
234- boolean evaluationFailed = false ;
235262 try {
236- evalResult = this .onSuccessExpression .getValue (this . prepareEvaluationContextToUse (null ), message );
263+ evalResult = this .onSuccessExpression .getValue (prepareEvaluationContextToUse (null ), message );
237264 }
238265 catch (Exception e ) {
239266 evalResult = e ;
240- evaluationFailed = true ;
241267 }
242- if (this .successChannel == null && this .successChannelName != null && getChannelResolver () != null ) {
243- this .successChannel = getChannelResolver ().resolveDestination (this .successChannelName );
268+ DestinationResolver <MessageChannel > channelResolver = getChannelResolver ();
269+ if (this .successChannel == null && this .successChannelName != null && channelResolver != null ) {
270+ this .successChannel = channelResolver .resolveDestination (this .successChannelName );
244271 }
245272 if (evalResult != null && this .successChannel != null ) {
246- AdviceMessage <?> resultMessage = new AdviceMessage <Object >(evalResult , message );
273+ AdviceMessage <?> resultMessage = new AdviceMessage <>(evalResult , message );
247274 this .messagingTemplate .send (this .successChannel , resultMessage );
248275 }
249- if (evaluationFailed && this .propagateOnSuccessEvaluationFailures ) {
276+ if (evalResult instanceof Exception && this .propagateOnSuccessEvaluationFailures ) {
250277 throw (Exception ) evalResult ;
251278 }
252279 }
253280
254- private Object evaluateFailureExpression (Message <?> message , Exception exception ) throws Exception {
281+ private Object evaluateFailureExpression (Message <?> message , Exception exception ) {
255282 Object evalResult ;
256283 try {
257- evalResult = this .onFailureExpression .getValue (this . prepareEvaluationContextToUse (exception ), message );
284+ evalResult = this .onFailureExpression .getValue (prepareEvaluationContextToUse (exception ), message );
258285 }
259286 catch (Exception e ) {
260287 evalResult = e ;
261288 logger .error ("Failure expression evaluation failed for " + message + ": " + e .getMessage ());
262289 }
263- if (this .failureChannel == null && this .failureChannelName != null && getChannelResolver () != null ) {
264- this .failureChannel = getChannelResolver ().resolveDestination (this .failureChannelName );
290+ DestinationResolver <MessageChannel > channelResolver = getChannelResolver ();
291+ if (this .failureChannel == null && this .failureChannelName != null && channelResolver != null ) {
292+ this .failureChannel = channelResolver .resolveDestination (this .failureChannelName );
265293 }
266294 if (evalResult != null && this .failureChannel != null ) {
267- MessagingException messagingException = new MessageHandlingExpressionEvaluatingAdviceException (message ,
268- "Handler Failed" , this .unwrapThrowableIfNecessary (exception ), evalResult );
269- ErrorMessage resultMessage = new ErrorMessage (messagingException );
270- this .messagingTemplate .send (this .failureChannel , resultMessage );
295+ MessagingException messagingException =
296+ new MessageHandlingExpressionEvaluatingAdviceException (message , "Handler Failed" ,
297+ unwrapThrowableIfNecessary (exception ), evalResult );
298+ ErrorMessage errorMessage = new ErrorMessage (messagingException );
299+ this .messagingTemplate .send (this .failureChannel , errorMessage );
271300 }
272301 return evalResult ;
273302 }
274303
275304 protected StandardEvaluationContext createEvaluationContext () {
276- return ExpressionUtils .createStandardEvaluationContext (this . getBeanFactory ());
305+ return ExpressionUtils .createStandardEvaluationContext (getBeanFactory ());
277306 }
278307
279308 /**
280309 * If we don't need variables (i.e., exception is null)
281310 * we can use a singleton context; otherwise we need a new one each time.
282- * @param exception
311+ * @param exception the {@link Exception} to use in the context.
283312 * @return The context.
284313 */
285314 private EvaluationContext prepareEvaluationContextToUse (Exception exception ) {
286315 EvaluationContext evaluationContextToUse ;
287316 if (exception != null ) {
288- evaluationContextToUse = this . createEvaluationContext ();
317+ evaluationContextToUse = createEvaluationContext ();
289318 evaluationContextToUse .setVariable ("exception" , exception );
290319 }
291320 else {
292321 if (this .evaluationContext == null ) {
293- this .evaluationContext = this . createEvaluationContext ();
322+ this .evaluationContext = createEvaluationContext ();
294323 }
295324 evaluationContextToUse = this .evaluationContext ;
296325 }
@@ -305,6 +334,7 @@ public static class MessageHandlingExpressionEvaluatingAdviceException extends M
305334
306335 public MessageHandlingExpressionEvaluatingAdviceException (Message <?> message , String description ,
307336 Throwable cause , Object evaluationResult ) {
337+
308338 super (message , description , cause );
309339 this .evaluationResult = evaluationResult ;
310340 }
0 commit comments