Annotated methods returing a String are showing as a collision with unannotated methods returning a String
See original GitHub issueI am using graphql-spqr in a Spring Boot app via the Spring Boot Starter. The Spring Boot Starter currently references 0.9.9 so I included 0.10.0 in my build.gradle
to see if this issue was fixed, but it still persisted in 0.10.0.
Anyway, I have a bunch of entity classes, eg:
import javax.validation.constraints.NotBlank;
public class Entity1 {
public String getField() { return "field value"; }
public int getOtherField() { return 1; }
}
public class Entity2 {
@NotBlank
public String getValidatedField() { return "value"; }
}
These are used in a service annotated with @GraphQLApi
, eg:
@GraphQLApi
public class EntityService {
@GraphQLQuery(name = "entity1")
public Entity1 getEntity1() {
return new Entity1();
}
@GraphQLQuery(name = "entity2")
public Entity2 getEntity2() {
return new Entity2();
}
}
This all works great. However, the following warning is printed to the console on application start:
2019-07-05 13:20:15.910 WARN 31447 --- [ main] i.l.graphql.generator.OperationMapper : Potential type name collision detected: 'String' bound to multiple types: java.lang.String (loaded by the bootstrap class loader) and @javax.validation.constraints.NotBlank(message="{javax.validation.constraints.NotBlank.message}", payload={}, groups={}) java.lang.String (loaded by the bootstrap class loader). Assign unique names using the appropriate annotations or override the TypeInfoGenerator. For details and solutions see https://github.com/leangen/graphql-spqr/wiki/Errors#non-unique-type-name. If this warning is a false positive, please report it: https://github.com/leangen/graphql-spqr/issues.
I spent some time attempting to debug why this occurs, but with no success. The closest I could figure was that “java.lang.String with an annotation” and “java.lang.String” both match the “String” GraphQL type, but when the Validator calls isMappingAllowed
, the comparison fails because it considers “java.lang.String with an annotation” and “java.lang.String” to be different.
Is there a way to ignore annotations that you have no control over and cannot add@GraphQLIgnore
to? Or is this another case to consider for Issue #232
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:8 (5 by maintainers)
For the meantime, you could make a comparator like this:
When comparing types, it will check that they only differ in ignored annotations. You can then register it via:
This is of course way too cumbersome… and will likely change soon… but it is something you can do if you want to.
An update on the subject of SPQR with Scala:
I got my
NonNullSchemaTransformer
to work by first converting the JavaType
s into another tree structure (I called itTypeInfo
) which always wraps nodes in Required or Optional to help with the tree shape problem above. In actual fact, I have five node types(!): ListTypeInfo, RequiredNonLeafTypeInfo, OptionalNonLeafTypeInfo, RequiredLeafTypeInfo, OptionalLeafTypeInfo.Then
SchemaTransformer.transformArgument
andSchemaTransformer.transformField
recursively descend into theGraphQLType
(fromGraphQLArgument.getType
orGraphQLFieldDefinition.getType
) together with the correspondingTypeInfo
(converted fromGraphQLArgument.getBaseType.getType
orOperation.getJavaType.getType
) at each level of recursion. It’s certainly not pretty, but it seems to work.Finally (I hope) I had to create an
ArgumentInjector
to pre-emptInputValueDeserializer
, ensuring that I never receive anull
for anOption
parameter. Might have to revisit that if we ever need to distinguish betweennull
andundefined
as the schema evolves.In summary:
TypeMapper
, aTypeAdapter
, aResolverInterceptor
, aSchemaTransformer
and anArgumentInjector
.Iterable
s, given that it assumes all GraphQL lists are either native arrays orjava.lang.Iterable
s.ResolverInterceptor
is a lifesaver, along with the exampleAuthInterceptor
inInterceptorTest
. Thanks @kaqqao !SchemaTransformer
worries me a bit. It doesn’t handle GraphQL unions or ScalaMap
s yet (don’t need them yet) but it’s already a fair amount of code, so it could be a maintenance problem.ResolutionEnvironment.convertOutput
from my ScalaOptionTypeAdapter).