Skip to content

Commit b59a3d6

Browse files
committed
GH-1204 Polish FunctionTypeUtils to ensure works with native
1 parent a7334b2 commit b59a3d6

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
import java.util.function.ToLongFunction;
4545

4646
import com.fasterxml.jackson.databind.JsonNode;
47+
import kotlin.jvm.functions.Function0;
48+
import kotlin.jvm.functions.Function1;
4749
import org.apache.commons.logging.Log;
4850
import org.apache.commons.logging.LogFactory;
4951
import org.reactivestreams.Publisher;
@@ -59,6 +61,7 @@
5961
import org.springframework.cloud.function.context.config.RoutingFunction;
6062
import org.springframework.context.support.GenericApplicationContext;
6163
import org.springframework.core.GenericTypeResolver;
64+
import org.springframework.core.KotlinDetector;
6265
import org.springframework.core.ResolvableType;
6366
import org.springframework.messaging.Message;
6467
import org.springframework.util.Assert;
@@ -203,25 +206,40 @@ public static Method discoverFunctionalMethod(Class<?> pojoFunctionClass) {
203206
}
204207

205208
public static Type discoverFunctionTypeFromClass(Class<?> functionalClass) {
206-
Type t = discoverFunctionTypeFromFunctionMethod(discoverFunctionalMethod(functionalClass));
207-
if (t == null) {
208-
ResolvableType resolvableFunctionType = ResolvableType.forClass(functionalClass);
209-
List<ResolvableType> resolvedGenerics = new ArrayList<>();
210-
if (resolvableFunctionType.hasGenerics()) {
211-
for (ResolvableType generic : resolvableFunctionType.getGenerics()) {
212-
if (generic.getType() instanceof TypeVariable) {
213-
resolvedGenerics.add(ResolvableType.forClass(Object.class));
214-
}
215-
else {
216-
resolvedGenerics.add(generic);
209+
if (KotlinDetector.isKotlinPresent()) {
210+
if (Function1.class.isAssignableFrom(functionalClass)) {
211+
ResolvableType kotlinType = ResolvableType.forClass(functionalClass).as(Function1.class);
212+
return GenericTypeResolver.resolveType(kotlinType.getType(), functionalClass);
213+
}
214+
else if (Function0.class.isAssignableFrom(functionalClass)) {
215+
ResolvableType kotlinType = ResolvableType.forClass(functionalClass).as(Function0.class);
216+
return GenericTypeResolver.resolveType(kotlinType.getType(), functionalClass);
217+
}
218+
}
219+
Type typeToReturn = null;
220+
if (Function.class.isAssignableFrom(functionalClass)) {
221+
for (Type superInterface : functionalClass.getGenericInterfaces()) {
222+
if (superInterface != null && !superInterface.equals(Object.class)) {
223+
if (superInterface.toString().contains("KStream") && ResolvableType.forType(superInterface).getGeneric(1).isArray()) {
224+
return null;
217225
}
218226
}
219227
}
220-
ResolvableType[] generics = resolvedGenerics.toArray(new ResolvableType[] {});
221-
222-
t = ResolvableType.forClassWithGenerics(functionalClass, generics).getType();
228+
ResolvableType functionType = ResolvableType.forClass(functionalClass).as(Function.class);
229+
typeToReturn = GenericTypeResolver.resolveType(functionType.getType(), functionalClass);
230+
}
231+
else if (Consumer.class.isAssignableFrom(functionalClass)) {
232+
ResolvableType functionType = ResolvableType.forClass(functionalClass).as(Consumer.class);
233+
typeToReturn = GenericTypeResolver.resolveType(functionType.getType(), functionalClass);
234+
}
235+
else if (Supplier.class.isAssignableFrom(functionalClass)) {
236+
ResolvableType functionType = ResolvableType.forClass(functionalClass).as(Supplier.class);
237+
typeToReturn = GenericTypeResolver.resolveType(functionType.getType(), functionalClass);
223238
}
224-
return t;
239+
// else {
240+
// typeToReturn = TypeResolver.reify(functionalClass);
241+
// }
242+
return typeToReturn;
225243
}
226244

227245
/**

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
3232
import com.google.gson.Gson;
3333
import io.cloudevents.spring.messaging.CloudEventMessageConverter;
34+
import org.apache.commons.logging.Log;
35+
import org.apache.commons.logging.LogFactory;
3436

3537
import org.springframework.beans.BeanUtils;
3638
import org.springframework.beans.factory.BeanFactory;
@@ -91,6 +93,7 @@
9193
@AutoConfigureAfter(name = {"org.springframework.cloud.function.deployer.FunctionDeployerConfiguration"})
9294
public class ContextFunctionCatalogAutoConfiguration {
9395

96+
private static Log logger = LogFactory.getLog(ContextFunctionCatalogAutoConfiguration.class);
9497
/**
9598
* The name of the property to specify desired JSON mapper. Available values are `jackson' and 'gson'.
9699
*/
@@ -246,7 +249,44 @@ private JsonMapper jackson(ApplicationContext context) {
246249
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
247250
mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
248251
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
252+
if (logger.isDebugEnabled()) {
253+
logger.debug("ObjectMapper configuration: " + getConfigDetails(mapper));
254+
}
249255
return new JacksonMapper(mapper);
250256
}
257+
258+
private static String getConfigDetails(ObjectMapper mapper) {
259+
StringBuilder sb = new StringBuilder();
260+
261+
sb.append("Modules:\n");
262+
if (mapper.getRegisteredModuleIds().isEmpty()) {
263+
sb.append("\t").append("-none-").append("\n");
264+
}
265+
for (Object m : mapper.getRegisteredModuleIds()) {
266+
sb.append(" ").append(m).append("\n");
267+
}
268+
269+
sb.append("\nSerialization Features:\n");
270+
for (SerializationFeature f : SerializationFeature.values()) {
271+
sb.append("\t").append(f).append(" -> ")
272+
.append(mapper.getSerializationConfig().hasSerializationFeatures(f.getMask()));
273+
if (f.enabledByDefault()) {
274+
sb.append(" (enabled by default)");
275+
}
276+
sb.append("\n");
277+
}
278+
279+
sb.append("\nDeserialization Features:\n");
280+
for (DeserializationFeature f : DeserializationFeature.values()) {
281+
sb.append("\t").append(f).append(" -> ")
282+
.append(mapper.getDeserializationConfig().hasDeserializationFeatures(f.getMask()));
283+
if (f.enabledByDefault()) {
284+
sb.append(" (enabled by default)");
285+
}
286+
sb.append("\n");
287+
}
288+
289+
return sb.toString();
290+
}
251291
}
252292
}

0 commit comments

Comments
 (0)