1818
1919import java .lang .annotation .Annotation ;
2020import java .lang .reflect .Method ;
21+ import java .util .Arrays ;
2122import java .util .HashMap ;
2223import java .util .LinkedList ;
2324import java .util .List ;
8485 */
8586class GatewayMethodInboundMessageMapper implements InboundMessageMapper <Object []>, BeanFactoryAware {
8687
87- private static final Log logger = LogFactory .getLog (GatewayMethodInboundMessageMapper .class );
88+ private static final Log LOGGER = LogFactory .getLog (GatewayMethodInboundMessageMapper .class );
8889
8990 private static final SpelExpressionParser PARSER = new SpelExpressionParser ();
9091
@@ -145,18 +146,18 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
145146 this .globalHeaderExpressions = globalHeaderExpressions ;
146147 this .parameterList = getMethodParameterList (method );
147148 this .payloadExpression = parsePayloadExpression (method );
148- if (mapper == null ) {
149- this .argsMapper = new DefaultMethodArgsMessageMapper ();
150- }
151- else {
152- this .argsMapper = mapper ;
153- }
154149 if (messageBuilderFactory == null ) {
155150 this .messageBuilderFactory = new DefaultMessageBuilderFactory ();
156151 }
157152 else {
158153 this .messageBuilderFactory = messageBuilderFactory ;
159154 }
155+ if (mapper == null ) {
156+ this .argsMapper = new DefaultMethodArgsMessageMapper ();
157+ }
158+ else {
159+ this .argsMapper = mapper ;
160+ }
160161 }
161162
162163
@@ -194,13 +195,11 @@ private Message<?> mapArgumentsToMessage(Object[] arguments, @Nullable Map<Strin
194195 try {
195196 return this .argsMapper .toMessage (new MethodArgsHolder (this .method , arguments ), headers );
196197 }
198+ catch (MessagingException e ) { // NOSONAR fto avoid if..else
199+ throw e ;
200+ }
197201 catch (Exception e ) {
198- if (e instanceof MessagingException ) {
199- throw (MessagingException ) e ;
200- }
201- else {
202- throw new MessageMappingException ("Failed to map arguments" , e );
203- }
202+ throw new MessageMappingException ("Failed to map arguments: " + Arrays .toString (arguments ), e );
204203 }
205204 }
206205
@@ -235,8 +234,8 @@ private void copyHeaders(Map<?, ?> argumentValue, Map<String, Object> headers) {
235234 for (Entry <?, ?> entry : argumentValue .entrySet ()) {
236235 Object key = entry .getKey ();
237236 if (!(key instanceof String )) {
238- if (logger .isWarnEnabled ()) {
239- logger .warn ("Invalid header name [" + key +
237+ if (LOGGER .isWarnEnabled ()) {
238+ LOGGER .warn ("Invalid header name [" + key +
240239 "], name type must be String. Skipping mapping of this header to MessageHeaders." );
241240 }
242241 }
@@ -286,13 +285,16 @@ private static Expression parsePayloadExpression(Method method) {
286285
287286 public class DefaultMethodArgsMessageMapper implements MethodArgsMessageMapper {
288287
288+ private final MessageBuilderFactory messageBuilderFactory =
289+ GatewayMethodInboundMessageMapper .this .messageBuilderFactory ;
290+
289291 @ Override
290292 public Message <?> toMessage (MethodArgsHolder holder , @ Nullable Map <String , Object > headers ) {
291293 Object messageOrPayload = null ;
292294 boolean foundPayloadAnnotation = false ;
293295 Object [] arguments = holder .getArgs ();
294296 EvaluationContext methodInvocationEvaluationContext = createMethodInvocationEvaluationContext (arguments );
295- headers =
297+ Map < String , Object > headersToPopulate =
296298 headers != null
297299 ? new HashMap <>(headers )
298300 : new HashMap <>();
@@ -309,76 +311,114 @@ public Message<?> toMessage(MethodArgsHolder holder, @Nullable Map<String, Objec
309311 false );
310312 if (annotation != null ) {
311313 if (annotation .annotationType ().equals (Payload .class )) {
312- if (messageOrPayload != null ) {
313- throwExceptionForMultipleMessageOrPayloadParameters (methodParameter );
314- }
315- String expression = (String ) AnnotationUtils .getValue (annotation );
316- if (!StringUtils .hasText (expression )) {
317- messageOrPayload = argumentValue ;
318- }
319- else {
320- messageOrPayload = evaluatePayloadExpression (expression , argumentValue );
321- }
314+ messageOrPayload =
315+ processPayloadAnnotation (messageOrPayload , argumentValue , methodParameter , annotation );
322316 foundPayloadAnnotation = true ;
323317 }
324318 else if (annotation .annotationType ().equals (Header .class )) {
325- String headerName = determineHeaderName (annotation , methodParameter );
326- if ((Boolean ) AnnotationUtils .getValue (annotation , "required" ) // NOSONAR never null
327- && argumentValue == null ) {
328- throw new IllegalArgumentException ("Received null argument value for required header: '"
329- + headerName + "'" );
330- }
331- headers .put (headerName , argumentValue );
319+ processHeaderAnnotation (headersToPopulate , argumentValue , methodParameter , annotation );
332320 }
333321 else if (annotation .annotationType ().equals (Headers .class )) {
334- if (argumentValue != null ) {
335- if (!(argumentValue instanceof Map )) {
336- throw new IllegalArgumentException (
337- "@Headers annotation is only valid for Map-typed parameters" );
338- }
339- for (Object key : ((Map <?, ?>) argumentValue ).keySet ()) {
340- Assert .isInstanceOf (String .class , key , "Invalid header name [" + key +
341- "], name type must be String." );
342- Object value = ((Map <?, ?>) argumentValue ).get (key );
343- headers .put ((String ) key , value );
344- }
345- }
322+ processHeadersAnnotation (headersToPopulate , argumentValue );
346323 }
347324 }
348325 else if (messageOrPayload == null ) {
349326 messageOrPayload = argumentValue ;
350327 }
351328 else if (Map .class .isAssignableFrom (methodParameter .getParameterType ())) {
352- if (messageOrPayload instanceof Map && !foundPayloadAnnotation ) {
353- if (GatewayMethodInboundMessageMapper .this .payloadExpression == null ) {
354- throw new MessagingException ("Ambiguous method parameters; found more than one " +
355- "Map-typed parameter and neither one contains a @Payload annotation" );
356- }
357- }
358- GatewayMethodInboundMessageMapper .this .copyHeaders ((Map <?, ?>) argumentValue , headers );
329+ processMapArgument (messageOrPayload , foundPayloadAnnotation , headersToPopulate ,
330+ (Map <?, ?>) argumentValue );
359331 }
360332 else if (GatewayMethodInboundMessageMapper .this .payloadExpression == null ) {
361- GatewayMethodInboundMessageMapper .this
362- .throwExceptionForMultipleMessageOrPayloadParameters (methodParameter );
333+ throwExceptionForMultipleMessageOrPayloadParameters (methodParameter );
363334 }
364335 }
365- Assert .isTrue (messageOrPayload != null , "unable to determine a Message or payload parameter on method ["
366- + GatewayMethodInboundMessageMapper .this .method + "]" );
336+
337+ Assert .isTrue (messageOrPayload != null ,
338+ () -> "unable to determine a Message or payload parameter on method ["
339+ + GatewayMethodInboundMessageMapper .this .method + "]" );
340+ populateSendAndReplyTimeoutHeaders (methodInvocationEvaluationContext , headersToPopulate );
341+
342+ return buildMessage (headersToPopulate , messageOrPayload , methodInvocationEvaluationContext );
343+ }
344+
345+ @ Nullable
346+ private Object processPayloadAnnotation (@ Nullable Object messageOrPayload ,
347+ Object argumentValue , MethodParameter methodParameter , Annotation annotation ) {
348+
349+ if (messageOrPayload != null ) {
350+ throwExceptionForMultipleMessageOrPayloadParameters (methodParameter );
351+ }
352+ String expression = (String ) AnnotationUtils .getValue (annotation );
353+ if (!StringUtils .hasText (expression )) {
354+ return argumentValue ;
355+ }
356+ else {
357+ return evaluatePayloadExpression (expression , argumentValue );
358+ }
359+ }
360+
361+ private void processHeaderAnnotation (Map <String , Object > headersToPopulate , @ Nullable Object argumentValue ,
362+ MethodParameter methodParameter , Annotation annotation ) {
363+
364+ String headerName = determineHeaderName (annotation , methodParameter );
365+ if ((Boolean ) AnnotationUtils .getValue (annotation , "required" ) // NOSONAR never null
366+ && argumentValue == null ) {
367+ throw new IllegalArgumentException ("Received null argument value for required header: '"
368+ + headerName + "'" );
369+ }
370+ headersToPopulate .put (headerName , argumentValue );
371+ }
372+
373+ private void processHeadersAnnotation (Map <String , Object > headersToPopulate , @ Nullable Object argumentValue ) {
374+ if (argumentValue != null ) {
375+ if (!(argumentValue instanceof Map )) {
376+ throw new IllegalArgumentException (
377+ "@Headers annotation is only valid for Map-typed parameters" );
378+ }
379+ for (Object key : ((Map <?, ?>) argumentValue ).keySet ()) {
380+ Assert .isInstanceOf (String .class , key , "Invalid header name [" + key +
381+ "], name type must be String." );
382+ Object value = ((Map <?, ?>) argumentValue ).get (key );
383+ headersToPopulate .put ((String ) key , value );
384+ }
385+ }
386+ }
387+
388+ private void processMapArgument (Object messageOrPayload , boolean foundPayloadAnnotation ,
389+ Map <String , Object > headersToPopulate , Map <?, ?> argumentValue ) {
390+
391+ if (messageOrPayload instanceof Map && !foundPayloadAnnotation ) {
392+ if (GatewayMethodInboundMessageMapper .this .payloadExpression == null ) {
393+ throw new MessagingException ("Ambiguous method parameters; found more than one " +
394+ "Map-typed parameter and neither one contains a @Payload annotation" );
395+ }
396+ }
397+ copyHeaders (argumentValue , headersToPopulate );
398+ }
399+
400+ private void populateSendAndReplyTimeoutHeaders (EvaluationContext methodInvocationEvaluationContext ,
401+ Map <String , Object > headersToPopulate ) {
402+
367403 if (GatewayMethodInboundMessageMapper .this .sendTimeoutExpression != null ) {
368- headers .computeIfAbsent (GenericMessagingTemplate .DEFAULT_SEND_TIMEOUT_HEADER ,
404+ headersToPopulate .computeIfAbsent (GenericMessagingTemplate .DEFAULT_SEND_TIMEOUT_HEADER ,
369405 v -> GatewayMethodInboundMessageMapper .this .sendTimeoutExpression
370406 .getValue (methodInvocationEvaluationContext , Long .class ));
371407 }
372408 if (GatewayMethodInboundMessageMapper .this .replyTimeoutExpression != null ) {
373- headers .computeIfAbsent (GenericMessagingTemplate .DEFAULT_RECEIVE_TIMEOUT_HEADER ,
409+ headersToPopulate .computeIfAbsent (GenericMessagingTemplate .DEFAULT_RECEIVE_TIMEOUT_HEADER ,
374410 v -> GatewayMethodInboundMessageMapper .this .replyTimeoutExpression
375411 .getValue (methodInvocationEvaluationContext , Long .class ));
376412 }
377- MessageBuilderFactory messageBuilderFactory = GatewayMethodInboundMessageMapper .this .messageBuilderFactory ;
413+ }
414+
415+ private Message <?> buildMessage (Map <String , Object > headers , Object messageOrPayload ,
416+ EvaluationContext methodInvocationEvaluationContext ) {
417+
378418 AbstractIntegrationMessageBuilder <?> builder =
379419 (messageOrPayload instanceof Message )
380- ? messageBuilderFactory .fromMessage ((Message <?>) messageOrPayload )
381- : messageBuilderFactory .withPayload (messageOrPayload );
420+ ? this . messageBuilderFactory .fromMessage ((Message <?>) messageOrPayload )
421+ : this . messageBuilderFactory .withPayload (messageOrPayload );
382422 builder .copyHeadersIfAbsent (headers );
383423 // Explicit headers in XML override any @Header annotations...
384424 if (!CollectionUtils .isEmpty (GatewayMethodInboundMessageMapper .this .headerExpressions )) {
0 commit comments