Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/main/java/graphql/schema/PropertyDataFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import static graphql.Scalars.GraphQLBoolean;
Expand Down Expand Up @@ -44,6 +45,7 @@ public class PropertyDataFetcher<T> implements DataFetcher<T> {

private final String propertyName;
private final Function<Object, Object> function;
private final ConcurrentHashMap<String, String> booleanMethodPrefixCache = new ConcurrentHashMap<>();

/**
* This constructor will use the property name and examine the {@link DataFetchingEnvironment#getSource()}
Expand Down Expand Up @@ -153,11 +155,7 @@ private interface MethodFinder {

private Object getPropertyViaGetterMethod(Object object, GraphQLOutputType outputType, MethodFinder methodFinder) throws NoSuchMethodException {
if (isBooleanProperty(outputType)) {
try {
return getPropertyViaGetterUsingPrefix(object, "is", methodFinder);
} catch (NoSuchMethodException e) {
return getPropertyViaGetterUsingPrefix(object, "get", methodFinder);
}
return getBooleanProperty(object, methodFinder);
} else {
return getPropertyViaGetterUsingPrefix(object, "get", methodFinder);
}
Expand All @@ -173,6 +171,25 @@ private Object getPropertyViaGetterUsingPrefix(Object object, String prefix, Met
}
}

/**
* Read the value of a boolean property, both via accessors named isXXX and getXXX.
* Cache the method prefix to avoid the performance hit of
* NoSuchMethodException.fillInStacktrace.
* Kotlin for example uses getXXX accessors for boolean properties.
*/
private Object getBooleanProperty(Object object, MethodFinder methodFinder) throws NoSuchMethodException {
String className = object.getClass().getCanonicalName();
if (booleanMethodPrefixCache.containsKey(className)) {
return getPropertyViaGetterUsingPrefix(object, booleanMethodPrefixCache.get(className), methodFinder);
}
try {
return getPropertyViaGetterUsingPrefix(object, "is", methodFinder);
} catch (NoSuchMethodException e) {
booleanMethodPrefixCache.put(className, "get");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will it be enough? My guess propertyName should be used in the cache.

return getPropertyViaGetterUsingPrefix(object, "get", methodFinder);
}
}

@SuppressWarnings("SimplifiableIfStatement")
private boolean isBooleanProperty(GraphQLOutputType outputType) {
if (outputType == GraphQLBoolean) return true;
Expand Down