Skip to content

Support multiple typeNames on @SchemaMapping and @BatchMapping #235

@francis-a

Description

@francis-a

I'm not sure how universal this issue is but I've run into a use-case where it would be useful to be able to define multiple typeNames on a @BatchMapping (and @SchemaMapping) annotation.

My use-case is I have a filed populated by an "expensive" operation that is modeled in GraphQL as a part of an interface and a union type.

interface Model {
   id: String!
   expensiveField:  String!
}

type A implements Model {
   id: String!
   expensiveField:  String!
}

type B implements Model {
   id: String!
   expensiveField:  String!
}

union AorB = A | B

type Query {
 findAorBbyId(id: String!): AorB
}

In Java (Kotlin) I've modeled this schema as

interface Model {
   val id: String
}

data class A(
   override val id: String
)

data class B(
   override val id: String
)

@QueryMapping(name="findAorBbyId")
fun findAorBbyId(@Argument(name = "id"): Model {
   return if(xxx) {
      A("id")
   } else {
      B("id")
   }
}

This works well and allows me to skip defining expensiveField on my Java model and avoid any unnecessary work unless this field is explicitly requested.

In order to resolve the expensiveField field I'm using @BatchMapping, although @QueryMapping would work exactly the same.

    @BatchMapping(typeName = "A", field = "expensiveField")
    fun batchLoadExpensiveFieldA(models: List<Model>) = resolve(models)

    @BatchMapping(typeName = "B", field = "expensiveField")
    fun batchLoadExpensiveFieldB(models: List<Model>) = resolve(models)

This works fine but since I have this field defined on both A and B in my GraphQL schema but not on the shared Java model I have no way to specify a common typeName requiring duplicated @BatchMapping functions.

Checking through the AnnotatedControllerConfigurer it seems like it would be easy enough to update getMappingInfo to return a list of MappingInfos and support defining multiple typeNames.

Annotation annotation = annotations.iterator().next();
if (annotation instanceof SchemaMapping) {
SchemaMapping mapping = (SchemaMapping) annotation;
typeName = mapping.typeName();
field = (StringUtils.hasText(mapping.field()) ? mapping.field() : method.getName());
}
else {
BatchMapping mapping = (BatchMapping) annotation;
typeName = mapping.typeName();
field = (StringUtils.hasText(mapping.field()) ? mapping.field() : method.getName());
batchMapping = true;
}

Would a change like this be useful? Am I missing another way to support this use-use instead?

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions