1
1
/*
2
- * Copyright 2002-2018 the original author or authors.
2
+ * Copyright 2002-2019 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
16
16
17
17
package org .springframework .integration .handler .advice ;
18
18
19
+ import org .springframework .beans .factory .BeanFactory ;
19
20
import org .springframework .expression .EvaluationContext ;
20
21
import org .springframework .expression .Expression ;
21
- import org .springframework .expression .spel .standard .SpelExpressionParser ;
22
22
import org .springframework .expression .spel .support .StandardEvaluationContext ;
23
23
import org .springframework .integration .core .MessagingTemplate ;
24
24
import org .springframework .integration .expression .ExpressionUtils ;
25
+ import org .springframework .integration .expression .FunctionExpression ;
25
26
import org .springframework .integration .message .AdviceMessage ;
27
+ import org .springframework .lang .Nullable ;
26
28
import org .springframework .messaging .Message ;
27
29
import org .springframework .messaging .MessageChannel ;
28
30
import org .springframework .messaging .MessagingException ;
31
+ import org .springframework .messaging .core .DestinationResolver ;
29
32
import org .springframework .messaging .support .ErrorMessage ;
33
+ import org .springframework .util .StringUtils ;
30
34
31
35
/**
32
36
* Used to advise {@link org.springframework.messaging.MessageHandler}s.
36
40
* containing the evaluation result in its payload and the {@code inputMessage} property containing
37
41
* the original message that was sent to the endpoint.
38
42
* 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.
39
46
*
40
47
* @author Gary Russell
41
48
* @author Artem Bilan
49
+ *
42
50
* @since 2.2
43
51
*
44
52
*/
45
53
public class ExpressionEvaluatingRequestHandlerAdvice extends AbstractRequestHandlerAdvice {
46
54
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 ();
48
58
49
- private volatile MessageChannel successChannel ;
59
+ private Expression onSuccessExpression ;
50
60
51
- private volatile String successChannelName ;
61
+ private MessageChannel successChannel ;
52
62
53
- private volatile Expression onFailureExpression ;
63
+ private String successChannelName ;
54
64
55
- private volatile MessageChannel failureChannel ;
65
+ private Expression onFailureExpression ;
56
66
57
- private volatile String failureChannelName ;
67
+ private MessageChannel failureChannel ;
58
68
59
- private final MessagingTemplate messagingTemplate = new MessagingTemplate () ;
69
+ private String failureChannelName ;
60
70
61
- private volatile boolean trapException = false ;
71
+ private boolean trapException = false ;
62
72
63
- private volatile boolean returnFailureExpressionResult = false ;
73
+ private boolean returnFailureExpressionResult = false ;
64
74
65
- private volatile boolean propagateOnSuccessEvaluationFailures ;
75
+ private boolean propagateOnSuccessEvaluationFailures ;
66
76
67
- private volatile EvaluationContext evaluationContext ;
77
+ private EvaluationContext evaluationContext ;
68
78
69
79
/**
70
80
* Set the expression to evaluate against the message after a successful
71
81
* handler invocation.
82
+ * Defaults to {@code payload}, if {@code successChannel} is configured.
72
83
* @param onSuccessExpression the SpEL expression.
73
84
* @since 4.3.7
74
85
*/
75
86
public void setOnSuccessExpressionString (String onSuccessExpression ) {
76
- this . onSuccessExpression = new SpelExpressionParser () .parseExpression (onSuccessExpression );
87
+ setOnSuccessExpression ( EXPRESSION_PARSER .parseExpression (onSuccessExpression ) );
77
88
}
78
89
79
90
/**
80
91
* Set the expression to evaluate against the message after a successful
81
92
* handler invocation.
93
+ * Defaults to {@code payload}, if {@code successChannel} is configured.
82
94
* @param onSuccessExpression the SpEL expression.
83
95
* @since 5.0
84
96
*/
85
- public void setOnSuccessExpression (Expression onSuccessExpression ) {
97
+ public void setOnSuccessExpression (@ Nullable Expression onSuccessExpression ) {
86
98
this .onSuccessExpression = onSuccessExpression ;
87
99
}
88
100
@@ -94,26 +106,28 @@ public void setOnSuccessExpression(Expression onSuccessExpression) {
94
106
*/
95
107
@ Deprecated
96
108
public void setExpressionOnSuccess (Expression onSuccessExpression ) {
97
- this . onSuccessExpression = onSuccessExpression ;
109
+ setOnSuccessExpression ( onSuccessExpression ) ;
98
110
}
99
111
100
112
/**
101
113
* 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.
103
116
* @param onFailureExpression the SpEL expression.
104
117
* @since 4.3.7
105
118
*/
106
119
public void setOnFailureExpressionString (String onFailureExpression ) {
107
- this . onFailureExpression = new SpelExpressionParser () .parseExpression (onFailureExpression );
120
+ setOnFailureExpression ( EXPRESSION_PARSER .parseExpression (onFailureExpression ) );
108
121
}
109
122
110
123
/**
111
124
* 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.
113
127
* @param onFailureExpression the SpEL expression.
114
128
* @since 5.0
115
129
*/
116
- public void setOnFailureExpression (Expression onFailureExpression ) {
130
+ public void setOnFailureExpression (@ Nullable Expression onFailureExpression ) {
117
131
this .onFailureExpression = onFailureExpression ;
118
132
}
119
133
@@ -125,7 +139,7 @@ public void setOnFailureExpression(Expression onFailureExpression) {
125
139
*/
126
140
@ Deprecated
127
141
public void setExpressionOnFailure (Expression onFailureExpression ) {
128
- this . onFailureExpression = onFailureExpression ;
142
+ setOnFailureExpression ( onFailureExpression ) ;
129
143
}
130
144
131
145
/**
@@ -178,7 +192,6 @@ public void setTrapException(boolean trapException) {
178
192
/**
179
193
* If true, the result of evaluating the onFailureExpression will
180
194
* be returned as the result of AbstractReplyProducingMessageHandler.handleRequestMessage(Message).
181
- *
182
195
* @param returnFailureExpressionResult true to return the result of the evaluation.
183
196
*/
184
197
public void setReturnFailureExpressionResult (boolean returnFailureExpressionResult ) {
@@ -200,24 +213,39 @@ public void setPropagateEvaluationFailures(boolean propagateOnSuccessEvaluationF
200
213
@ Override
201
214
protected void onInit () {
202
215
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 ;
205
231
}
206
232
}
207
233
208
234
@ 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
+
210
238
try {
211
239
Object result = callback .execute ();
212
240
if (this .onSuccessExpression != null ) {
213
- this . evaluateSuccessExpression (message );
241
+ evaluateSuccessExpression (message );
214
242
}
215
243
return result ;
216
244
}
217
245
catch (Exception e ) {
218
- Exception actualException = this . unwrapExceptionIfNecessary (e );
246
+ Exception actualException = unwrapExceptionIfNecessary (e );
219
247
if (this .onFailureExpression != null ) {
220
- Object evalResult = this . evaluateFailureExpression (message , actualException );
248
+ Object evalResult = evaluateFailureExpression (message , actualException );
221
249
if (this .returnFailureExpressionResult ) {
222
250
return evalResult ;
223
251
}
@@ -229,68 +257,69 @@ protected Object doInvoke(ExecutionCallback callback, Object target, Message<?>
229
257
}
230
258
}
231
259
232
- private void evaluateSuccessExpression (Message <?> message ) throws Exception {
260
+ private void evaluateSuccessExpression (Message <?> message ) throws Exception { // NOSONAR
233
261
Object evalResult ;
234
- boolean evaluationFailed = false ;
235
262
try {
236
- evalResult = this .onSuccessExpression .getValue (this . prepareEvaluationContextToUse (null ), message );
263
+ evalResult = this .onSuccessExpression .getValue (prepareEvaluationContextToUse (null ), message );
237
264
}
238
265
catch (Exception e ) {
239
266
evalResult = e ;
240
- evaluationFailed = true ;
241
267
}
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 );
244
271
}
245
272
if (evalResult != null && this .successChannel != null ) {
246
- AdviceMessage <?> resultMessage = new AdviceMessage <Object >(evalResult , message );
273
+ AdviceMessage <?> resultMessage = new AdviceMessage <>(evalResult , message );
247
274
this .messagingTemplate .send (this .successChannel , resultMessage );
248
275
}
249
- if (evaluationFailed && this .propagateOnSuccessEvaluationFailures ) {
276
+ if (evalResult instanceof Exception && this .propagateOnSuccessEvaluationFailures ) {
250
277
throw (Exception ) evalResult ;
251
278
}
252
279
}
253
280
254
- private Object evaluateFailureExpression (Message <?> message , Exception exception ) throws Exception {
281
+ private Object evaluateFailureExpression (Message <?> message , Exception exception ) {
255
282
Object evalResult ;
256
283
try {
257
- evalResult = this .onFailureExpression .getValue (this . prepareEvaluationContextToUse (exception ), message );
284
+ evalResult = this .onFailureExpression .getValue (prepareEvaluationContextToUse (exception ), message );
258
285
}
259
286
catch (Exception e ) {
260
287
evalResult = e ;
261
288
logger .error ("Failure expression evaluation failed for " + message + ": " + e .getMessage ());
262
289
}
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 );
265
293
}
266
294
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 );
271
300
}
272
301
return evalResult ;
273
302
}
274
303
275
304
protected StandardEvaluationContext createEvaluationContext () {
276
- return ExpressionUtils .createStandardEvaluationContext (this . getBeanFactory ());
305
+ return ExpressionUtils .createStandardEvaluationContext (getBeanFactory ());
277
306
}
278
307
279
308
/**
280
309
* If we don't need variables (i.e., exception is null)
281
310
* 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.
283
312
* @return The context.
284
313
*/
285
314
private EvaluationContext prepareEvaluationContextToUse (Exception exception ) {
286
315
EvaluationContext evaluationContextToUse ;
287
316
if (exception != null ) {
288
- evaluationContextToUse = this . createEvaluationContext ();
317
+ evaluationContextToUse = createEvaluationContext ();
289
318
evaluationContextToUse .setVariable ("exception" , exception );
290
319
}
291
320
else {
292
321
if (this .evaluationContext == null ) {
293
- this .evaluationContext = this . createEvaluationContext ();
322
+ this .evaluationContext = createEvaluationContext ();
294
323
}
295
324
evaluationContextToUse = this .evaluationContext ;
296
325
}
@@ -305,6 +334,7 @@ public static class MessageHandlingExpressionEvaluatingAdviceException extends M
305
334
306
335
public MessageHandlingExpressionEvaluatingAdviceException (Message <?> message , String description ,
307
336
Throwable cause , Object evaluationResult ) {
337
+
308
338
super (message , description , cause );
309
339
this .evaluationResult = evaluationResult ;
310
340
}
0 commit comments