Skip to content

Commit f354950

Browse files
committed
Improve logging of controller method mappings
1 parent f4c6fca commit f354950

File tree

3 files changed

+49
-35
lines changed

3 files changed

+49
-35
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/federation/FederationSchemaFactory.java

+8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Map;
2323
import java.util.concurrent.CompletionStage;
2424
import java.util.function.BiFunction;
25+
import java.util.stream.Collectors;
2526

2627
import com.apollographql.federation.graphqljava.Federation;
2728
import com.apollographql.federation.graphqljava.SchemaTransformer;
@@ -98,6 +99,13 @@ public void afterPropertiesSet() {
9899
if (this.typeResolver == null) {
99100
this.typeResolver = new ClassNameTypeResolver();
100101
}
102+
103+
if (logger.isTraceEnabled()) {
104+
String formatted = this.handlerMethods.entrySet().stream()
105+
.map((entry) -> entry.getKey() + " -> " + entry.getValue().getShortLogMessage())
106+
.collect(Collectors.joining("\n", "\n", "\n"));
107+
logger.trace("@EntityMapping registrations:" + formatted);
108+
}
101109
}
102110

103111
@Override

spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java

+31-2
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,13 @@ public void configure(RuntimeWiring.Builder runtimeWiringBuilder) {
257257
allInfos.forEach((info) -> registerDataFetcher(info, runtimeWiringBuilder));
258258

259259
RuntimeWiring wiring = runtimeWiringBuilder.build();
260-
subTypeInfos = this.interfaceMappingHelper.filterExistingMappings(subTypeInfos, wiring.getDataFetchers());
260+
subTypeInfos = this.interfaceMappingHelper.removeExplicitMappings(subTypeInfos, wiring.getDataFetchers());
261261

262262
subTypeInfos.forEach((info) -> registerDataFetcher(info, runtimeWiringBuilder));
263+
264+
if (logger.isTraceEnabled()) {
265+
logger.trace("Controller method registrations:" + formatRegistrations(runtimeWiringBuilder));
266+
}
263267
}
264268

265269
@Override
@@ -403,6 +407,16 @@ private DataFetcher<Object> registerBatchLoader(DataFetcherMappingInfo info) {
403407
"Mono<Map<K, V>>, Map<K, V>, Flux<V>, or Collection<V>: " + handlerMethod);
404408
}
405409

410+
@SuppressWarnings("rawtypes")
411+
protected static String formatRegistrations(RuntimeWiring.Builder wiringBuilder) {
412+
return wiringBuilder.build().getDataFetchers().entrySet().stream()
413+
.map((typeEntry) -> typeEntry.getKey() + ":\n" +
414+
typeEntry.getValue().entrySet().stream()
415+
.map((fieldEntry) -> fieldEntry.getKey() + " -> " + fieldEntry.getValue())
416+
.collect(Collectors.joining("\n\t", "\t", "")))
417+
.collect(Collectors.joining("\n", "\n", "\n"));
418+
}
419+
406420
/**
407421
* Alternative to {@link #configure(RuntimeWiring.Builder)} that registers
408422
* data fetchers in a {@link GraphQLCodeRegistry.Builder}. This could be
@@ -587,6 +601,11 @@ public Object get(DataFetchingEnvironment env) {
587601
Assert.state(dataLoader != null, "No DataLoader for key '" + this.dataLoaderKey + "'");
588602
return dataLoader.load(env.getSource());
589603
}
604+
605+
@Override
606+
public String toString() {
607+
return getDescription();
608+
}
590609
}
591610

592611

@@ -597,6 +616,9 @@ private static final class InterfaceMappingHelper {
597616

598617
private final MultiValueMap<String, String> interfaceMappings = new LinkedMultiValueMap<>();
599618

619+
/**
620+
* Extract information interface implementation types.
621+
*/
600622
void setTypeDefinitionRegistry(TypeDefinitionRegistry registry) {
601623
for (TypeDefinition<?> definition : registry.types().values()) {
602624
if (definition instanceof ObjectTypeDefinition objectDefinition) {
@@ -607,6 +629,10 @@ void setTypeDefinitionRegistry(TypeDefinitionRegistry registry) {
607629
}
608630
}
609631

632+
/**
633+
* Remove mappings to interface fields, and return mappings for the same
634+
* fields in all implementing types.
635+
*/
610636
Set<DataFetcherMappingInfo> removeInterfaceMappings(Set<DataFetcherMappingInfo> infos) {
611637
Set<DataFetcherMappingInfo> subTypeMappings = new LinkedHashSet<>();
612638
Iterator<DataFetcherMappingInfo> it = infos.iterator();
@@ -623,8 +649,11 @@ Set<DataFetcherMappingInfo> removeInterfaceMappings(Set<DataFetcherMappingInfo>
623649
return subTypeMappings;
624650
}
625651

652+
/**
653+
* Remove mappings that are covered by explicit {@link DataFetcher} registrations.
654+
*/
626655
@SuppressWarnings("rawtypes")
627-
Set<DataFetcherMappingInfo> filterExistingMappings(
656+
Set<DataFetcherMappingInfo> removeExplicitMappings(
628657
Set<DataFetcherMappingInfo> infos, Map<String, Map<String, DataFetcher>> dataFetchers) {
629658

630659
return infos.stream()

spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerDetectionSupport.java

+10-33
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package org.springframework.graphql.data.method.annotation.support;
1818

1919
import java.lang.reflect.Method;
20-
import java.lang.reflect.Type;
21-
import java.util.Arrays;
2220
import java.util.Collection;
2321
import java.util.Collections;
2422
import java.util.LinkedHashSet;
@@ -28,7 +26,6 @@
2826
import java.util.concurrent.Callable;
2927
import java.util.concurrent.Executor;
3028
import java.util.function.Predicate;
31-
import java.util.stream.Collectors;
3229

3330
import graphql.schema.DataFetcher;
3431
import org.apache.commons.logging.Log;
@@ -258,13 +255,12 @@ protected Set<M> detectHandlerMethods() {
258255
continue;
259256
}
260257
Class<?> beanClass = context.getType(beanName);
261-
findHandlerMethods(beanName, beanClass).forEach((info) -> registerHandlerMethod(info, results));
258+
findHandlerMethods(beanName, beanClass).forEach((info) -> addHandlerMethod(info, results));
262259
}
260+
263261
return results;
264262
}
265263

266-
protected abstract HandlerMethod getHandlerMethod(M mappingInfo);
267-
268264
private Collection<M> findHandlerMethods(Object handler, @Nullable Class<?> handlerClass) {
269265
if (handlerClass == null) {
270266
return Collections.emptyList();
@@ -274,34 +270,20 @@ private Collection<M> findHandlerMethods(Object handler, @Nullable Class<?> hand
274270
Map<Method, M> map = MethodIntrospector.selectMethods(
275271
userClass, (Method method) -> getMappingInfo(method, handler, userClass));
276272

277-
Collection<M> mappingInfos = map.values();
278-
279-
if (this.logger.isTraceEnabled() && !mappingInfos.isEmpty()) {
280-
this.logger.trace(formatMappings(userClass, mappingInfos));
281-
}
282-
283-
return mappingInfos;
273+
return map.values();
284274
}
285275

286276
@Nullable
287277
protected abstract M getMappingInfo(Method method, Object handler, Class<?> handlerType);
288278

289-
private String formatMappings(Class<?> handlerType, Collection<M> infos) {
290-
String formattedType = Arrays.stream(ClassUtils.getPackageName(handlerType).split("\\."))
291-
.map((p) -> p.substring(0, 1))
292-
.collect(Collectors.joining(".", "", "." + handlerType.getSimpleName()));
293-
return infos.stream()
294-
.map((info) -> {
295-
Method method = getHandlerMethod(info).getMethod();
296-
String methodParameters = Arrays.stream(method.getGenericParameterTypes())
297-
.map(Type::getTypeName)
298-
.collect(Collectors.joining(",", "(", ")"));
299-
return info + methodParameters;
300-
})
301-
.collect(Collectors.joining("\n\t", "\n\t" + formattedType + ":" + "\n\t", ""));
279+
protected HandlerMethod createHandlerMethod(Method originalMethod, Object handler, Class<?> handlerType) {
280+
Method method = AopUtils.selectInvocableMethod(originalMethod, handlerType);
281+
return (handler instanceof String beanName) ?
282+
new HandlerMethod(beanName, obtainApplicationContext().getAutowireCapableBeanFactory(), method) :
283+
new HandlerMethod(handler, method);
302284
}
303285

304-
private void registerHandlerMethod(M info, Set<M> results) {
286+
private void addHandlerMethod(M info, Set<M> results) {
305287
Assert.state(this.exceptionResolver != null, "afterPropertiesSet not called");
306288
HandlerMethod handlerMethod = getHandlerMethod(info);
307289
M existing = results.stream().filter((o) -> o.equals(info)).findFirst().orElse(null);
@@ -315,12 +297,7 @@ private void registerHandlerMethod(M info, Set<M> results) {
315297
this.exceptionResolver.registerController(handlerMethod.getBeanType());
316298
}
317299

318-
protected HandlerMethod createHandlerMethod(Method originalMethod, Object handler, Class<?> handlerType) {
319-
Method method = AopUtils.selectInvocableMethod(originalMethod, handlerType);
320-
return (handler instanceof String beanName) ?
321-
new HandlerMethod(beanName, obtainApplicationContext().getAutowireCapableBeanFactory(), method) :
322-
new HandlerMethod(handler, method);
323-
}
300+
protected abstract HandlerMethod getHandlerMethod(M mappingInfo);
324301

325302
protected boolean shouldInvokeAsync(HandlerMethod handlerMethod) {
326303
return (this.blockingMethodPredicate.test(handlerMethod) && this.executor != null &&

0 commit comments

Comments
 (0)