2

I am reviewing the codebase of a solace application. Here a FlowReceiver is configured with a ConsumerFlowProperties to replay from the start of a queue. Then the FlowReceiver is started and stopped, and the session is closed without reading any messages at all. Then at the very end, it starts the ListenerContainer associated with the Events', which is being used by a method annotated with @JmsListener. But why does the ConsumerFlowProperties carry over? Why is it replaying from the very start all the messages that exist in the solace queue? Shouldnt the properties be associated with the previous session/consumer?

    public void replayThenStart() {
        final var jcsmpFactory = JCSMPFactory.onlyInstance();
        JCSMPSession session = null;
        try {
            session = jcsmpFactory.createSession(jcsmpProperties);
            session.connect();

            final var queue = jcsmpFactory.createQueue("q/uat/event");
            final var consumerFlowProperties = new ConsumerFlowProperties();
            consumerFlowProperties.setEndpoint(queue);
            consumerFlowProperties.setReplayStartLocation(jcsmpFactory.createReplayStartLocationBeginning());
            consumerFlowProperties.setActiveFlowIndication(false);

            FlowReceiver consumer = null;
            try {
                consumer = session.createFlow(this, consumerFlowProperties);
                consumer.start();
                log.info("Replay flow (" + consumer + ") created.");
            } catch (Throwable t) {
                log.error("Failed replay flow.", t);
            } finally {
                if (consumer != null) {
                    log.info("Close replay flow.");
                    consumer.close();
                }
            }
        } catch (Throwable t) {
            log.error("Failed replay session.", t);
        } finally {
            if (session != null) {
                session.closeSession();
            }
        }

        Objects.requireNonNull(jmsListenerEndpointRegistry.getListenerContainer("eventListener")).start();
    }

    @JmsListener(id = "eventListener", destination = "q/uat/event", containerFactory = "eventContainerFactory")
    public void onEvents(final List<Event> events, @Header("authentication") final String header) {
        try {
            onEvents(events, jwtUtil.getAuthentication(header));
        } catch (Throwable e) {
            log.error("Failed authenticating header [{}].", header, e);
            log.debug("Unable to retrieve events - [{}]", events);
        }
    }

    public void onEvents (final List<Event> events, final Authentication authentication) {
        //process events
    }
chunkynuggy
  • 147
  • 8

1 Answers1

4

It looks to me like they want to use JMS to consume the events, but they also want to use Solace's replay capability. And since that isn't a JMS feature they are using Solace's JCSMP API to trigger replay.

So they are setting up the JMS consumer to listen on the queue, which is a durable endpoint on the broker. And then using JCSMP to say "replay events to that queue". The queue itself is where the messages get replayed and resides on the broker, and the ConsumerFlow is just how your apps bind to that queue. There are some diagrams in the Solace docs here that should help describe this: https://docs.solace.com/API/Component-Maps.htm#SMF

Mrc0113
  • 453
  • 3
  • 13
  • 1
    Another suggestion here would be to not even call `consumer.start()` if you don't want messages to be received in the JCSMP code. The replay request should already be triggered by `createFlow`. – Mrc0113 Jul 12 '23 at 17:08