1
1
/*
2
- * Copyright 2016-2021 the original author or authors.
2
+ * Copyright 2016-2022 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.
21
21
import java .lang .reflect .Modifier ;
22
22
import java .util .Map ;
23
23
import java .util .Set ;
24
+ import java .util .function .Function ;
24
25
25
26
import org .apache .commons .logging .Log ;
26
27
import org .apache .commons .logging .LogFactory ;
31
32
import org .springframework .core .MethodIntrospector ;
32
33
import org .springframework .core .log .LogMessage ;
33
34
import org .springframework .integration .context .IntegrationContextUtils ;
35
+ import org .springframework .integration .core .GenericSelector ;
36
+ import org .springframework .integration .transformer .GenericTransformer ;
34
37
import org .springframework .lang .Nullable ;
35
38
import org .springframework .messaging .Message ;
39
+ import org .springframework .messaging .MessageHeaders ;
36
40
import org .springframework .messaging .converter .MessageConverter ;
37
41
import org .springframework .util .Assert ;
38
42
import org .springframework .util .ClassUtils ;
@@ -85,11 +89,20 @@ public LambdaMessageProcessor(Object target, @Nullable Class<?> expectedType) {
85
89
"classes with single method - functional interface implementations." );
86
90
87
91
this .method = methods .iterator ().next ();
88
- ReflectionUtils .makeAccessible (this .method );
92
+ if (!isExplicit (target )) {
93
+ ReflectionUtils .makeAccessible (this .method );
94
+ }
89
95
this .parameterTypes = this .method .getParameterTypes ();
90
96
this .expectedType = expectedType ;
91
97
}
92
98
99
+ private static boolean isExplicit (Object target ) {
100
+ return target instanceof Function <?, ?> ||
101
+ target instanceof GenericHandler <?> ||
102
+ target instanceof GenericSelector <?> ||
103
+ target instanceof GenericTransformer <?, ?>;
104
+ }
105
+
93
106
@ Override
94
107
public void setBeanFactory (BeanFactory beanFactory ) throws BeansException {
95
108
this .messageConverter =
@@ -102,20 +115,22 @@ public Object processMessage(Message<?> message) {
102
115
Object [] args = buildArgs (message );
103
116
104
117
try {
105
- Object result = this . method . invoke ( this . target , args );
118
+ Object result = invokeMethod ( args );
106
119
if (result != null && org .springframework .integration .util .ClassUtils .isKotlinUnit (result .getClass ())) {
107
120
result = null ;
108
121
}
109
122
return result ;
110
123
}
124
+ catch (RuntimeException ex ) {
125
+ if (ex instanceof ClassCastException classCastException ) {
126
+ logClassCastException (classCastException );
127
+ }
128
+ throw ex ;
129
+ }
111
130
catch (InvocationTargetException e ) {
112
131
final Throwable cause = e .getCause ();
113
- if (e .getTargetException () instanceof ClassCastException ) {
114
- LOGGER .error ("Could not invoke the method '" + this .method + "' due to a class cast exception, " +
115
- "if using a lambda in the DSL, consider using an overloaded EIP method " +
116
- "that takes a Class<?> argument to explicitly specify the type. " +
117
- "An example of when this often occurs is if the lambda is configured to " +
118
- "receive a Message<?> argument." , cause );
132
+ if (e .getTargetException () instanceof ClassCastException classCastException ) {
133
+ logClassCastException (classCastException );
119
134
}
120
135
if (cause instanceof RuntimeException ) { // NOSONAR
121
136
throw (RuntimeException ) cause ;
@@ -170,4 +185,41 @@ else if (Map.class.isAssignableFrom(parameterType)) {
170
185
return args ;
171
186
}
172
187
188
+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
189
+ private Object invokeMethod (Object [] args ) throws InvocationTargetException , IllegalAccessException {
190
+ if (this .target instanceof Function function ) {
191
+ return function .apply (args [0 ]);
192
+ }
193
+ else if (this .target instanceof GenericSelector selector ) {
194
+ return selector .accept (args [0 ]);
195
+ }
196
+ else if (this .target instanceof GenericTransformer transformer ) {
197
+ return transformer .transform (args [0 ]);
198
+ }
199
+ else if (this .target instanceof GenericHandler handler ) {
200
+ return handler .handle (args [0 ], (MessageHeaders ) args [1 ]);
201
+ }
202
+ else {
203
+ return this .method .invoke (this .target , args );
204
+ }
205
+
206
+ /* TODO when preview features are available in the next Java version
207
+ return switch (this.target) {
208
+ case Function function -> function.apply(args[0]);
209
+ case GenericSelector selector -> selector.accept(args[0]);
210
+ case GenericTransformer transformer -> transformer.transform(args[0]);
211
+ case GenericHandler handler -> handler.handle(args[0], (MessageHeaders) args[1]);
212
+ default -> this.method.invoke(this.target, args);
213
+ };
214
+ */
215
+ }
216
+
217
+ private void logClassCastException (ClassCastException classCastException ) {
218
+ LOGGER .error ("Could not invoke the method '" + this .method + "' due to a class cast exception, " +
219
+ "if using a lambda in the DSL, consider using an overloaded EIP method " +
220
+ "that takes a Class<?> argument to explicitly specify the type. " +
221
+ "An example of when this often occurs is if the lambda is configured to " +
222
+ "receive a Message<?> argument." , classCastException );
223
+ }
224
+
173
225
}
0 commit comments