Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jms queue purge #1230

Open
bbortt opened this issue Oct 9, 2024 · 5 comments
Open

jms queue purge #1230

bbortt opened this issue Oct 9, 2024 · 5 comments
Labels
Prio: High State: To discuss In case there are open questions concerning the issue Type: Bug

Comments

@bbortt
Copy link
Collaborator

bbortt commented Oct 9, 2024

reported in https://citrusframework.zulipchat.com/#narrow/stream/259943-citrus/topic/Problems.20with.20purgeQueues.20action.

The purgeQueues-action does not work for me as expected; the queue does not seem to get purged.

For the setup: my system under tests receives a text/plain body via http/post and sends this body to an artemis topic.

For the test, I simply send some string to the system under test and then receive the corresponding JMS message. The JMS-setup on the citrus-side looks like this:

@Configuration
public class Jms {
  public static final String ENDPOINT = "JMS_ENDPOINT";
  public static final String CONNECTION_FACTORY = "CONNECTION_FACTORY";

  @Bean
  @Qualifier(CONNECTION_FACTORY)
  public ConnectionFactory purgeConnectionFactory(
      @Value("${test-config.artemis.url}") String url,
      @Value("${test-config.artemis.username}") String username,
      @Value("${test-config.artemis.password}") String password) {
    return new ActiveMQJMSConnectionFactory(url, username, password);
  }

  @Bean
  @Qualifier(ENDPOINT)
  public JmsEndpoint jmsEndpoint(
      @Qualifier(CONNECTION_FACTORY) ConnectionFactory connectionFactory,
      @Value("${test-config.artemis.receive.fqqn}") String fqqn) { // fqqn in this case is `messages::citrus`
    return new JmsEndpointBuilder()
        .connectionFactory(connectionFactory)
        .pubSubDomain(true)
        .destination(fqqn)
        .autoStart(true)
        .build();
  }
}

This works fine and as expected.

Now what I want to do is to clear the queue identified by the fqqn, so I implemented the following:

@Configuration
public class BeforeTestSequence {
  @Bean
  public SequenceBeforeTest beforeTest(
      @Qualifier(Jms.CONNECTION_FACTORY) ConnectionFactory connectionFactory,
      @Value("${test-config.artemis.receive.fqqn}") String fqqn) {
    return SequenceBeforeTest.Builder.beforeTest()
        .actions(
            purgeQueues()
                .connectionFactory(connectionFactory)
                .queue(fqqn))
        .build();
  }
}

This does not work as expected. In a "normal run", the test is green. However, if the queue messages::citrus already exists (from a previous run for example) and I write some message to that queue and THEN trigger the tests, the validation fails. The test "sees" the message i send beforehand, so the cleanup that should be happening does not happfen. In fact, I debugged into PurgeJmsQueuesAction::purgeDestination and the message received was always null.

If you need a full reproducer: https://github.com/turing85/citrus-playground/tree/feature/before-test-sequence

To reproduce:

start artemis (docker-compose --file local-deployment/docker-compose.yml up --detach)
start service (./mvnw --projects service quarkus:dev)
run the citrus tests however you like
To send an interfering message to the queue, execute the following curl after the tests have run at least once (i.e. after the queue for citrus was created)`:

curl -v -X POST localhost:8080/send --data "ouch" --header "Content-Type: text/plain"

If you want to access the artemis broker, go to localhost:8161/console, credentials are artemis/artemis.****

@bbortt
Copy link
Collaborator Author

bbortt commented Oct 9, 2024

cc: @turing85

@bbortt bbortt added State: To discuss In case there are open questions concerning the issue Type: Bug Prio: High labels Oct 9, 2024
@louisa-frison
Copy link

I tried to find out what is happening and I think it could be related to

  • the topic consumer configured with .autoStart(true)
    and
  • the purge-queue-action
    interfering.

A scenario could be:
1.
The topic consumer starts up at the beginning of the test and immediately reads the message
(in the documentation https://citrusframework.org/citrus/reference/4.5.0/html/index.html#jms-topic-subscriber
this sentence sounds like it: "Now with auto-start set to true the Citrus JMS endpoint will setup a subscription at the very beginning when the endpoint is loaded in the project." )

2.
After this, the purge-queue-action can't consume the message anymore.

3.
Once

runner.then(
      receive(jmsEndpoint)
          .message()
          .body("${message}"));

in the test is executed, it finds the message read by the topic consumer in the beginning
(which should have been deleted by the purge-queue-action, but was not... ).

I don't know how to avoid that interference itself,
but I found a purgeEndpoints()-action in the docs and that worked for me.
I extended the reproducer here:
https://github.com/louisa-frison/citrus-playground/tree/try-fix/purge-endpoint

@louisa-frison
Copy link

Hi @bbortt / @christophd ,
@turing85 tested the purge-endpoint way of fixing the issue and on his machine it worked, too.

The question arose, whether:
a) calling purgeQueues() and purgeEndpoints() both explicitly is not the desired way
and purgeQueues() should call purgeEndpoints() internally to make the purging more straightforward / compact
b) calling purgeQueues() and purgeEndpoints() both explicitly is the correct way to do it

Optionally, if b) is the case:
As someone who only knows citrus from a user perspective and is not so familiar with its inner workings,
it took me some time to find out about purgeEndpoints()
If that sounds reasonable, I could maybe improve the documentation a bit,
e.g. in the jms topic subscriber .autoStart() section, adding a hint to the purgeEndpoints()-section saying it might be necessary in some cases
or something like that.

@christophd
Copy link
Member

It is because you are using a JMS topic subscriber. The JMS topic broadcasts each message to all consumers subscribed. So purging the JMS topic will not affect other subscribers that have already received the message. In this specific case you need to also purge the endpoints meaning all Citrus topic subscribers, too.

This is the nature of publish-subscribe topics compared to JMS queues. With JMS queue the purge operation on the queue itself would be sufficient without the purge on the Citrus endpoint.

So option a) is not the right way, because many endpoints may consumer from one single queue/topic. Option b) is right only for JMS topics where you need to explicitly also purge the Citrus topic subscriber endpoints.

Hope that helps. Any updates/improvements to the documentation are highly appreciated. Many thanks!

@louisa-frison
Copy link

Thanks, that cleared things up !
Then I will think about whether there is something helpful I could add to the documentation or not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Prio: High State: To discuss In case there are open questions concerning the issue Type: Bug
Projects
None yet
Development

No branches or pull requests

3 participants