Spring GraphQL 1.0.0-M3 Released

Releases | Brian Clozel | October 28, 2021 | ...

The Spring GraphQL team is pleased to announce a 3rd milestone towards a 1.0.0 release, driven with great help from the community .

Batch Mapping

The 2nd milestone introduced an annotation programming model for GraphQL data controllers with @SchemaMapping methods. The 3rd milestone adds a new @BatchMapping method.

If you're familiar with GraphQL, you know that navigating an object graph can cause the "N+1 queries problem" if we're not mapping carefully object relations. We could already leverage the Batching feature from GraphQL Java to solve that problem, but this release introduces dedicated support as well as an @BatchMapping annotation for a smoother experience:

@Controller
public class BookController {

    @BatchMapping
    public Mono<Map<Book, Author>> author(List<Book> books) {
        // ...
    }
}

With that example, we're using a GraphQL engine mechanism to efficiently load many Book->Author relations with a single call.

Improved Querydsl Support

The QuerydslDataFetcher support now checks the selected fields for a query and fetches only the corresponding properties of the underlying domain entity.

TypeResolver's

There is now built-in support for TypeResolver's for GraphQL Unions and Interfaces. By default, it tries to match the simple name of a Java class to a GraphQL Object type, and it tries the same for super types in the hierarchy of the class.

There are further options to customize this behavior to provide sufficient hints to match concrete Java classes to GraphQL Object types. Please, try this and let us know how well it works or if you need further flexibility around this feature.

DataBinder for Input Arguments

GraphQL Java parses input arguments to generic Maps of data. Spring GraphQL now uses the Spring Framework DataBinder mechanism to turn those Maps into the typed objects declared on an @Argument controller method parameter. You can hook in the ConversionService to use in the DataBinder to convert individual input fields when needed.

WebSocketInterceptor

There is now a WebSocketInterceptor sub-type of WebInterceptor which can also handle the CONNECTION_INIT and the COMPLETE messages on a WebSocket connection, including access to the CONNECTION_INIT payload along with the ability to reject the connection. Please, give this feature a try and let us know if there is anything further needed.

CORS Configuration

The Spring GraphQL Boot starter provides spring.graphql.cors.* properties to configure CORS for the exposed GraphQL endpoints.

Query Files for GraphQlTester

This release builds on the GraphQlTester API and the testing auto-configuration to help you test your Spring GraphQL application.

GraphQlTester now supports use of *.graphql query files in tests as an alternative to writing queries, inline in the Java test classes. Given a projectReleases.graphql file in your test resources:

query projectReleases($slug: ID!) {
    project(slug: $slug) {
        releases {
            version
        }
    }
}

You can now refer to this query file in your test:

graphQlTester.queryName("projectReleases") 
        .variable("slug", "spring-framework") 
        .execute()
        .path("project.releases[*].version")
        .entityList(String.class)
        .hasSizeGreaterThan(1);

The "JS GraphQL" plugin for IntelliJ supports GraphQL query files with code completion.

"Sliced tests" support with @GraphQlTest

Last but not least, we're now providing a new @GraphQlTest testing facility, quite similar to the @WebMvcTest and @JsonTest Spring Boot annotations. With this, you can write integration tests that rely on particular slice of your application. No need to load the entire application context, only the relevant parts are considered, which makes it easy to mock and test without involving too much infrastructure.

In this example, we're testing our BookController to make sure that it's properly implemented - no need to set up complex data fixtures as we can mock the repository.

@GraphQlTest(controllers = BookController.class)
public class BookControllerTests {

    @Autowired
    private GraphQlTester graphQlTester;

    @MockBean
    private BookRepository bookRepository;

    @Test
    void bookdByIdShouldReturnSpringBook() {
        given(this.bookRepository.findById(42L)).willReturn(new Book(42L, "Spring GraphQL"));
        String query = """
			{
			  bookById(id: "42"){
			    id
			    name
			  }
			}
			""";
        this.graphQlTester.query(query).execute()
                .path("data.bookById.name").entity(String.class).isEqualTo("Spring GraphQL");
    }

}

More improvements and fixes made their way into their release and they're available right now in the new Spring GraphQL 1.0.0-M3 from the Spring Milestone repository.

How can you help?

If you're interested in helping out, you can get started with Spring GraphQL and raise issues on our GitHub project. If you have general questions, please ask on stackoverflow.com using the spring-graphql tag.

Project Page | GitHub | Issues | Documentation | Stack Overflow

Get the Spring newsletter

Thank you for your interest. Someone will get back to you shortly.

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring Runtime offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all