Skip to content

Commit

Permalink
Replace argument type with @Source to determine source/parent
Browse files Browse the repository at this point in the history
  • Loading branch information
dugenkui03 committed Mar 9, 2022
1 parent afb0b64 commit 5deba19
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 22 deletions.
12 changes: 6 additions & 6 deletions spring-graphql-docs/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ parent type name, and the field name:
public class BookController {
@SchemaMapping(typeName="Book", field="author")
public Author getAuthor(Book book) {
public Author getAuthor(@Source Book book) {
// ...
}
}
Expand All @@ -1026,7 +1026,7 @@ defaults to type "Book" and field "author":
public class BookController {
@SchemaMapping
public Author author(Book book) {
public Author author(@Source Book book) {
// ...
}
}
Expand Down Expand Up @@ -1098,7 +1098,7 @@ See <<controllers-schema-mapping-arguments>>.
| For access to field arguments through a project interface.
See <<controllers-schema-mapping-projectedpayload-argument>>.

| Source
| @Source
| For access to the source (i.e. parent/container) instance of the field.
See <<controllers-schema-mapping-source>>.

Expand Down Expand Up @@ -1287,19 +1287,19 @@ For example:


[[controllers-schema-mapping-source]]
==== Source
==== @Source

In GraphQL Java, the `DataFetchingEnvironment` provides access to the source (i.e.
parent/container) instance of the field. To access this, simply declare a method parameter
of the expected target type.
annotated with `@Source`.

[source,java,indent=0,subs="verbatim,quotes"]
----
@Controller
public class BookController {
@SchemaMapping
public Author author(Book book) {
public Author author(@Source Book book) {
// ...
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.graphql.data.method.annotation;

import graphql.schema.DataFetchingEnvironment;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotation to bind a method parameter to the
* {@link DataFetchingEnvironment#getSource() source/parent} instance of the field.
*
* @author Genkui Du
* @since 1.0.0
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Source {

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,32 +15,26 @@
*/
package org.springframework.graphql.data.method.annotation.support;

import java.util.Collection;

import graphql.schema.DataFetchingEnvironment;

import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.Source;
import org.springframework.util.Assert;

/**
* Resolver for the source/parent of a field, obtained via
* {@link DataFetchingEnvironment#getSource()}.
*
* <p>This resolver supports any non-simple value type, also excluding arrays
* and collections, and therefore must be ordered last, in a fallback mode,
* allowing other resolvers to resolve the argument first.
*
* @author Rossen Stoyanchev
* @author Genkui Du
* @since 1.0.0
*/
public class SourceMethodArgumentResolver implements HandlerMethodArgumentResolver {

@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> type = parameter.getParameterType();
return (!BeanUtils.isSimpleValueType(type) && !type.isArray() && !Collection.class.isAssignableFrom(type));
return parameter.getParameterAnnotation(Source.class) != null;
}

@Override
Expand All @@ -49,7 +43,7 @@ public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment
Assert.isInstanceOf(parameter.getParameterType(), source,
"The declared parameter of type '" + parameter.getParameterType() + "' " +
"does not match the type of the source Object '" + source.getClass() + "'.");
return source;
return environment.getSource();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.idl.RuntimeWiring;
import org.junit.jupiter.api.Test;
import org.springframework.graphql.data.method.annotation.Source;
import reactor.core.publisher.Flux;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Expand Down Expand Up @@ -118,7 +119,7 @@ public Book bookById(@Argument String id) {
}

@MutationMapping
public void saveBook(Book book) {
public void saveBook(@Source Book book) {
}

@SubscriptionMapping
Expand All @@ -127,7 +128,7 @@ public Flux<Book> bookSearch(@Argument String author) {
}

@SchemaMapping
public Author author(DataFetchingEnvironment environment, Book book) {
public Author author(DataFetchingEnvironment environment, @Source Book book) {
return null;
}

Expand All @@ -139,7 +140,7 @@ public Book bookByIdWithNonMatchingMethodName(@Argument String id) {
}

@MutationMapping("saveBookCustomized")
public void saveBookWithNonMatchingMethodName(Book book) {
public void saveBookWithNonMatchingMethodName(@Source Book book) {
}

@SubscriptionMapping("bookSearchCustomized")
Expand All @@ -148,7 +149,7 @@ public Flux<Book> bookSearchWithNonMatchingMethodName(@Argument String author) {
}

@SchemaMapping("authorCustomized")
public Author authorWithNonMatchingMethodName(Book book) {
public Author authorWithNonMatchingMethodName(@Source Book book) {
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import graphql.schema.DataFetchingEnvironment;
import org.dataloader.DataLoader;
import org.junit.jupiter.api.Test;
import org.springframework.graphql.data.method.annotation.Source;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
Expand Down Expand Up @@ -251,7 +252,7 @@ public List<Book> booksByProjectedCriteria(@Argument BookProjection criteria) {
}

@SchemaMapping
public CompletableFuture<Author> author(Book book, DataLoader<Long, Author> dataLoader) {
public CompletableFuture<Author> author(@Source Book book, DataLoader<Long, Author> dataLoader) {
return dataLoader.load(book.getAuthorId());
}

Expand Down

0 comments on commit 5deba19

Please sign in to comment.