java-graphql-dgs

📁 roelvandun/skills 📅 1 day ago
1
总安装量
1
周安装量
#76254
全站排名
安装命令
npx skills add https://github.com/roelvandun/skills --skill java-graphql-dgs

Agent 安装分布

amp 1
cline 1
opencode 1
cursor 1
kimi-cli 1
codex 1

Skill 文档

Netflix DGS Framework Guide

DGS (Domain Graph Service) is a Netflix framework that makes it easy to build GraphQL services on top of Spring Boot. It uses an annotation-based programming model on top of Spring for GraphQL.

Process

Follow this process when adding or changing a GraphQL feature:

  • Step 1: Define or update the schema in src/main/resources/schema/*.graphqls
  • Step 2: Create or update a @DgsComponent class for the data fetcher
  • Step 3: Annotate the method with @DgsQuery, @DgsMutation, or @DgsSubscription
  • Step 4: Use @InputArgument to bind query arguments
  • Step 5: Write a test using @EnableDgsTest and DgsQueryExecutor

Quick Reference

Maven setup

See Setup for full dependency configuration.

The essential Maven addition (in dependencyManagement):

<dependency>
  <groupId>com.netflix.graphql.dgs</groupId>
  <artifactId>graphql-dgs-platform-dependencies</artifactId>
  <version>10.0.6</version>
  <type>pom</type>
  <scope>import</scope>
</dependency>

Plus the starter:

<dependency>
  <groupId>com.netflix.graphql.dgs</groupId>
  <artifactId>dgs-starter</artifactId>
</dependency>

Schema files

Place all GraphQL schema files in src/main/resources/schema/ with a .graphqls extension. DGS picks them up automatically.

type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  email: String!
  name: String
}

Data fetcher

@DgsComponent
@RequiredArgsConstructor
public class UserDataFetcher {

    private final UserService userService;

    @DgsQuery
    public User user(@InputArgument String id) {
        return userService.findById(id);
    }
}

Mutation

@DgsMutation
public User createUser(@InputArgument CreateUserInput input) {
    return userService.create(input);
}

Use input CreateUserInput { ... } in the schema for mutation arguments.

Child data fetcher (avoid N+1)

When a field requires a separate query, use a child fetcher:

@DgsData(parentType = "User", field = "loyaltyCard")
public LoyaltyCard loyaltyCard(DgsDataFetchingEnvironment dfe) {
    User user = dfe.getSource();
    return cardService.findByCustomerId(user.getId());
}

For collections with N+1 concerns, see Data Fetchers.

Test

@SpringBootTest(classes = {UserDataFetcher.class, UserService.class})
@EnableDgsTest
class UserDataFetcherTest {

    @Autowired
    DgsQueryExecutor dgsQueryExecutor;

    @Test
    void user() {
        String email = dgsQueryExecutor.executeAndExtractJsonPath(
            "{ user(id: \"123\") { email } }",
            "data.user.email"
        );
        assertThat(email).isEqualTo("test@example.com");
    }
}

Reference Files

Core Topics

  • Setup — Maven dependencies, module structure, application properties
  • Data Fetchers — Annotations, arguments, child fetchers, data loaders
  • Mutations — @DgsMutation, input types, sparse updates
  • Data Loaders — @DgsDataLoader, BatchLoader, MappedBatchLoader, Try, virtual threads
  • Subscriptions — @DgsSubscription, WebSocket, SSE, testing
  • Error Handling — @ControllerAdvice, TypedGraphQLError, subscription errors
  • Scalars — @DgsScalar, extended scalars, @DgsRuntimeWiring
  • Code Generation — Gradle/Maven plugin, DgsConstants, type-safe query API
  • Federation — @key, @extends, @DgsEntityFetcher
  • Testing — @EnableDgsTest, DgsQueryExecutor, MockMvc integration
  • Configuration — Full dgs.graphql.* property reference
  • Spring GraphQL Integration — DGS/Spring GraphQL relationship, config overlap

Advanced Topics

Key Rules

Schema design

  • ALWAYS design schema first, then implement data fetchers
  • ALWAYS place schema files in src/main/resources/schema/ with .graphqls extension
  • ALWAYS use input types for mutation arguments: mutation(input: MyInput!)
  • NEVER expose internal domain objects directly — create dedicated GraphQL types

Data fetchers

  • ALWAYS annotate the data fetcher class with @DgsComponent
  • USE @DgsQuery / @DgsMutation as shorthands; use @DgsData(parentType, field) for child fetchers
  • USE @InputArgument on method parameters to bind GraphQL arguments
  • PREFER child fetchers with DgsDataFetchingEnvironment.getSource() over embedding nested data in parent fetchers
  • ALWAYS use @RequiredArgsConstructor with Lombok for constructor injection

Testing

  • ALWAYS test data fetchers with @EnableDgsTest — it is lighter than @SpringBootTest with a full context
  • USE DgsQueryExecutor.executeAndExtractJsonPath() to extract specific fields
  • USE @MockBean to mock service dependencies in data fetcher tests
  • NEVER rely on the HTTP layer in data fetcher unit tests — use DgsQueryExecutor instead

Ground Rules

  • ALWAYS follow schema-first development: schema drives the Java implementation, not the other way around
  • ALWAYS keep @DgsComponent classes free of business logic — delegate to @Service classes
  • NEVER add DGS annotations to @Service or @Repository classes
  • PREFER the DGS programming model over Spring GraphQL annotations for consistency
  • USE the platform BOM to manage DGS dependency versions — never pin individual module versions manually