Original discussion here

There have been several reports of message listeners still actively listening while being the in the application context cache during integration tests. There does not seem to be a mechanism to keep these listener beans in the cache while also switching off the listening.

Would it make sense to extend the SmartLifecycle interface?

Something like onEnterActiveContext and onLeaveActiveContext could be intercepted in the listener beans to toggle the listening. These methods would be called when a bean moves into or out of the active application context. It's not the same as start and stop, which are only called when the bean is loaded for the first time and when the application shuts down.

Comment From: jhoeller

Actually, stop() and re-start() is a quite good fit when becoming inactive and then active again. Those are not just for startup and shutdown, they also allow for intermediate pausing and restarting, with a lot of refinements having gone into that in 6.1 in particular (not least of it all for CRaC snapshots).

ConfigurableApplicationContext itself extends Lifecycle for that reason, providing context-level stop() and start() methods that propagate to all contained Lifecycle beans. We could possibly call those methods when a context becomes inactive (entering the context cache) and then active again (taken out of the context cache).

Comment From: fabian-flechtmann

Thanks for getting back to me!

That sounds like a good fit. The listener i'm working with is already reacting to start() and stop() as you propose and others probably are as well.

Do you think it would break any existing behavior to call these methods when a context becomes inactive?

Comment From: jhoeller

I see it as a pretty straightforward step for the state of the context itself.

That said, the Test Context Framework needs to be able to track when a context actually becomes inactive. At the moment, multiple tests can use the same context from the cache without 'returning' it, so there is no actual tracking when a context becomes inactive (in the sense of not being used by any test at the moment). I need to discuss this with @sbrannen, let's see what we can do there.

Comment From: sbrannen

After discussing this with @jhoeller, we have decided that it is worthwhile investigating whether we can stop an inactive ApplicationContext in the TestContext framework.

This could potentially be achieved via the following.

  • Track "active" contexts in the ContextCache via some sort of active use counter.
  • Increment the active use counter and start the ApplicationContext whenever TestContext.getApplicationContext() is invoked the first time for a given test class.
  • Decrement the active use counter whenever a test class completes (for example, via a AfterAllCallback in JUnit Jupiter).
  • If the decrement results in the active use counter dropping to zero, stop the ApplicationContext.

Figuring out when TestContext.getApplicationContext() is invoked the first time for a given test class is likely not possible without tracking the "active test class" along with the "active use counter". Thus, we might need some form of concurrent data structure (or a structure within DefaultContextCache) for that purpose. Actually, we might be able to track only the "active test classes" instead of any actual counter.

Comment From: sbrannen

As a side note, this is somewhat related to the following issue which resulted in the introduction of test events such as BeforeTestClassEvent and AfterTestClassEvent.

  • 18490