1

I'm using spring boot v3.0.2 with websockets and faced problem with graphQL subscriptions. The task is pretty simple - notify client when backend entity changes. So, I have EntityChangeNotifier -

@Service
public class EntityChangeNotifier {

    private final Collection<Listener<MyEntity>> listeners = new ArrayList<>();

    @Override
    public void notifyChange(MyEntity entity) {
        listeners.forEach(listener -> listener.onEntityChange(entity));
    }

    @Override
    public void registerListener(Listener<T> listener) {
        listeners.add(listener);
    }

    interface Listener<T> {
        void onEntityChange(T entity);
    }

}

Service class -

@Service
public class Service {

    private final MyRepository repository;

    private final EntityChangeNotifier entityChangeNotifier;

    @Autowired
    public Service(MyRepository repository, EntityChangeNotifier entityChangeNotifier) {
        this.repository = repository;
        this.entityChangeNotifier = entityChangeNotifier;
    }

    @Transactional
    public long saveEntity(MyEntity entity) {
        MyEntity saved = repository.save(entity);
        entityChangeNotifier.notifyChange(entity);
        return saved.getId();
    }

and GraphQL mappings -

@Controller
public class Mappings {

    private final EntityChangeNotifier entityChangeNotifier;
    private final Service service;

    @Autowired
    public Mappings(Service service, EntityChangeNotifier entityChangeNotifier) {
        this.service = service;
        this.entityChangeNotifier = entityChangeNotifier;
    }

    @SubscriptionMapping
    public Publisher<MyEntity> changed() {
        return Flux.create(fluxSink -> entityChangeNotifier.registerListener(fluxSink::next));
    }

    @MutationMapping
    public Long create() {
        return service.saveEntity(new MyEntity(0, "testName"));
    }
}

GraphQL schema -

type Mutation {
    create: Int!
}

type Subscription {
    changed: MyEntity
}

type MyEntity {
    id
    name
}

The code is very basic, but the problem is it doesn't work. I test it via graphiQL and after saving entity, subscription just ends without any result. As far as I discover, sink is marked as cancelled for some reason. Could you please hint me what is wrong? Btw - when I use cold publisher all works fine. But such code, obviously, doesn't comfort me -

    @SubscriptionMapping
    public Publisher<MyEntity> test() {
        Random random = new Random();
        return Flux.interval(Duration.ofSeconds(5))
                .map(i -> new MyEntity(0, "name" + random.nextInt()));
    }

Cosdix
  • 107
  • 1
  • 10

1 Answers1

0

Solved. The problem was in... special test conditions and graphiQL subscriptions handling. It just cancel subscription when you switch tab - so all is fine

Cosdix
  • 107
  • 1
  • 10
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 17 '23 at 18:36