AssertValidName создает имя, предположительно созданное самой библиотекой. - PullRequest
0 голосов
/ 21 ноября 2018

При этом используется довольно сложный набор сущностей, который в основном состоит из сущностей JPA, но также включает в себя прокси и сущности, извлеченные из API.Я только действительно аннотировал базовый класс, который пытаюсь получить с помощью аннотаций @GraphQLQuery, но он попадает в иерархию, расположенную ниже, и в какой-то момент находит свойство, которое является статическим HashMap<String, String[]> с жестко закодированным содержимым.(Я научился не спрашивать ...) В этот момент он выдает это исключение, и все останавливается:

graphql.AssertException: Name must be non-null, non-empty and match [_A-Za-z][_0-9A-Za-z]* - was 'Map_String_String[]Scalar'
at graphql.Assert.assertValidName(Assert.java:58)
at graphql.schema.GraphQLScalarType.<init>(GraphQLScalarType.java:50)
at graphql.schema.GraphQLScalarType.<init>(GraphQLScalarType.java:45)
at io.leangen.graphql.util.Scalars.graphQLMapScalar(Scalars.java:325)
at io.leangen.graphql.generator.mapping.common.ObjectScalarAdapter.toGraphQLType(ObjectScalarAdapter.java:20)
at io.leangen.graphql.generator.mapping.common.ObjectScalarAdapter.toGraphQLType(ObjectScalarAdapter.java:16)
at io.leangen.graphql.generator.mapping.common.CachingMapper.toGraphQLType(CachingMapper.java:30)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:179)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:165)
at io.leangen.graphql.generator.OperationMapper.toGraphQLField(OperationMapper.java:138)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.lambda$getFields$3(ObjectTypeMapper.java:88)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1625)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.getFields(ObjectTypeMapper.java:89)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.toGraphQLType(ObjectTypeMapper.java:41)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.toGraphQLType(ObjectTypeMapper.java:33)
at io.leangen.graphql.generator.mapping.common.CachingMapper.toGraphQLType(CachingMapper.java:30)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:179)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:165)
at io.leangen.graphql.generator.OperationMapper.toGraphQLField(OperationMapper.java:138)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.lambda$getFields$3(ObjectTypeMapper.java:88)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1625)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.getFields(ObjectTypeMapper.java:89)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.toGraphQLType(ObjectTypeMapper.java:41)
at io.leangen.graphql.generator.mapping.common.ObjectTypeMapper.toGraphQLType(ObjectTypeMapper.java:33)
at io.leangen.graphql.generator.mapping.common.CachingMapper.toGraphQLType(CachingMapper.java:30)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:179)
at io.leangen.graphql.generator.OperationMapper.toGraphQLType(OperationMapper.java:165)
at io.leangen.graphql.generator.OperationMapper.toGraphQLField(OperationMapper.java:138)
at io.leangen.graphql.generator.OperationMapper.lambda$generateQueries$0(OperationMapper.java:91)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at io.leangen.graphql.generator.OperationMapper.generateQueries(OperationMapper.java:92)
at io.leangen.graphql.generator.OperationMapper.<init>(OperationMapper.java:75)
at io.leangen.graphql.GraphQLSchemaGenerator.generate(GraphQLSchemaGenerator.java:868)
at com.ist.exam.graphql.services.GraphQLService.init(GraphQLService.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:349)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:300)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
... 39 more

Я понятия не имею, как генерируется это имя, но оно выглядит как "Map_String_String [] Scalar ", который затем вызывает assertValidName.

Я бы пометил это свойство с помощью @GraphQLQuery(name="somethingClever"), но на данный момент мы находимся в библиотеке, общей для всей компании, и изменения, внесенные здесь, должны пройти череззапрос на изменение и прочее.

Я пытался исключить этот прокси-пакет с помощью withBasePackages, но это, похоже, не дало результата.Это метод, пытающийся создать схему:

GraphQLSchema schema = new GraphQLSchemaGenerator()
                    .withBasePackages("entities")
                    .withResolverBuilders(new AnnotatedResolverBuilder())
                    .withOperationsFromSingleton(examService)
                    .withValueMapperFactory(new JacksonValueMapperFactory())
                    .generate();
            graphQL = GraphQL.newGraphQL(schema).build();

Кто-нибудь видел эти проблемы раньше?Могу ли я занести в черный список пакет вместо белого списка?например, withBasePackages("!proxies")

1 Ответ

0 голосов
/ 02 января 2019

Это ошибка , поскольку недопустимое имя никогда не должно генерироваться.Я исправлю это немедленно в следующем выпуске GraphQL SPQR (текущая версия на момент написания статьи 0.9.9).

Что касается того, как в итоге получится Map_String_String[]Scalar, это скорее вовлекает ..Карты исключительно сложны, так как в GraphQL нет ничего похожего на карту.Варианты в основном состоят в том, чтобы рассматривать карту как список типизированных пар ключ-значение или просто как неизвестную динамическую структуру (так называемая JSON скаляр ).SPQR включает оба подхода, но по умолчанию обрабатывает карты как сложные (JSON) скаляры.Чтобы сохранить некоторое представление о том, что находится внутри, он сгенерирует скаляр с разными именами для каждого базового типа Java.При этом он должен генерировать уникальное имя для каждого.В вашем случае он находит Map<String, String[]>, который генерирует недопустимое имя, которое вы видите - Map_String_String[]Scalar.

Вы можете легко обойти эту проблему, зарегистрировав пользовательский TypeMapper, который поймает этот случай, иливсе сложные скаляры в этом отношении, и дайте им одно и то же имя вместо уникального.

Например

public class CustomObjectScalarMapper extends ObjectScalarMapper {
    private static final String OBJECT_SCALAR_NAME = "ObjectScalar";

    @Override
    protected String getTypeName(AnnotatedType type, BuildContext buildContext) {
        return OBJECT_SCALAR_NAME;
    }

    @Override
    protected String getInputTypeName(AnnotatedType type, BuildContext buildContext) {
        return OBJECT_SCALAR_NAME;
    }
}

И замените существующий ObjectScalarMapper на:

generator.withTypeMappers((conf, current) -> current.replace(ObjectScalarMapper.class, new CustomObjectScalarMapper()))

При этом все сложные скаляры будут называться ObjectScalar, и проблема не возникнет.

Если вы хотите быть более детализированным, переопределите также метод supports.


Небольшое замечание, ваша конфигурация генератора без необходимости устанавливает кучу вещей на значения по умолчанию.

GraphQLSchema schema = new GraphQLSchemaGenerator()
                    .withBasePackages("entities")
                    .withResolverBuilders(new AnnotatedResolverBuilder())
                    .withOperationsFromSingleton(examService)
                    .withValueMapperFactory(new JacksonValueMapperFactory())
                    .generate();

эквивалентно

GraphQLSchema schema = new GraphQLSchemaGenerator()
                    .withBasePackages("entities")
                    .withOperationsFromSingleton(examService)
                    .generate();
...