-
Notifications
You must be signed in to change notification settings - Fork 47
client_non_spring
- Introduction
- Use the Spring capabilities with a non spring app
- Tutorials
- Summary
- What does the plugin generate?
- Creating a GraphQL client app
- The minimal app
Since the 1.12 release, the recommended way to build a client with this plugin, is to use it as Spring app. It adds a little latency when starting the app, but it allows all the "magic" of Spring. You can keep your own code to be "non spring", as described in the client FAQ.
This page describes how to use the GraphQL from a jersey http client that you provide to the plugin, or that the plugin will create.
Doing this makes it more difficult to use some complex http configurations (https, cookies...). And very difficult to authenticate against a GraphQL server that would use OAuth, SAML, OpenID Connect... This last point is the main reason that leads to use Spring and its up-to-date Spring Security module. On the contrary, authenticate a Spring Boot application against an OAuth2 protected server is very easy. You can take a look at the OAuth client page page: just add 5 lines of code and some configuration lines, and it's done!
You can use the Spring capabilities with a non spring app. Please check this FAQ for more information on this: Use the Spring capabilities with a non-spring App.
This page is an overview. It contains all the important information on how to create the app.
You'll find a detailed tutorial, with all steps on how to use the client, with two versions:
The client mode makes it easy for a Java GraphQL client-side application, to execute queries/mutations/subscriptions against a GraphQL server. The graphql-maven-plugin generates all the necessary code, so that a Java application can call a GraphQL server by simply calling the relevant Java method.
The plugin manages two kinds of request:
- The Full request: it's actually a standard GraphQL request, that you can test within graphiql
- The Partial request: you can call a java method that executes one of the queries/mutations/subscriptions defined in the schema. This java method accepts one parameter for each parameter of this query/mutation/subscription.
It manages two ways of executing the request:
- The direct execution: you call the generated method with the GraphQL request (partial or full), and you receive the result into Java objects. This is simpler, but slower: for technical reasons, the plugin has to analyze the content of the request. And it will do that at each execution. The main reason for that is to allow proper deserialization of GraphQL interfaces and unions: the
__typename
must be injected into the query, for all returned object, union and interface types, in order to properly deserialize the interfaces and union into the proper class. - The recommended prepared execution:
- A
GraphQLRequest
object is created by the application. This allows to analyze the request only once. If you create theseGraphQLRequest
at application startup, then the syntax control is done once for every requests at startup. This avoids to have errors occurring later, during the app execution. - Each GraphQL request execution is executed from this object.
- Note: the
GraphQLRequest
object has been created in the 1.6 release. The prepared object was before stored into a ObjectResponse. This ObjectResponse has been maintained when used with the withQueryResponseDef Builder method, and the code that uses will continue to work. Support for other Builder method has been removed. There is no plan yet to remove the ObjectResponse object and the withQueryResponseDef Builder method. But they should be avoided in new code.
- A
Both kinds of requests, and both modes of execution allows to use bind parameters into your queries/mutations/subscriptions (see below for more information on that)
When configuring the graphql-maven-plugin in client mode, it reads a GraphQL schema file, and generates all the necessary code to make it easy to call a GraphQL server.
As an overview, it generates:
- One Executor class for each Query/Mutation/Subscription object. These Executors contain all the methods that allow to execute a full query, and shortcut methods to execute the queries, mutations and subscriptions.
- The introspection queries (__schema and __type) are added to the query defined in the GraphQL schema. For "memory", you must provide a query in every GraphQL schema.
- One POJO for each standard object of the GraphQL object
- One java interface for each GraphQL
union
andinterface
- One java class for each GraphQL
type
andinput
type, including the query, mutation and subscription (if any). If the GraphQL type implements an interface, then its java class implements this same interface - One java enum for each GraphQL enum
- One java interface for each GraphQL
- One GraphQLRequest object, that allows to store prepared queries
- You can adapt the plugin behavior to your needs. Take a tour on the Client personalization page for all the information
Please note that all the code below is taken from the Forum sample, available in the graphql-maven-plugin-samples-Forum-client sample, provided here. This module is both a sample, and a project to execute integration tests of the plugin (there is a client and a server projects, to test both sides of GraphQL).
You can access directly to this sample with github in the Maven project or in the Gradle project.
First, you'll have to create or get your GraphQL schema. The GraphQL plugin expects a .graphqls file. See the GraphQL schema doc for all the details.
Then, add the plugin either to your POM file (if you're using Maven) or your build.gradle file (if you're using Gradle):
The POM file looks like this:
<project ...>
...
<properties>
<graphql-maven-plugin.version>2.8</graphql-maven-plugin.version>
</properties>
...
<build>
<plugins>
...
<plugin>
<!-- Just to be sure that your code is based on java 8 or higher -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<release>8</release>
</configuration>
</plugin>
<plugin>
<groupId>com.graphql-java-generator</groupId>
<artifactId>graphql-maven-plugin</artifactId>
<version>${graphql-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>generateClientCode</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>my.target.package</packageName>
<customScalars>
<customScalar>
<graphQLTypeName>Date</graphQLTypeName>
<javaType>java.util.Date</javaType>
<graphQLScalarTypeStaticField>com.graphql_java_generator.customscalars.GraphQLScalarTypeDate.Date</graphQLScalarTypeStaticField>
</customScalar>
</customScalars>
<!-- The parameters below change the 1.x default behavior. They are set to respect the default behavior of the future 2.x versions -->
<generateDeprecatedRequestResponse>false</generateDeprecatedRequestResponse>
<separateUtilityClasses>true</separateUtilityClasses>
<!-- You can add here other plugin parameters -->
</configuration>
</plugin>
<plugin>
<!-- This helps by adding the generated source in the build path of your IDE -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/graphql-maven-plugin</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
...
<extensions>
<!-- Adding these extensions prevents the error below, with JDK 9 and higher: -->
<!-- NoSuchMethodError: 'java.lang.String javax.annotation.Resource.lookup()' -->
<extension>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</extension>
<extension>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</extension>
</extensions>
</plugins>
</build>
...
<dependencies>
<!-- Dependencies for GraphQL -->
<dependency>
<groupId>com.graphql-java-generator</groupId>
<artifactId>graphql-java-client-runtime</artifactId>
<version>${graphql-maven-plugin.version}</version>
</dependency>
...
</dependencies>
...
</project>
The build.gradle file looks like this:
plugins {
id "com.graphql_java_generator.graphql-gradle-plugin" version "2.8"
id 'java'
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
// THE VERSION MUST BE THE SAME AS THE PLUGIN's ONE
implementation "com.graphql-java-generator:graphql-java-client-runtime:2.8"
}
// The line below makes the GraphQL plugin be executed before Java compiles, so that all sources are generated on time
compileJava.dependsOn generateClientCode
processResources.dependsOn generateClientCode
// The line below adds the generated sources as a java source folder in the IDE
sourceSets.main.java.srcDirs += '/build/generated/sources/graphqlGradlePlugin'
sourceSets.main.java.srcDirs += '/build/generated/resources/graphqlGradlePlugin'
// Let's configure the GraphQL Gradle Plugin:
// All available parameters are described here:
// https://graphql-maven-plugin-project.graphql-java-generator.com/graphql-maven-plugin/generateClientCode-mojo.html
generateClientCodeConf {
packageName = 'org.forum.client'
customScalars = [ [
graphQLTypeName: "Date",
javaType: "java.util.Date",
graphQLScalarTypeStaticField: "com.graphql_java_generator.customscalars.GraphQLScalarTypeDate.Date"
] ]
// The parameters below change the 1.x default behavior. They are set to respect the default behavior of the future 2.x versions
generateDeprecatedRequestResponse = false
separateUtilityClasses = true
// You can add here other plugin parameters
}
You can define the package that will contain the generated code. If you don't, the default package is com.generated.graphql.
The necessary runtime source code is joined into the generated code, and remains in its original package, which is com.graphql_java_generator.*. So everything is embedded. Read the Howto personalize the generated code if you want to change this default plugin behavior.
The first build is important, before starting coding. It generates all the POJO, based on the GraphQL schema, and all the utility files.
For Maven, do:
mvn clean install
For Gradle, do:
gradle clean build
Once you've done that, the generated code is available:
- For Maven: in target/generated-sources/graphql-maven-plugin. Thanks to the build-helper-maven-plugin, this folder should be available as a source folder in your IDE.
- For Gradle: in the /build/generated/sources/graphqlGradlePlugin (for Gradle, since 1.15), thanks to the
sourceSets.main.java.srcDirs[..]
line in the build.gradle file
We can now create a first app. It can looks like this:
package com.graphql_java_generator.minimal_app;
import java.util.Date;
import com.graphql_java_generator.exception.GraphQLRequestExecutionException;
import com.graphql_java_generator.exception.GraphQLRequestPreparationException;
import com.graphql_java_generator.samples.forum.client.graphql.forum.client.QueryExecutor;
public class MinimalNonSpringApp {
public static void main(String[] args) throws GraphQLRequestExecutionException, GraphQLRequestPreparationException {
// The executor, that allows to execute GraphQL queries. The class name is the one defined in the GraphQL schema.
// You can instanciate in the same way the mutation and the subscription executors.
QueryExecutor queryExecutor = new QueryExecutor("http://localhost:8180/graphql");
// A basic demo of input parameters
Date date = new Date(2019 - 1900, 12 - 1, 20);
// For this simple sample, we execute a direct query. But prepared queries are recommended.
// Please note that input parameters are mandatory for list or input types.
System.out.println(
"Executing query: '{id name publiclyAvailable topics(since: ¶m){id}}', with input parameter param of value '"
+ date + "'");
System.out
.println(queryExecutor.boards("{id name publiclyAvailable topics(since: ¶m){id}}", "param", date));
}
}
For simplicity, this class contains only the main method. Here is what it does:
- Instanciate a query executor. The class name is the name of the query, as defined in the GraphQL schema.
- You can instanciate in the same way the mutation and the subscription executors.
- Initializes a date variable, to show the use of input parameters.
- Uses the queryExecutor to execute a boards query. The name of the query is the one defined in the GraphQL schema.
- This sample provides the input parameter value (or values, as query/mutation/subscription may contain more than one input parameters), from this couple if method parameters:
- The name of the parameter, as defined in the query string. Here: param
- The runtime value of the parameter.
Creating a first app (non spring)
Connect to more than one GraphQL servers
Easily execute GraphQL requests with GraphQL Repositories
Access to an OAuth2 GraphQL server
How to personalize the client app
Howto personalize the generated code
Client migration from 1.x to 2.x
Implement an OAuth2 GraphQL server
Howto personalize the generated code
Server migration from 1.x to 2.x