Skip to content

Commit a8f2226

Browse files
author
Shane Myrick
committed
Update context docs
1 parent 7e6c51e commit a8f2226

File tree

4 files changed

+208
-214
lines changed

4 files changed

+208
-214
lines changed

docs/execution/contextual-data.md

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ Once context factory bean is available in the Spring application context it will
1818
to populate GraphQL context based on the incoming request and make it available during query execution. See [graphql-kotlin-spring-server documentation](../spring-server/spring-graphql-context)
1919
for additional details
2020

21-
Once your application is configured to build your custom `MyGraphQLContext`, simply add `@GraphQLContext` annotation to
22-
any function argument and the corresponding GraphQL context from the environment will be automatically injected during
23-
execution.
21+
## GraphQLContext Interface
22+
23+
Once your application is configured to build your custom `MyGraphQLContext`, simply mark the class with the `GraphQLContext` interface and the
24+
corresponding GraphQL context from the environment will be automatically injected during execution.
2425

2526
```kotlin
26-
class ContextualQuery {
27+
class MyGraphQLContext(val customValue: String) : GraphQLContext
2728

29+
class ContextualQuery {
2830
fun contextualQuery(
29-
value: Int,
30-
@GraphQLContext context: MyGraphQLContext
31-
): ContextualResponse = ContextualResponse(value, context.myCustomValue)
31+
context: MyGraphQLContext,
32+
value: Int
33+
): String = "The custom value was ${context.customValue} and the value was $value"
3234
}
3335
```
3436

@@ -40,10 +42,27 @@ schema {
4042
}
4143

4244
type Query {
43-
contextualQuery(
44-
value: Int!
45-
): ContextualResponse!
45+
contextualQuery(value: Int!): String!
4646
}
4747
```
4848

49-
Note that the `@GraphQLContext` annotated argument is not reflected in the GraphQL schema.
49+
Note that the argument that implements `GraphQLContext` is not reflected in the GraphQL schema.
50+
51+
52+
### GraphQLContext Annotation
53+
54+
From the 1.x.x release we also support marking any argument with the annotaiton `@GraphQLContext`.
55+
If the schema generator sees this annotation on an argument it will assume that this is the class used in the `GraphQLContextFactory` and return the context as this argument value.
56+
This does require though that you mark every usage of the arument with the annotation. This can be helpful if you do no control the implementation of the context
57+
class you are using.
58+
59+
```kotlin
60+
class MyGraphQLContext(val customValue: String)
61+
62+
class ContextualQuery {
63+
fun contextualQuery(
64+
@GraphQLContext context: MyGraphQLContext,
65+
value: Int
66+
): String = "The custom value was ${context.customValue} and the value was $value"
67+
}
68+
```

docs/spring-server/spring-graphql-context.md

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ id: spring-graphql-context
33
title: Generating GraphQL Context
44
---
55

6-
`graphql-kotlin-spring-server` provides a simple mechanism to build [GraphQL context](../execution/contextual-data) per query execution through
6+
`graphql-kotlin-spring-server` provides a simple mechanism to build a [GraphQL context](../execution/contextual-data) per query execution through
77
[GraphQLContextFactory](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/graphql-kotlin-spring-server/src/main/kotlin/com/expediagroup/graphql/spring/execution/GraphQLContextFactory.kt).
8-
Once context factory bean is available in the Spring application context it will then be used in a corresponding
8+
Once a context factory bean is available, it will then be used in
99
[ContextWebFilter](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/graphql-kotlin-spring-server/src/main/kotlin/com/expediagroup/graphql/spring/execution/ContextWebFilter.kt)
10-
to populate GraphQL context based on the incoming request and make it available during query execution.
10+
to populate the GraphQL context based on the incoming request and make it available during query execution.
1111

1212
For example if we define our custom context as follows:
1313

@@ -21,39 +21,15 @@ We can generate corresponding `GraphQLContextFactory` bean:
2121
@Component
2222
class MyGraphQLContextFactory: GraphQLContextFactory<MyGraphQLContext> {
2323
override suspend fun generateContext(
24-
request: ServerHttpRequest,
24+
request: ServerHttpRequest,
2525
response: ServerHttpResponse
2626
): MyGraphQLContext = MyGraphQLContext(
2727
myCustomValue = request.headers.getFirst("MyHeader") ?: "defaultContext"
2828
)
2929
}
3030
```
3131

32-
Once your application is configured to build your custom `MyGraphQLContext`, we can then specify it as function argument by annotating it with `@GraphQLContext`.
32+
Once your application is configured to build your custom `MyGraphQLContext`, we can then specify it as function argument but it will not be included in the schema.
3333
While executing the query, the corresponding GraphQL context will be read from the environment and automatically injected to the function input arguments.
3434

35-
```kotlin
36-
@Component
37-
class ContextualQuery: Query {
38-
fun contextualQuery(
39-
value: Int,
40-
@GraphQLContext context: MyGraphQLContext
41-
): ContextualResponse = ContextualResponse(value, context.myCustomValue)
42-
}
43-
```
44-
45-
The above query would produce the following GraphQL schema:
46-
47-
```graphql
48-
schema {
49-
query: Query
50-
}
51-
52-
type Query {
53-
contextualQuery(
54-
value: Int!
55-
): ContextualResponse!
56-
}
57-
```
58-
59-
Notice that the `@GraphQLContext` annotated argument is not reflected in the generated GraphQL schema.
35+
For more details see the [Contextual Data page](../execution/contextual-data).

docs/writing-schemas/arguments.md

Lines changed: 123 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,123 @@
1-
---
2-
id: arguments
3-
title: Arguments
4-
---
5-
6-
Method arguments are automatically exposed as part of the arguments to the corresponding GraphQL fields.
7-
8-
```kotlin
9-
class SimpleQuery{
10-
11-
@GraphQLDescription("performs some operation")
12-
fun doSomething(@GraphQLDescription("super important value") value: Int): Boolean = true
13-
}
14-
```
15-
16-
The above Kotlin code will generate following GraphQL schema:
17-
18-
```graphql
19-
type Query {
20-
"""performs some operation"""
21-
doSomething(
22-
"""super important value"""
23-
value: Int!
24-
): Boolean!
25-
}
26-
```
27-
28-
This behavior is true for all arguments except for the GraphQL context objects. See section below for detailed
29-
information about `@GraphQLContext`.
30-
31-
### Input Types
32-
33-
Query and mutation function arguments are automatically converted to corresponding GraphQL input fields. GraphQL makes a
34-
distinction between input and output types and requires unique names for all the types. Since we can use the same
35-
objects for input and output in our Kotlin functions, `graphql-kotlin-schema-generator` will automatically append
36-
`Input` suffix to the query input objects.
37-
38-
```kotlin
39-
class WidgetMutation {
40-
41-
@GraphQLDescription("modifies passed in widget so it doesn't have null value")
42-
fun processWidget(@GraphQLDescription("widget to be modified") widget: Widget): Widget {
43-
if (null == widget.value) {
44-
widget.value = 42
45-
}
46-
return widget
47-
}
48-
}
49-
50-
@GraphQLDescription("A useful widget")
51-
data class Widget(
52-
@GraphQLDescription("The widget's value that can be null")
53-
var value: Int? = nul
54-
) {
55-
@GraphQLDescription("returns original value multiplied by target OR null if original value was null")
56-
fun multiplyValueBy(multiplier: Int) = value?.times(multiplier)
57-
}
58-
```
59-
60-
Will generate
61-
62-
```graphql
63-
type Mutation {
64-
"""modifies passed in widget so it doesn't have null value"""
65-
processWidget(
66-
"""widget to be modified"""
67-
widget: WidgetInput!
68-
): Widget!
69-
}
70-
71-
"""A useful widget"""
72-
type Widget {
73-
74-
"""The widget's value that can be null"""
75-
value: Int
76-
77-
"""
78-
returns original value multiplied by target OR null if original value was null
79-
"""
80-
multiplyValueBy(multiplier: Int!): Int
81-
}
82-
83-
"""A useful widget"""
84-
input WidgetInput {
85-
86-
"""The widget's value that can be null"""
87-
value: Int
88-
}
89-
90-
```
91-
92-
Please note that only fields are exposed in the input objects. Functions will only be available on the GraphQL output
93-
types.
94-
95-
If you know a type will only be used for input types you can call your class `CustomTypeInput`. The library will not
96-
append `Input` if the class name already ends with `Input` but that means you can not use this type as output because
97-
the schema would have two types with the same name and will be invalid.
98-
99-
### Optional input fields
100-
101-
Kotlin requires variables/values to be initialized upon their declaration either from the user input OR by providing
102-
defaults (even if they are marked as nullable). Therefore in order for GraphQL input field to be optional it needs to be
103-
nullable and also specify default Kotlin value.
104-
105-
```kotlin
106-
@GraphQLDescription("query with optional input")
107-
fun doSomethingWithOptionalInput(
108-
@GraphQLDescription("this field is required") requiredValue: Int,
109-
@GraphQLDescription("this field is optional") optionalValue: Int?)
110-
= "required value=$requiredValue, optional value=$optionalValue"
111-
```
112-
113-
NOTE: Non nullable input fields will always require users to specify the value regardless whether default Kotlin value
114-
is provided or not.
115-
116-
NOTE: Even though you could specify a default value in Kotlin `optionalValue: Int? = null`, this will not be used since
117-
if no value is provided to the schema `graphql-java` passes null as the value so the Kotlin default value will never be
118-
used, like in this argument `optionalList: List<Int>? = emptyList()`, the value will be null if not passed a value by
119-
the client.
120-
121-
### Default values
122-
123-
Default argument values are currently not supported. See issue
124-
[#53](https://github.com/ExpediaGroup/graphql-kotlin/issues/53) for more details.
1+
---
2+
id: arguments
3+
title: Arguments
4+
---
5+
6+
Method arguments are automatically exposed as part of the arguments to the corresponding GraphQL fields.
7+
8+
```kotlin
9+
class SimpleQuery{
10+
11+
@GraphQLDescription("performs some operation")
12+
fun doSomething(@GraphQLDescription("super important value") value: Int): Boolean = true
13+
}
14+
```
15+
16+
The above Kotlin code will generate following GraphQL schema:
17+
18+
```graphql
19+
type Query {
20+
"""performs some operation"""
21+
doSomething(
22+
"""super important value"""
23+
value: Int!
24+
): Boolean!
25+
}
26+
```
27+
28+
This behavior is true for all arguments except for the special classes for the [GraphQLContext](../execution/contextual-data) and the [DataFetchingEnvironment](../execution/data-fetching-environment)
29+
30+
### Input Types
31+
32+
Query and mutation function arguments are automatically converted to corresponding GraphQL input fields. GraphQL makes a
33+
distinction between input and output types and requires unique names for all the types. Since we can use the same
34+
objects for input and output in our Kotlin functions, `graphql-kotlin-schema-generator` will automatically append
35+
`Input` suffix to the query input objects.
36+
37+
```kotlin
38+
class WidgetMutation {
39+
40+
@GraphQLDescription("modifies passed in widget so it doesn't have null value")
41+
fun processWidget(@GraphQLDescription("widget to be modified") widget: Widget): Widget {
42+
if (null == widget.value) {
43+
widget.value = 42
44+
}
45+
return widget
46+
}
47+
}
48+
49+
@GraphQLDescription("A useful widget")
50+
data class Widget(
51+
@GraphQLDescription("The widget's value that can be null")
52+
var value: Int? = nul
53+
) {
54+
@GraphQLDescription("returns original value multiplied by target OR null if original value was null")
55+
fun multiplyValueBy(multiplier: Int) = value?.times(multiplier)
56+
}
57+
```
58+
59+
Will generate
60+
61+
```graphql
62+
type Mutation {
63+
"""modifies passed in widget so it doesn't have null value"""
64+
processWidget(
65+
"""widget to be modified"""
66+
widget: WidgetInput!
67+
): Widget!
68+
}
69+
70+
"""A useful widget"""
71+
type Widget {
72+
73+
"""The widget's value that can be null"""
74+
value: Int
75+
76+
"""
77+
returns original value multiplied by target OR null if original value was null
78+
"""
79+
multiplyValueBy(multiplier: Int!): Int
80+
}
81+
82+
"""A useful widget"""
83+
input WidgetInput {
84+
85+
"""The widget's value that can be null"""
86+
value: Int
87+
}
88+
89+
```
90+
91+
Please note that only fields are exposed in the input objects. Functions will only be available on the GraphQL output
92+
types.
93+
94+
If you know a type will only be used for input types you can call your class `CustomTypeInput`. The library will not
95+
append `Input` if the class name already ends with `Input` but that means you can not use this type as output because
96+
the schema would have two types with the same name and will be invalid.
97+
98+
### Optional input fields
99+
100+
Kotlin requires variables/values to be initialized upon their declaration either from the user input OR by providing
101+
defaults (even if they are marked as nullable). Therefore in order for GraphQL input field to be optional it needs to be
102+
nullable and also specify default Kotlin value.
103+
104+
```kotlin
105+
@GraphQLDescription("query with optional input")
106+
fun doSomethingWithOptionalInput(
107+
@GraphQLDescription("this field is required") requiredValue: Int,
108+
@GraphQLDescription("this field is optional") optionalValue: Int?)
109+
= "required value=$requiredValue, optional value=$optionalValue"
110+
```
111+
112+
NOTE: Non nullable input fields will always require users to specify the value regardless whether default Kotlin value
113+
is provided or not.
114+
115+
NOTE: Even though you could specify a default value in Kotlin `optionalValue: Int? = null`, this will not be used since
116+
if no value is provided to the schema `graphql-java` passes null as the value so the Kotlin default value will never be
117+
used, like in this argument `optionalList: List<Int>? = emptyList()`, the value will be null if not passed a value by
118+
the client.
119+
120+
### Default values
121+
122+
Default argument values are currently not supported. See issue
123+
[#53](https://github.com/ExpediaGroup/graphql-kotlin/issues/53) for more details.

0 commit comments

Comments
 (0)