2011-11-14 2 views
2

시스템에서 JMS 메시지를 수신 할 때 응용 프로그램 컨텍스트를 새로 고침하고 싶습니다. 이를 위해 Spring Integration jms : message-driven-channel-adapter를 설정하여 ApplicationContextAware를 구현하는 서비스 액티베이터에 메시지를 전달합니다. 이 액티베이터 (ConfigurationReloader 클래스)는 ConfigurableApplicationContext # refresh() 메소드를 호출합니다. 다음은 JMS 메시지 전달시 스프링 컨텍스트 새로 고침

샘플 코드입니다 :

<jms:message-driven-channel-adapter id="jmsDriverConfigurationAdapter" 
    destination="configurationApplyQueue" channel="jmsConfigurationInboundChannel" /> 

<channel id="jmsConfigurationInboundChannel"/> 

<service-activator input-channel="jmsConfigurationInboundChannel" ref="configurationReloader" method="refresh"/> 

그리고 내 활성 :

public final class ConfigurationReloader implements ApplicationContextAware { 
     private ConfigurableApplicationContext applicationContext; 

     public void refresh() { 
      this.applicationContext.refresh(); 
     } 

     @Override 
     public void setApplicationContext(
       final ApplicationContext applicationContext) throws BeansException { 
      if (applicationContext instanceof ConfigurableApplicationContext) { 
       this.applicationContext = 
        (ConfigurableApplicationContext) applicationContext; 
      } 
     } 
    } 
같은 메시지 컨텍스트 시작 종료 동작을 제공하는 경우

하지만 DefaultMessageListenerContainer 콩 종료에 붙어 :

2011-11-14 15:42:52,980 [org.springframework.jms.listener.DefaultMessageLis tenerContainer#0-1] DEBUG org.springframework.jms.listener.DefaultMessageLis tenerContainer - Shutting down JMS listener container 
2011-11-14 15:42:52,980 [org.springframework.jms.listener.DefaultMessageLis tenerContainer#0-1] DEBUG org.springframework.jms.listener.DefaultMessageLis tenerContainer - Waiting for shutdown of message listener invokers 
2011-11-14 15:42:55,104 [org.springframework.jms.listener.DefaultMessageLis tenerContainer#0-1] DEBUG org.springframework.jms.listener.DefaultMessageLis tenerContainer - Still waiting for shutdown of 1 message listener invokers 

JMS를 통해이 작업을 호출하는 것이 중요합니다. 왜냐하면 n ew 구성 매개 변수가 메시지와 함께 전달됩니다. SpringCore 및 Spring Integration의 최신 버전을 기반으로 한 전면에 DispatcherServlet이있는 표준 Spring MVC 애플리케이션입니다. 또한 컨트롤러를 통해 ConfigurationLoader를 호출하면 정상적으로 작동하므로 JMS 관련 문제라고 확신합니다. 내가 DefaultMessageListenerContainer 번호 538 행 호출 후 그것을 stucks (lifecycleMonitor에 대기() 메소드) 디버깅했듯이

는 :

/** 
* Destroy the registered JMS Sessions and associated MessageConsumers. 
*/ 
protected void doShutdown() throws JMSException { 
    logger.debug("Waiting for shutdown of message listener invokers"); 
    try { 
     synchronized (this.lifecycleMonitor) { 
      while (this.activeInvokerCount > 0) { 
       if (logger.isDebugEnabled()) { 
        logger.debug("Still waiting for shutdown of " + this.activeInvokerCount + 
          " message listener invokers"); 
       } 
       this.lifecycleMonitor.wait(); // <--- line 538 
      } 
     } 
    } 
    catch (InterruptedException ex) { 
     // Re-interrupt current thread, to allow other threads to react. 
     Thread.currentThread().interrupt(); 
    } 
} 

... 그래서 아마 그것의가는 notifyAll 모니터/통지 전화를 아무도 없다 어떤 종류의 벌레?

감사합니다.

답변

2

왜 이러한 정교한 아키텍처가 필요한지 설명해주십시오. JMS 메시지를 받았을 때 응용 프로그램 컨텍스트를 다시로드합니까? 미친 소리인가요? 아니면 독창적 인 것 같아요?

그래도 나는 100 % 확신 할 수는 없지만 제공된 정보는 매우 명확합니다. JMS 메시지를 소비하면서 애플리케이션 컨텍스트를 종료하려고합니다. 그러나 소비자가 Spring에서 관리하기 때문에 컨텍스트는 완전히 종료 될 때까지 기다릴 수 없습니다. Spring Integration 메시지 소비자가 필요로하는 컨텍스트를 포함하여 ConfigurationReloader입니다. 그리고 ConfigurationReloader은 컨텍스트가 파손되기를 기다리기 때문에 완료 할 수 없습니다 (refresh()이 차단됨).

간단히 말하면 순환 종속성과 교착 상태가 도입되었습니다.

해결책은 간단합니다. 컨텍스트 새로 고침을 지연하여 JMS 메시지가 소비 된 후에 발생하도록합니다. 가장 쉬운 방법은 다음과 같습니다.

public void refresh() { 
    Thread destroyThread = new Thread() { 
     @Override 
     public void run() { 
      this.applicationContext.refresh(); 
     } 
    }; 
    destroyThread.start(); 
} 

이 방법이 효과가있을 것이라고 저는 확신합니다.

+0

그래, 고마워! 그것이 독창적인지는 모르지만 조금은 미친 짓인지는 모르겠다;) 내가 이루고자하는 것은 일종의 동적 통합 계층이다. 구성 요소 (전체 통합 계층)의 설계는 JMS를 통해 제공됩니다. 교착 상태가 맞았습니다. 다른 솔루션 (더 간단 할 수도 있음)은 DirectChannel 대신 QueueChannel을 사용하는 것입니다. 메시지가 큐에 놓이면 DMLC 리스너 스레드 처리가 완료됩니다. 그런 다음 메시지가 대기열에서 가져오고 교착 상태없이 동일한 스레드에서 컨텍스트가 새로 고쳐질 수 있습니다. –