citrusframework / citrus

Framework for automated integration tests with focus on messaging integration
https://citrusframework.org
Apache License 2.0
456 stars 134 forks source link

"purge-endpoint" fails sometimes during "after-suite" because Session is closed #103

Open erikonthenet opened 8 years ago

erikonthenet commented 8 years ago

Environment: the service (jdk-8) runs locally with jetty. The citrus tests (2.5.2), run with maven-failsafe-plugin. DB: Postgresql, JMS: HornetQ.

In our service tests we enqueue messages onto the IN-queue, the service does magic and produces a message on the OUT-queue. Most tests use receive-actions to validate the message. But not all messages are received, or maybe a test-build fails. That's why we like to purge the OUT-Q at the end of all tests. According to the documentation the "After Suite" would be the place to clean up JMS destinations. So we use the testcase:after-suite with action "purge-endpoint".

Sometimes messages are indeed purged (received), but other times, the logging shows an IllegalStateException: Session is closed. I suspect that connections are being closed in a parallel process which sometimes results in a failure while purging the JMS endpoint (hornetq-queue).

Can you confirm/fix this? Thanks in advance!

Kind regards, Erik Loosman

Failure example:

[INFO ] 14-06-2016 12:46:22 GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@5ed828d: startup date [Tue Jun 14 12:45:42 CEST 2016]; root of context hierarchy
[INFO ] 14-06-2016 12:46:22 SequenceAfterSuite - Entering after suite block
[ERROR] 14-06-2016 12:46:22 SequenceAfterSuite - After suite action failed purge-endpointNested exception is:
org.springframework.jms.IllegalStateException: Session is closed; nested exception is javax.jms.IllegalStateException: Session is closed
        at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:279)
        at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
        at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:497)
        at org.springframework.jms.core.JmsTemplate.receiveSelected(JmsTemplate.java:754)
        at org.springframework.jms.core.JmsTemplate.receive(JmsTemplate.java:733)
        at org.springframework.jms.core.JmsTemplate.receive(JmsTemplate.java:724)
        at com.consol.citrus.jms.endpoint.JmsConsumer.receive(JmsConsumer.java:67)
        at com.consol.citrus.messaging.AbstractSelectiveMessageConsumer.receive(AbstractSelectiveMessageConsumer.java:50)
        at com.consol.citrus.actions.PurgeEndpointAction.purgeEndpoint(PurgeEndpointAction.java:114)
        at com.consol.citrus.actions.PurgeEndpointAction.doExecute(PurgeEndpointAction.java:83)
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
        at com.consol.citrus.container.SequenceAfterSuite.doExecute(SequenceAfterSuite.java:58)
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
        at com.consol.citrus.junit.TestSuiteExecutionListener$AfterSuiteShutdownHook.run(TestSuiteExecutionListener.java:102)
        at java.lang.Thread.run(Thread.java:745)
Caused by: javax.jms.IllegalStateException: Session is closed
        at org.hornetq.jms.client.HornetQSession.checkClosed(HornetQSession.java:1216)
        at org.hornetq.jms.client.HornetQSession.getTransacted(HornetQSession.java:194)
        at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.invoke(CachingConnectionFactory.java:386)
        at com.sun.proxy.$Proxy26.getTransacted(Unknown Source)
        at org.springframework.jms.core.JmsTemplate.doReceive(JmsTemplate.java:804)
        at org.springframework.jms.core.JmsTemplate.doReceive(JmsTemplate.java:784)
        at org.springframework.jms.core.JmsTemplate$9.doInJms(JmsTemplate.java:757)
        at org.springframework.jms.core.JmsTemplate$9.doInJms(JmsTemplate.java:754)
        at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:494)
        ... 12 more
[ERROR] 14-06-2016 12:46:22 SequenceAfterSuite - Continue after suite actions
[INFO ] 14-06-2016 12:46:22 Citrus -
[INFO ] 14-06-2016 12:46:22 Citrus - AFTER TEST SUITE: FAILED

Success example

[INFO ] 14-06-2016 12:49:29 SequenceAfterSuite - Entering after suite block
[INFO ] 14-06-2016 12:49:29 GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@44c8afef: startup date [Tue Jun 14 12:49:16 CEST 2016]; root of context hierarchy
[INFO ] 14-06-2016 12:49:29 JmsConsumer - Received JMS message on destination: 'OUT_Q'
[INFO ] 14-06-2016 12:49:29 CachingConnectionFactory - Established shared JMS Connection: org.hornetq.jms.client.HornetQConnection@4faf1215
[INFO ] 14-06-2016 12:49:29 JmsConsumer - Received JMS message on destination: 'OUT_Q'
[INFO ] 14-06-2016 12:49:30 PurgeEndpointAction - Purged message endpoints
[INFO ] 14-06-2016 12:49:30 Citrus -
[INFO ] 14-06-2016 12:49:30 Citrus - AFTER TEST SUITE: SUCCESS
christophd commented 8 years ago

This is because Spring TestNG test support closes the application context automatically after all tests are finished.

The shutdown process of the application context is done before after suite actions in Citrus are started. Then shutdown and after suite actions are running in parallel as you suggested. I need to find out if we can influence the order of after suite operations so Citrus actions are executed before the application context is shut down.