GraphQL Made Easy for Spring Boot

Build a full-featured GraphQL server with Java or Kotlin in record time

Getting Started Guide

Annotation-based Spring Boot programming model

@DgsComponent
public class ShowsDataFetcher {

  @DgsData(parentType = "Query", field = "shows")
  public List<Show> shows(@InputArgument("titleFilter") String titleFilter) {
      if(titleFilter == null) {
          return shows;
      }

      return shows.stream()
          .filter(s -> s.getTitle().contains(titleFilter))
          .collect(Collectors.toList());
  }

Write query tests as unit tests

@SpringBootTest(classes = {DgsAutoConfiguration.class, ShowsDatafetcher.class})
class ShowsDatafetcherTest {

  @Autowired
  DgsQueryExecutor dgsQueryExecutor;

  @Test
  void shows() {
      List<String> titles = dgsQueryExecutor.executeAndExtractJsonPath(
          " { shows { title releaseYear }}",
          "data.shows[*].title");

      assertThat(titles).contains("Ozark");
  }
}

Create types from schemas with code generation

@DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.SHOW.TYPE_NAME)
public List<Show> shows() {
  return List.of(
    Show.newBuilder()
        .title("Ozark")
        .releaseYear(2017)
        .build()
  );
}

GraphQL subscriptions over WebSockets or SSE

@DgsData(parentType = "Subscription", field = "stocks")
public Publisher stocks() {
  return Flux.interval(Duration.ofSeconds(1)).map({ t -> Tick(t.toString()) })
}

File uploads via GraphQL

@DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = "uploadScriptWithMultipartPOST")
public boolean uploadScript(DataFetchingEnvironment dfe) throws IOException {
  MultipartFile file = dfe.getArgument("input");
  String content = new String(file.getBytes());
  return ! content.isEmpty();
}

Easy integration with GraphQL Federation

type Show @key(fields: "id") @extends {
  id: ID @external
  reviews: [Review]
}

type Review {
  starRating: Int
}
@DgsEntityFetcher(name = "Show")
public Show showEntity(Map values) {
  return new Show(values.get("id"));
}

@DgsData(parentType = "Show", field = "reviews")
public List<Review> reviews(DataFetchingEnvironment dfe) {
  Show show = dfe.getSource();
  return reviewService.getReviews(show.getId());
}

Q&A

How did this project begin?

The DGS framework project started at Netflix in 2019 as internal teams began developing multiple GraphQL services. As 2020 wrapped up, Netflix decided to open source the framework and build a community around it.

Is it production ready?

Yes! Netflix has been using the framework for over a year and a half in different parts of our organisation, including at large scale, before it was open sourced. We've had many releases adding new features, fixing bugs etc., and it has become a very stable platform.

Why not just use graphql-java?

The DGS framework is built on top of graphql-java. Graphql-java is, and should be, lower level building blocks to handle query execution and such. The DGS framework makes all this available with a convenient Spring Boot programming model.

The framework has a lot of Kotlin code, can I use it with Java?

The DGS framework is primarily designed to be used with Java. Although it's primarily written in Kotlin, most consumers of the framework are Java. Of course, if you are using Kotlin, that works great too.

Does Netflix run on a fork of the framework?

No, Netflix is using the same OSS components! We do have some extra modules plugged in for distributed tracing, logging, metrics etc, and we have documentation that shows how to implement similar integrations for your own infrastructure.

Why start with release version 3.x?

Netflix developed and used the framework over the course of almost two years before open sourcing, which involved many releases. After open sourcing the project, we are now using the OSS project internally as well. We did have to wipe out the git history, but continued the versioning we were already using.