I have couple of existing backend services exporting graphql data for 'accounts' & 'billing'. These services have implemented graphql using graphql-java-kickstart (without springboot). I want to use apollo federation router on top of these services.
Is it possible to use apollo-federation-jvm with graphql-java-kickstart? I see most of the examples showing schema federation are springboot based.
So far i have implemented following and i am able to get the apollo router running with federated schema, however, when i am executing a query then getting below error:
"message": "Variable 'representations' has an invalid value: Variable 'representations' has coerced Null value for NonNull type '[_Any!]!'",
This error is happening for following query while fetching billing for an account:
query($representations:[_Any!]!){_entities(representations:$representations){...on AccountsItem{billing{accountNumber billingDetails{lastBillAmount}}}}}
Here are schemas for accounts and billing:
Accounts:
type Query {
accounts: [AccountsItem!]!
searchAccounts(filter: AccountFilter!): [AccountsItem!]
}
input AccountFilter {
accountAlias: String
}
"AccountOverview for account list call"
type AccountsItem @key(fields: "alias"){
accountNumber: String
alias: String
status: String
cbpid: String
accountTypeNumber: String
autoPayPromoEligInd: String
}
Billing:
type Query {
billing(accountAlias: String!): Billing!
}
type AccountsItem @key(fields: "alias") @extends {
alias: String @external
billing: Billing
}
type Billing {
accountNumber: String
billingDetails: BillingDetails
}
type BillingDetails{
billType: String
currentBalance: String
lastBillAmount: String
}
Below code is for schema transformation:
private static DataFetcher<?> getDataFetcher(GraphQLResolver<?>[] resolvers) {
DataFetcher<?> entityDataFetcher = env -> {
List<Map<String, Object>> argument = env.getArgument(_Entity.argumentName);
return argument.stream()
.map(reference -> {
if ("AccountsItem".equals(reference.get("__typename"))) {
return new AccountsItem((String)reference.get("alias"));
} else if ("billing".equals(reference.get("__typename"))) {
return ((BillingResolver)resolvers[0]).billing((String)reference.get("alias"), env);
}
return null;
})
.collect(Collectors.toList());
};
return entityDataFetcher;
}
@Bean
public GraphQL graphQL(GraphQLResolver<?>[] resolvers) {
final String originalSDL = readResource("graphql/schema.graphqls");
DataFetcher<?> entityDataFetcher = getDataFetcher(resolvers);
GraphQLSchema federatedSchema = Federation.transform(originalSDL, getRuntimeWiring(entityDataFetcher))
.fetchEntities(entityDataFetcher)
.resolveEntityType(env -> {
final Object src = env.getObject();
if (src instanceof AccountsItem) {
return env.getSchema().getObjectType("AccountsItem");
}
return null;
}
)
.build();
return GraphQL.newGraphQL(federatedSchema).build();
}
private static RuntimeWiring getRuntimeWiring(DataFetcher<?> entityDataFetcher){
return RuntimeWiring.newRuntimeWiring()
.type("AccountsItem",typeWiring -> typeWiring
.dataFetcher("billing", entityDataFetcher))
.type("Query",typeWiring -> typeWiring
.dataFetcher("billing", entityDataFetcher))
.build();
}
I found the problem with my code. I was not setting 'variables' passed by apollo federation in graphql request in ExecutionInput in below code: