Class MatsSpringAnnotationRegistration

All Implemented Interfaces:
org.springframework.beans.factory.Aware, org.springframework.beans.factory.config.BeanPostProcessor, org.springframework.context.ApplicationContextAware

@Role(2) @Component public class MatsSpringAnnotationRegistration extends Object implements org.springframework.beans.factory.config.BeanPostProcessor, org.springframework.context.ApplicationContextAware
The BeanPostProcessor-class specified by the @EnableMats annotation.

It checks all Spring beans in the current Spring ApplicationContext for whether their classes are annotated with @MatsClassMapping, or if they have methods annotated with @MatsMapping or @MatsEndpointSetup, and if so configures Mats endpoints for them on the (possibly specified) MatsFactory. It will also control any registered MatsFactory beans, invoking MatsFactory.holdEndpointsUntilFactoryIsStarted() early in the startup procedure before adding the endpoints, and then MatsFactory.start() as late as possible in the startup procedure. Upon Spring context shutdown, it invokes MatsFactory.stop(..) as early as possible in the shutdown procedure.

Startup procedure:

  1. The MatsSpringAnnotationRegistration (which is a BeanPostProcessor) will have each bean in the Spring ApplicationContext presented:
    1. Each MatsFactory bean will have their MatsFactory.holdEndpointsUntilFactoryIsStarted() method invoked.
    2. Each bean, and each method of each bean, will be searched for the relevant annotations. Such annotated methods will be put in a list.
  2. Upon ContextRefreshedEvent:
    1. All definitions that was put in the list will be processed, and Mats Endpoints will be registered into the MatsFactory - using the specified MatsFactory if this was qualified in the definition (Read more at @MatsMapping).
    2. Then, all MatsFactories present in the ApplicationContext will have their MatsFactory.start() method invoked, which will "release" the configured Mats endpoints, so that they will start (which in turn fires up their "stage processor" threads, which will each go and get a connection to the underlying MQ (which probably is JMS-based) and start to listen for messages).

Notice: ContextRefreshedEvent is invoked late in the Spring ApplicationContext startup procedure. This means that all beans have been fully injected, and any @PostConstruct and lifecycle events have been run. Thus, if the Endpoint depends on any bean/service, it is now running. This is important as the Endpoint's Stage Processors will start picking messages of the queue pretty much immediately. And this is important again if you have any cache that takes time to be populated - it might be of interest to instead use programmatic registration and implement delayed start for Endpoints which depends on caches that take a substantial time to load.

Notice: All MatsFactories found in the Spring ApplicationContext are started, regardless of whether they had any Mats endpoints registered using the Mats SpringConfig. This implies that if you register any Mats endpoints programmatically using e.g. @PostConstruct or similar functionality, these will also be started - unless they have not had their MatsEndpoint.finishSetup() method invoked, ref. "delayed start" mentioned above.

Shutdown procedure:

  1. Upon ContextClosedEvent, all MatsFactories in the ApplicationContext will have their stop() method invoked.
  2. This causes all registered Mats Endpoints to be stopped, which releases the connection to the underlying MQ and stops the stage processor threads.

Notice: ContextClosedEvent is fired rather early in the Spring ApplicationContext shutdown procedure. When running in integration testing mode, which typically will involve starting an in-vm ActiveMQ in the same JVM as the endpoints, this early stopping and releasing of connections is beneficial so that when the in-vm ActiveMQ is stopped somewhat later, one won't get a load of connection failures from the Mats endpoints which otherwise would have their connections shut down under their feet.

  • Constructor Details

    • MatsSpringAnnotationRegistration

      public MatsSpringAnnotationRegistration()
  • Method Details

    • setApplicationContext

      public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException
      Specified by:
      setApplicationContext in interface org.springframework.context.ApplicationContextAware
    • postProcessBeforeInitialization

      public Object postProcessBeforeInitialization(Object bean, String beanName) throws org.springframework.beans.BeansException
      Specified by:
      postProcessBeforeInitialization in interface org.springframework.beans.factory.config.BeanPostProcessor
    • postProcessAfterInitialization

      public Object postProcessAfterInitialization(Object bean, String beanName) throws org.springframework.beans.BeansException
      Specified by:
      postProcessAfterInitialization in interface org.springframework.beans.factory.config.BeanPostProcessor
    • onContextRefreshedEvent

      @EventListener public void onContextRefreshedEvent(org.springframework.context.event.ContextRefreshedEvent e)
      ContextRefreshedEvent runs pretty much as the latest step in the Spring life cycle starting process: Processes all MatsMapping and MatsEndpointSetup annotations, then starts the MatsFactory, which will start any "hanging" MATS Endpoints, which will then start consuming messages.
    • onContextClosedEvent

      @EventListener public void onContextClosedEvent(org.springframework.context.event.ContextClosedEvent e)
      ContextClosedEvent runs pretty much as the first step in the Spring life cycle stopping process: Stop the MatsFactory, which will stop all MATS Endpoints, which will have them release their JMS resources - and then the MatsFactory will clean out the JmsMatsJmsSessionHandler.