graphql-java-annotations
graphql-java-annotations copied to clipboard
"Duplicate field found in extension" from GraphQLTypeRetriever.getGraphQLType
I start getting "Duplicate field found in extension" GraphQLTypeRetriever.getGraphQLType when I try to examine the interface after using extensionsHandler.registerTypeExtension
for the implementation.
There seems to be a side impact in the used OutputObjectBuilder that doesn't understand that the annotated interface method exactly the same as what was found previously graphQLObjectInfoRetriever.getOrderedMethods
.
List<String> definedFields = new ArrayList<>();
for (Method method : graphQLObjectInfoRetriever.getOrderedMethods(object)) {
if (method.isBridge() || method.isSynthetic()) {
continue;
}
if (methodSearchAlgorithm.isFound(method)) {
GraphQLFieldDefinition gqlField = graphQLFieldRetriever.getField(method, container);
definedFields.add(gqlField.getName());
builder.field(gqlField);
}
}
for (Field field : getAllFields(object).values()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (fieldSearchAlgorithm.isFound(field)) {
GraphQLFieldDefinition gqlField = graphQLFieldRetriever.getField(field, container);
definedFields.add(gqlField.getName());
builder.field(gqlField);
}
}
for (Class<?> iface : object.getInterfaces()) {
if (iface.getAnnotation(GraphQLTypeResolver.class) != null) {
String ifaceName = graphQLObjectInfoRetriever.getTypeName(iface);
if (container.getProcessing().contains(ifaceName)) {
builder.withInterface(new GraphQLTypeReference(ifaceName));
} else {
builder.withInterface((GraphQLInterfaceType) graphQLInterfaceRetriever.getInterface(iface, container));
}
builder.fields(extensionsHandler.getExtensionFields(iface, definedFields, container));
}
}
builder.fields(extensionsHandler.getExtensionFields(object, definedFields, container));
If the intention is to return extended GraphQLType then I suggest that at least whenever extensions type registry contains the class then extensionshandler is used and otherwise only the parts identical to InputObjectBuilder are used.
public GraphQLObjectType.Builder getOutputObjectBuilder(Class<?> object, ProcessingElementsContainer container) throws GraphQLAnnotationsException {
GraphQLObjectType.Builder builder = newObject();
builder.name(graphQLObjectInfoRetriever.getTypeName(object));
GraphQLDescription description = object.getAnnotation(GraphQLDescription.class);
if (description != null) {
builder.description(description.value());
}
List<String> definedFields = new ArrayList<>();
if (!container.getExtensionsTypeRegistry().containsKey(object)) {
for (Method method : graphQLObjectInfoRetriever.getOrderedMethods(object)) {
if (method.isBridge() || method.isSynthetic()) {
continue;
}
if (methodSearchAlgorithm.isFound(method)) {
GraphQLFieldDefinition gqlField = graphQLFieldRetriever.getField(method, container);
definedFields.add(gqlField.getName());
builder.field(gqlField);
}
}
for (Field field : getAllFields(object).values()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (fieldSearchAlgorithm.isFound(field)) {
GraphQLFieldDefinition gqlField = graphQLFieldRetriever.getField(field, container);
definedFields.add(gqlField.getName());
builder.field(gqlField);
}
}
} else {
for (Class<?> iface : object.getInterfaces()) {
if (iface.getAnnotation(GraphQLTypeResolver.class) != null) {
String ifaceName = graphQLObjectInfoRetriever.getTypeName(iface);
if (container.getProcessing().contains(ifaceName)) {
builder.withInterface(new GraphQLTypeReference(ifaceName));
} else {
builder.withInterface((GraphQLInterfaceType) graphQLInterfaceRetriever.getInterface(iface, container));
}
builder.fields(extensionsHandler.getExtensionFields(iface, definedFields, container));
}
}
builder.fields(extensionsHandler.getExtensionFields(object, definedFields, container));
}
return builder;
}
This of course doesn't help the ambiguous situations when there are multiple implementations of which to choose from and some of the share the same class structure yielding to same/overloaded versions of the methods.
I'd at least change also the GraphQLExtensionsHandler
so that same/overloaded methods would not be processed twice.
@yarinvak and I will have a look at it. If you know how to solve it. we'd be thankful if you sent a PR
can you please show us an example of your usage? and what is the expected behaviour on your side? Also, you can PR this if you know how to solve the problem
Hi @TuomasKiviaho,
We're helping with project maintenance and reviewing the list of opened PRs and Issues.
This issue was created quite a while ago, we were wondering if you were still interested in the outcome, please let us know if this is the case.
Without an answer by July 1st, 2023, this issue will be closed as "inactive" (and can always be re-opened later on if needed).
Thanks,