I am using graphql-spqr So that I don't have to create schema.graphql
files.
I have a base class in which most of my other classes inherit from. For example
@GraphQLInterface(name = "BaseResponse", implementationAutoDiscovery = true)
@ToString
@Data
public class BaseResponse {
@JsonInclude(Include.NON_NULL)
protected String responseCode;
@JsonInclude(Include.NON_NULL)
protected String responseDescription;
protected String hash;
}
Other classes inherit from the above base class as below
@ToString(callSuper = true)
@Data
@AllArgsConstructor
public class GetAllGroupResponse extends BaseResponse {
private List<Group> groups;
}
When I set the parent values of GetAllGroupResponse
like below
getAllGroupResponse.setResponseCode(ResponseCodeEnum.SH_97.getRespCode());
getAllGroupResponse.setResponseDescription(ResponseCodeEnum.SH_97.getRespDescription());
I wish to retrieve the value of responseCode from my graphql query request
{
getAllPagable(pageNumber : 1, numberOfRecords : 3) { responseCode groups { groupName } }
}
but it throws an error below which tells me it can't see the responseCode variable because it is not a direct property of the class GetAllGroupResponse
Validation error of type FieldUndefined: Field 'responseCode' in type 'GetAllGroupResponse' is undefined @ 'getAllPagable/responseCode'
PS. BaseResponse
is from a different package/library project that was imported into the current project
UPDATE
Based on the GitHub issues raised and solutions provided. I created a bean as below
@Bean
public ExtensionProvider<GeneratorConfiguration, ResolverBuilder> resolverBuilderExtensionProvider() {
String[] packages = {"com.sheeft.microservices.library", "com.sheeft.mircoservice.groups"};
return (config, current) -> {
List<ResolverBuilder> resolverBuilders = new ArrayList<>();
//add a custom subtype of PublicResolverBuilder that only exposes a method if it's called "greeting"
resolverBuilders.add(new PublicResolverBuilder() {
@Override
public PublicResolverBuilder withBasePackages(String... basePackages) {
return super.withBasePackages(packages); //To change body of generated methods, choose Tools | Templates.
}
});
//add the default builder
resolverBuilders.add(new AnnotatedResolverBuilder().withBasePackages(packages));
return resolverBuilders;
};
}
and now I get an error which says the following
object type 'GetAllGroupResponse' does not implement interface 'BaseResponse' because field 'responseCode' is missing
So I decided to add the getResponseCode
getter method manually and it runs successfully. When I the call the /graphql
endpoint it throws an exception
Object required to be not null", "trace": "graphql.AssertException: Object required to be not null
I think all you need is to set the base packages for your project. E.g.
generator.withBasePackages("your.root.package", "library.root.package")
Or, if you're using SPQR Spring Starter, add
graphql.spqr.base-packages=your.root.package,library.root.package
to your application.properties
file, for the same effect.
This is needed when you have a hierarchy of classes across multiple packages (or even libraries, like in your case) to let SPQR know which packages should be exposed, because otherwise it might accidentally expose some framework code or even core Java things like getClass.