Netflix / Netflix/dgs-codegen

EntitiesProjectionRoot - duplicated entries when using "extend type"

Open
#878 0 comments 0 reactions 1 assignee View on GitHub

@paulbakker is already working on this.

Since Oct 6, 2025.

investigate
Dominant language
Kotlin
Stars
217
Forks
116
PR merge metrics
No merged PRs in 30d

Description

When using the DGS code generator with multiple subgraph schemas, if several schemas use extend type to add fields to the same type, the code generator may generate duplicate methods in the projection classes. For example, if AnimalWithDetails is extended in multiple schema files, the generated EntitiesProjectionRoot.java can contain multiple identical onAnimalWithDetails() methods, causing compilation errors.
This issue occurs even when using the @extends directive at the same time with "extended". The root cause seems to be that the code generator does not properly deduplicate type extensions across schema files, leading to repeated method definitions in the generated code.

I'm a bit lost why this is happening, I've only that 2 schemas! Deleted the rest to try to find the root cause, in the example bellow the projection is generated with 2 methods with the same signature.

I'm missing something?
Thanks in advance

Build.gradle:

plugins {
    id 'com.netflix.dgs.codegen' version '8.1.1' apply false
}

.....

generateJava {
    schemaPaths = ["${rootDir}/my_other_source/src/main/resources/schema",
                   "${projectDir}/src/main/resources/schema"]
    // List of directories containing schema files
    packageName = 'my.package.proxy.codegen'
    // The package name to use to generate sources
    generateClient = true // Enable generating the type safe query API
}

core.graphql:

"""Root query type (extended by subgraphs)."""
type Query

interface AnimalInterface @key(fields: "someId") {
    someId: ID
    license: String
    nickname: String
}

type Animal implements AnimalInterface @key(fields: "someId") {
    someId: ID
    license: String
    nickname: String
}

type AnimalWithDetails implements AnimalInterface @key(fields: "someId") {
    someId: ID
    license: String
    nickname: String
}

other_subgraph.graphql

extend type Query {
	getAnimalData(someId: String): AnimalWithDetails
}

extend type AnimalWithDetails @key(fields: "someId") {
	speciesName: String
	color: String
}

Generated EntitiesProjectionRoot.java

package ....;

import com.netflix.graphql.dgs.client.codegen.BaseSubProjectionNode;

public class EntitiesProjectionRoot<PARENT extends BaseSubProjectionNode<?, ?>, ROOT extends BaseSubProjectionNode<?, ?>> extends BaseSubProjectionNode<PARENT, ROOT> {
  public EntitiesProjectionRoot() {
    super(null, null, java.util.Optional.of("_entities"));
  }

  public EntitiesAnimalKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> onAnimal(
      ) {
     EntitiesAnimalKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> fragment = new EntitiesAnimalKeyProjection(this, this);
     getFragments().add(fragment);
     return fragment;
  }

  public EntitiesAnimalWithDetailsKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> onAnimalWithDetails(
      ) {
     EntitiesAnimalWithDetailsKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> fragment = new EntitiesAnimalWithDetailsKeyProjection(this, this);
     getFragments().add(fragment);
     return fragment;
  }

  public EntitiesAnimalWithDetailsKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> onAnimalWithDetails(
      ) {
     EntitiesAnimalWithDetailsKeyProjection<EntitiesProjectionRoot<PARENT, ROOT>, EntitiesProjectionRoot<PARENT, ROOT>> fragment = new EntitiesAnimalWithDetailsKeyProjection(this, this);
     getFragments().add(fragment);
     return fragment;
  }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.