Skip to content

client_migrate_1 x_to_2 x

etienne-sf edited this page Feb 27, 2023 · 24 revisions

Work in progress (2.x is about to be released)

TODO : update the OAuth document (no more need of the ServerOAuth2AuthorizedClientExchangeFilterFunction)

Introduction

This page describe how to migrate a client implementation from a 1.x version to the last 2.x version.

If you're looking for a migration of the server implementation, please check the Server migration from 1.x to 2.x

The 2.x version is based on spring-graphql. Spring and spring-graphql are responsible for the whole transport part. The first versions allows to easily move from 1.x to 2.x versions.

Main changes

Basic configuration (GraphQL schema, server url...)

(unchanged) The schema file is searched at the

TODO schema file

The

  • In 1.x releases of the plugin the GraphQL endpoint's path is configured by the graphql.url entry in the Spring configuration file (application.yml or application.properties)
    • [for servers only] In the 2.x releases, this configuration is manager by spring. So the relevant configuration entry is spring.graphql.path in the Spring configuration file. Its default value is /graphql
    • [for client only] As there seems to be no way to define two GraphQL server urls in Spring GraphQL yet, the configuration entry remains graphql.endpointXXXXXX.url, where XXXXXX is the suffix defined in your pom.xml or gradle.plugin (it may be undefined, and is then empty)
    • Note: take care that Spring's properties ends with path, whereas the client is an url.
  • Exception management for Subscription
    • It is slightly different, as connection errors are now received by the callback, as the IO are now non blocking.

Spring GraphQlClient

Behind the query, mutation and subscription executors that are generated by the plugin, all requests are actually executed by a Spring GraphQlClient bean. There generated autoconfiguration class contains one or two such beans:

  • A bean named httpGraphQlClient that is used to execute queries and mutations.
    • The beans uses the generated Spring WebClient bean to execute the requests over http.
  • A bean named webSocketGraphQlClient (only if subscriptions are defined in the GraphQL schema), that is used to execute subscriptions

Like all the beans defined in the generated Spring auto configuration class, these beans can be overriden in your own Spring configuration. You'll just have to create a bean of the same name and type, and mark is as @Primary (caution: the generated autoconfiguration class MUST NOT be scanned by your Spring configuration, otherwise it becomes a standard Configuration class, and the @Primary annotation won't work). This allows to, for instance:

  • Define the CodecCustomizer
  • Provide your own HttpClient
  • Add an ExchangeFilterFunction, like the ServerOAuth2AuthorizedClientExchangeFilterFunction to manage OAuth on websocket for subscriptions (see below)

Support removed for javax.ws.rs.client.Client

The javax.ws.rs.client.Client is no more accepted. The Spring stack must be used instead.

Other changes

OAuth

OAuth is now supported by the standard Spring Boot configuration classes.

You'll still have to declare the oauth provider. For instance, for an application.properties that contains:

...

# Configuration for OAuth2, for our local OAuth authorization server
spring.security.oauth2.client.registration.provider_test.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.provider_test.client-id=clientId
spring.security.oauth2.client.registration.provider_test.client-secret=secret

...

then you'll have to define these beans in your configuration class:

	@Bean
	@Primary
	ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction(
			ReactiveClientRegistrationRepository clientRegistrations) {
		ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
				clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
		oauth.setDefaultClientRegistrationId("provider_test");
		return oauth;
	}

	@Bean
	@Primary
	public WebClient webClient(String graphqlEndpoint,
			CodecCustomizer defaultCodecCustomizer,
			@Autowired(required = false) @Qualifier("httpClient") HttpClient httpClient,
			@Autowired(required = false) @Qualifier("serverOAuth2AuthorizedClientExchangeFilterFunction") 				ServerOAuth2AuthorizedClientExchangeFilterFunction serverOAuth2AuthorizedClientExchangeFilterFunction) {
		return WebClient.builder()
				.baseUrl(graphqlEndpoint)
				.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
				.defaultUriVariables(Collections.singletonMap("url", graphqlEndpoint))
				.filter(serverOAuth2AuthorizedClientExchangeFilterFunction)
				.build();
	}

@SpringBootApplication annotation (and removal of GraphQLConfiguration)

The GraphQLConfiguration class has been removed. It was used to manage GraphQL configuration for non Spring apps based on the Jersey http client. The support for these apps has been removed, as the generated code is based on Spring. Non-spring apps are still supported, provided that they are encapsulated in a Spring app, like documented in the non Spring app page.

An impact is the use of the @SpringBootApplication annotation, on the main app class. The GraphqlClientUtils should be used instead, along with the QueryExecutor that must be loaded as Spring Bean, like this:

@SpringBootApplication(scanBasePackageClasses = { SpringMain.class, GraphqlClientUtils.class, QueryExecutor.class })
public class SpringMain {
	... Do something that uses GraphQL
}

How to get the query, mutation and subscription executors?

The generated Executors are Spring beans, and should now be retrieved only as Spring bean, like this:

@Component
public class MyComponent {

	@Autowired
	QueryExecutor queryExecutor;

	public void doSomething(){
		List<Character> withoutParameters() = queryExecutor.withoutParameters("{appearsIn name }");
		...
	}
}

The GraphQLRequest class

It is used to execute full requests. It is now suffixed by the schema suffix defined in the springBeanSuffix defined in the plugin configuration, which is an empty string by default.

Prepared full requests can be prepared like this:

@Component
class MySpringComponent {

	@Autowired
	AnotherMutationTypeExecutor mutationExecutor;
	
	private GraphQLRequest GraphQLRequest;
	
	public MySpringComponent() {
		GraphQLRequest = new GraphQLRequest("mutation{createHuman (human: &humanInput) {id name appearsIn friends {id name}}}");
	}

	void doSomething(Human humanParam) {
		Human human = mutationExecutor.exec(GraphQLRequest, "humanInput", humanParam).getCreateHuman();
		
		... Do something useful with human
	}

Query and Mutation (choice of the transport protocol)

The new queryMutationExecutionProtocol plugin parameter allows to choose between http (default) and webSocket.

Subscription

The SubscriptionClient now contains only the unsubscribe() method. The getSession() (that allows to retrieve the WebSocketSession has been removed, as all the web socket management is now done by spring-graphql)

The SubscriptionCallback interface is unchanged. But its onError(Throwable) method is now called with a GraphQLRequestExecutionException: its getErrors() method allows to retrieve the list of errors returned by the GraphQL server.

Clone this wiki locally