Skip to content

SpringEventTranslator - do not relay events if the reactor Environment is not alive #9912

@zyro23

Description

@zyro23

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. run sample-app
  2. see stacktrace

Expected Behaviour

  • the application should shutdown gracefully without errors
  • SpringEventTranslator should only relay events to reactor if the reactor Environment is alive
    • which is not always the case during application shutdown / spring context closing

i tried to override springReactorEventTranslator with a custom impl like this:

void onApplicationEvent(ApplicationEvent event) {
    def eventName = eventClassToName[event.getClass()]
    // don't relay events if Reactor is shutdown
    if (Environment.alive()) {
        notify(eventName, eventFor(event))
    }
}

this brought the desired result (clean shutdown)

Actual Behaviour

  • the spring websocket support fires a BrokerAvailabilityEvent (false) when the ApplicationContext is closed
  • that results in an exception (reactor dispatcher already closed)

stacktrace:

java.lang.IllegalArgumentException: This Dispatcher has been shut down.
    at reactor.core.support.Assert.isTrue(Assert.java:61) ~[reactor-core-2.0.7.RELEASE.jar:na]
    at reactor.core.dispatch.AbstractLifecycleDispatcher.dispatch(AbstractLifecycleDispatcher.java:111) ~[reactor-core-2.0.7.RELEASE.jar:na]
    at reactor.bus.EventBus.notify(EventBus.java:368) ~[reactor-bus-2.0.7.RELEASE.jar:na]
    at grails.events.Events$Trait$Helper.notify(Events.groovy:111) ~[grails-plugin-events-3.1.6.jar:3.1.6]
    at org.grails.events.spring.SpringEventTranslator.notify(SpringEventTranslator.groovy) ~[grails-plugin-events-3.1.6.jar:3.1.6]
    at org.grails.events.spring.SpringEventTranslator.onApplicationEvent(SpringEventTranslator.groovy:63) ~[grails-plugin-events-3.1.6.jar:3.1.6]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.publishBrokerUnavailableEvent(AbstractBrokerMessageHandler.java:272) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.stopInternal(SimpleBrokerMessageHandler.java:206) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.stop(AbstractBrokerMessageHandler.java:179) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.stop(AbstractBrokerMessageHandler.java:196) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.doStop(DefaultLifecycleProcessor.java:229) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.access$300(DefaultLifecycleProcessor.java:51) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.stop(DefaultLifecycleProcessor.java:363) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:202) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.onClose(DefaultLifecycleProcessor.java:118) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:975) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:901) [spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]

2016-05-05 13:27:54.829  WARN 4976 --- [       Thread-9] o.s.c.support.DefaultLifecycleProcessor  : Failed to shut down 1 bean with phase value 2147483647 within timeout of 30000: [simpleBrokerMessageHandler]

Environment Information

  • Operating System: win x64
  • Grails Version: 3.1.6
  • JDK Version: 8
  • Container Version (If Applicable): n/a

Example Application

  • see referenced commit
  • added grails-spring-websocket plugin, no further config
  • the Application class does a Runtime.runtime.exit 0 right after the app started

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions