1

I'm following the documentation of DGS subscriptions and I'm not getting any errors but not getting back any data either.

The setup is very simple. In the schema.graphqls file I have defined the subscription:

type Subscription {
    ratings: Rating
}

type Rating {
    stars: Int
}

And the Java code is as follows:

@DgsComponent
public class SubscriptionDataFetcher {
    @DgsData(parentType = "Subscription", field = "ratings")
    public Publisher<Rating> ratings() {
        return Flux.interval(Duration.ofSeconds(1)).map(t -> new Rating(4));
    }
}

If I now connect a websocket to my backend it connects just fine but not getting back any data as expected (doesn't matter how I do it, also tried using JavaScript, also connects just fine but not getting any data).

For example using curl to connect (but using JavaScript the result is the same, connects but no data):

curl -o - --http1.1 \
    --include \
    --no-buffer \
    --header "Connection: Upgrade" \
    --header "Upgrade: websocket" \
    --header "Host: localhost:8443" \
    --header "Origin: https://localhost:8443" \
    --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
    --header "Sec-WebSocket-Version: 13" \
    https://localhost:8443/subscriptions\?query\=ewoicXVlcnkiOiAic3Vic2NyaXB0aW9uIHsgIHN0b2NrcyB7bmFtZX0gfSIKfQ==

I have tried connecting via the Graphiql interface as well but that gives an error:

subscription {
  ratings {
    stars
  }
}

Error message:

{
  "message": "response is not defined",
  "stack": "ReferenceError: response is not defined\n    at https://localhost:8443/graphiql:46:35\n    at async Object.onRun (https://unpkg.com/graphiql/graphiql.min.js:1:540500)"
}

Another thing that's not clear to me from the examples in the link is how to actually manage subscriptions. So for example let's say I want to publish a notification if a mutation takes place. Any pointers how that would be done using the Netflix DGS framework would also be much appreciated.

Jonck van der Kogel
  • 2,983
  • 3
  • 23
  • 30

1 Answers1

3

Unfortunately, the graphiql interface that comes with DGS does not seems to handle subscriptions properly - if you add playground-spring-boot-starter to your project, a more polished tool will be available at /playground, which fully supports subscriptions. If you try your subscription there it should work (assuming you have already added graphql-dgs-subscriptions-websockets-autoconfigure as per the docs).

Regarding your second question about how to publish a notification if a mutation takes place - this is unfortunately missing from the documentation, but there is an example in the examples repo.

I have stripped down the example a bit here. If you want to support a subscription & mutation like this:

@DgsSubscription
public Publisher<Review> reviewAdded() {
    return reviewsService.getReviewsPublisher();
}

@DgsMutation
public Review addReview(@InputArgument SubmittedReview review) {
    return reviewsService.saveReview(review);
}

Inside your service, you would create a Flux (to return to subscribers) and keep a reference to its emitter so you can call next on it whenever a mutation occurs.

@Service
public class ReviewsService {

    private FluxSink<Review> reviewsStream;
    private ConnectableFlux<Review> reviewsPublisher;

    @PostConstruct
    public void init() {
        Flux<Review> publisher = Flux.create(emitter -> {
            reviewsStream = emitter;
        });

        reviewsPublisher = publisher.publish();
        reviewsPublisher.connect();
    }

    public Review saveReview(SubmittedReview reviewInput) {
        Review review = Review.newBuilder()
                .username(reviewInput.getUsername())
                .starScore(reviewInput.getStarScore())
                .submittedDate(OffsetDateTime.now()).build();

        // Save to the database, etc.

        reviewsStream.next(review); // publishes the review to subscribers
        return review;
    }

    public Publisher<Review> getReviewsPublisher() {
        return reviewsPublisher;
    }
}
SimonW
  • 309
  • 3
  • 8
  • The example overall is great, thanks for that. However, it seems I'm running into the issue with graphiql not handling subscriptions properly, but when I try to using the playground you suggested nothing comes up, just "Loading Graphql Playground." Have you used this playground before? Any thoughts on why that might not be working? – Davenporten May 24 '21 at 13:02
  • Yeah, I've tried adding it to the dgs-examples-kotlin repo and that worked fine. Not sure tbh. If you have a public repo that I can run, I can take a look when I get a chance. – SimonW May 24 '21 at 13:28
  • Gotcha, ok, that's good to know. I don't have a public repo, but I'll keep looking. Thanks for the response! – Davenporten May 24 '21 at 13:29
  • 1
    Just as a follow up, I never got the playground working, but I was able to confirm that my subscriptions were working (using the guidance @SimonW provided) by running https://github.com/hasura/graphqurl. Obviously not as convenient as a GUI, but worked well for making sure my subscriptions were working. – Davenporten May 24 '21 at 18:42