0

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();
}

1 Answer 1

0

I found the problem with my code. I was not setting 'variables' passed by apollo federation in graphql request in ExecutionInput in below code:

 public ExecutionResult executeQuery (GraphQLBody graphQLBody) {

    ExecutionInput.Builder builder = ExecutionInput.newExecutionInput().query(graphQLBody.getQuery());

    //Below code was missing
    if(graphQLBody.getVariables() != null) {
        builder.variables((Map<String, Object>) graphQLBody.getVariables());
    }
    ExecutionInput executionInput = builder.build();

    ExecutionResult executionResult = graphQL.execute(executionInput);

    return executionResult;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.