Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conflict between GraphQL and OpenAPI when using both extensions #46674

Open
alexfedorenchik opened this issue Mar 7, 2025 · 3 comments
Open

Comments

@alexfedorenchik
Copy link

Describe the bug

I'm developing an application where I need to expose models containing Object fields through GraphQL. To properly handle these Object fields in my GraphQL schema, I've implemented a GraphQLSchema.Builder observer that registers ExtendedScalars.Object.

@GraphQLApi
public class ExampleGraphQLResource {
    @Query
    public ModelExample sayHello() {
        return new ModelExample("graphql", "graphql_data");
    }

    public GraphQLSchema.Builder beforeSchemaBuild(@Observes GraphQLSchema.Builder builder) {
        builder.additionalType(ExtendedScalars.Object);
        return builder;
    }
}

public record ModelExample(String name, Object data) {
}

The GraphQL functionality works perfectly on its own. However, when I add the quarkus-smallrye-openapi extension (which I need for documenting a separate REST endpoint), the application fails to start. The failure occurs due to a type conflict, specifically around the Object type definition.

Expected behavior

Both extensions should work together without type conflicts, allowing the use of Object scalar in GraphQL schema while having OpenAPI documentation enabled.

Actual behavior

  1. Using ExtendedScalars.Object to register Object scalar type in GraphQL schema works fine when only GraphQL extension is present
  2. Adding quarkus-smallrye-openapi extension causes application startup failure
  3. The error indicates a type name conflict:
Caused by: graphql.AssertException: All types within a GraphQL schema must have unique names. No two provided types may have the same name.
No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).
You have redefined the type 'Object' from being a 'GraphQLObjectType' to a 'GraphQLScalarType'

How to Reproduce?

Minimal reproducer project
https://github.com/alexfedorenchik/schema_issue

Output of uname -a or ver

Darwin XXX 24.2.0 Darwin Kernel Version 24.2.0: Fri Dec 6 19:02:41 PST 2024; root:xnu-11215.61.5~2/RELEASE_ARM64_T6030 arm64

Output of java -version

openjdk version "21.0.2" 2024-01-16 OpenJDK Runtime Environment GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30) OpenJDK 64-Bit Server VM GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30, mixed mode, sharing)

Quarkus version or git rev

3.19.2

Build tool (ie. output of mvnw --version or gradlew --version)

Gradle 8.12

Additional information

Ugly workaround

    public GraphQLSchema.Builder beforeSchemaBuild(@Observes GraphQLSchema.Builder builder) {
        try {
            Field additionalTypesField = GraphQLSchema.Builder.class.getDeclaredField("additionalTypes");
            additionalTypesField.setAccessible(true);
            Set<GraphQLType> existingTypes = (Set<GraphQLType>) additionalTypesField.get(builder);

            Set<GraphQLType> updatedTypes = existingTypes.stream()
                .filter(type -> !(type instanceof GraphQLObjectType && ((GraphQLObjectType)type).getName().equals("Object")))
                .collect(Collectors.toSet());

            builder.clearAdditionalTypes();
            builder.additionalTypes(updatedTypes);

        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException("Failed to access builder's additional types", e);
        }

        builder.additionalType(CustomExtendedScalars.Object);
        return builder;
    }
Copy link

quarkus-bot bot commented Mar 7, 2025

/cc @EricWittmann (openapi), @MikeEdgar (openapi), @jmartisk (graphql), @phillip-kruger (graphql,openapi)

@jmartisk
Copy link
Contributor

jmartisk commented Mar 11, 2025

We don't support adding extended scalars this way (because Quarkus needs to know about them at build time already, and this graphql-java API adds it too late). If it sometimes works for you, I think it's kind of a coincidence. The OpenAPI extension registers the java.lang.Object class into the annotation index and that is what breaks the schema building. My guess is that we'll probably need to look into adding it as a new value for the quarkus.smallrye-graphql.extra-scalars property (https://github.com/quarkusio/quarkus/blob/3.19.2/extensions/smallrye-graphql/runtime/src/main/java/io/quarkus/smallrye/graphql/runtime/SmallRyeGraphQLConfig.java#L194) and have Quarkus register it for you...

@alexfedorenchik
Copy link
Author

@jmartisk
That would be amazing! The only thing to note is that my actual code is a bit more complex than the reproducer I shared. I have a custom scalar implementation with custom coercing, so having the ability to register custom scalars would be really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants