Apollo-server: Schema Stitching two remote Graphql/Prisma servers in gateway not working

Created on 19 Jul 2018  路  12Comments  路  Source: apollographql/apollo-server

I'm attempting to create a microservice based application that uses two remote Prisma/GraphQL schemas that run in Docker and a gateway that introspects them using schema stitching.

Prisma/GraphQL Schemas:

// Profile Schema service - http:localhost:3000/profile
type Profile {
  id: ID!
  user_id: ID!
  firstName: String!
  ...
}

type Query {
  findProfileById(id: ID!): Profile
  findProfileByUserID(user_id: ID!): Profile
}

// User Schema service - http:localhost:5000/user
type User {
  id: ID!
  profileID: ID!
  email: String!
  ...
}

type Query {
  findUserById(id: ID!): User
  findUserByProfileID(profileID: ID!): Profile
}

Now in the Gateway server I am able to introspect and mergeSchemas using graphql-tools successfully and I have added extended types to allow for relationships between the two types

// LinkTypeDefs
extend type Profile {
    user: User
}

extend type User {
   userProfile: Profile
}

I followed Apollo GraphQL documentation for schema stitching with remote schemas and this is the resolver I have for the now merged schemas

        app.use('/gateway', bodyParser.json(), graphqlExpress({ schema: mergeSchemas({ 
        schemas: [
            profileSchema,
            userSchema,
            linkTypeDefs
        ], 
        resolvers: mergeInfo =>  ({
            User: {
                userProfile: {
                    fragment: `fragment UserFragment on User { id }`,
                    resolve(user, args, context, info) {
                        return delegateToSchema({
                            schema: profileSchema,
                            operation: 'query',
                            fieldName: 'findProfileByUserId',
                            args: {
                                user_id: user.id
                            },
                            context,
                            info
                        },

                        );
                    },
                },
            },
            Profile: {
                user: {
                    fragment: `fragment ProfileFragment on Profile { id }`,
                    resolve(profile, args, context, info) {
                        return delegateToSchema({
                            schema: userSchema,
                            operation: 'query',
                            fieldName: 'findUserByProfileId',
                            args: {
                                profileID: profile.id
                            },
                            context,
                            info

                        })
                    }
                }
            }
        }),
    })
}));

The issue I am having is every time I query User or Profile for their new extended fields it always returns null. I have made sure that I have created User object with an existing profileId, likewise with Profile object with an existing userId. This is a sample of the query results

image

I have gone through the docs for about a week now and nothing seems to be working. From my understanding everything is plugged in properly. Hopefully someone can help. I have a feeling it has something to do with the fragments. I can provide a screenshot of the user and profile objects for more clarification if need be. First time raising an issue on github so be nice :) Thanks.

All 12 comments

I was faced with a similar issue just recently. In my case turns out I mistakenly did not attach the resolvers to the schema (both typeDefs and resolvers are needed to make it executable). Maybe you might want to make sure that the 'authSchema' resolver is attached and firing. Also note that you should delegate with info.mergeInfo.delegateToSchema. Hope this helps.

@darrenbutcher I ended up resolving the issue by changing delegateToSchema() to info.mergeInfo.delegate(). That seemed to do the trick.

image

I have not tried the newly updated info.mergeInfo.delegateToSchema yet but it is working as of now so I'm happy with that :)

Thanks for the help!

I think this issue should be reopened. I can't found info.mergeInfo. This is undefined.
info paramater isn't had mergeInfo and mergeInfo.delegateToSchema. This issue is no matched apollographql's official document.

I was resolved this issue using graphql-tools.delegateToSchema().

@yoonhoGo I am having the same trouble that you had where info.mergeInfo is undefined. Can you explain a little more what did to resolve this? Thanks!

@jasonmerino have you installed graphql-tools?

@jasonmerino graphql-tools has delegateToSchema function. This library is working well. If you need the document about it, refer to this page.

```javascript
import { delegateToSchema } from 'graphql-tools'

// in resolver
export const resolver = {
books(root) {
return delegateToSchema({ /* options */ })
}
}

What you are probably looking for is import { mergeSchemas } from 'graphql-tools'

For example, this is what works for me:

import { mergeSchemas } from 'graphql-tools
...
const mergedSchema = mergeSchemas({
     schemas: [
          schema1,
          schema2,
      ],
      resolvers: ({
           User: {
               getUser: {
                    fragment: `fragment MyFrag on User { id }`,
                    resolve: (parent, args, context, info) => {
                          return info.mergeInfo.delegateToSchema({
                                  // resolver code here
                           )}
                      }
                 }
             }
       )}
)}

I also suggest looking at their docs and upgrading to Apollo Server 2.0. I found I ran into less isues after migrating.

Hopefully this helps someone! :)

@general-wedge , did you change anything in your "resolver code here" area when you switched to "info.mergeInfo.delegateToSchema" from "delegateToSchema"?
I'm having the same issue you were initially having. I'm using Apollo Server 2.0. I'm currently using info.mergeInfo.delegate and that is working, but it is marked as deprecated and I'd like to switch, but I'm getting nulls in the results when I change to info.mergeInfo.delegateToSchema.

works:

resolvers.Enrollment = {
        userProfile: {
          fragment: 'fragment EnrollmentFragment on Enrollment { user_id }',
          resolve(parent, args, context, info) {
            return info.mergeInfo.delegate(
              'query',
              'user',
              {
                id: parent.user_id,
              },
              context,
              info,
            );
          },
        },
      };

Returns null results for userProfile:

resolvers.Enrollment = {
        userProfile: {
          fragment: 'fragment EnrollmentFragment on Enrollment { user_id }',
          resolve(parent, args, context, info) {
            return info.mergeInfo.delegateToSchema({
              schema: userSchema,
              operation: 'query',
              fieldName: 'user',
              args: {
                id: parent.user_id,
              },
              context,
              info,
            });
          },
        },
      },
    };

@duinness have you found a solution? We are having the same problem

@kilianc use delegateToSchema from graphql-tools and it should work fine.

example

Its been awhile and I can't remember what changed. The only code difference from what I have now and what I posted above is that I changed the way I was getting the value for 'schema' so I'm thinking what I had before in 'userSchema' wasn't correct.

delegateToSchema is working for me now

Was this page helpful?
0 / 5 - 0 ratings