[英]Possible Strange Behaviour in JMS Config Class
這是與我之前的文章不同的但又相關的問題: 安全終止Spring JMS應用程序
我使用Spring Boot的JMS應用程序可以正確處理所有內容,並且可以正常關閉。 為了使它起作用,我從以下位置更改了一個bean:
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(mqConnectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setConcurrency("1");
factory.setErrorHandler(errorHandler());
factory.setSessionTransacted(true);
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return factory;
}
至:
@Bean
public DefaultMessageListenerContainer defaultMessageListenerContainer() {
DefaultMessageListenerContainer jmsListenerContainer = new DefaultMessageListenerContainer();
jmsListenerContainer.setConnectionFactory(mqConnectionFactory());
jmsListenerContainer.setDestinationResolver(destinationResolver());
jmsListenerContainer.setDestinationName(queueName);
jmsListenerContainer.setConcurrency("1");
jmsListenerContainer.setErrorHandler(errorHandler());
jmsListenerContainer.setSessionTransacted(true);
jmsListenerContainer.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
jmsListenerContainer.setAutoStartup(false);
return jmsListenerContainer;
}
問題是,由於我對彈簧的了解很少,我本可以創建一個“修補程序”。 更改的bean jmsListenerContainer.setAutoStartup(false);
當我偶然發現這篇文章時添加了: http : //forum.spring.io/forum/spring-projects/integration/79176-illegalstateexception-no-message-listener-specified為沒有將autoStartup
設置為false的情況我的日志中已處理的消息:
java.lang.IllegalStateException: No message listener specified - see property 'messageListener'
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:691) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:315) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:253) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1150) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1142) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1039) [spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_74]
一切仍在處理並正確關閉,我只是在日志中看到了這一點。 不知道我的配置文件中是否存在沖突,這可能是此問題的根源。 我只想確保所做的更改不會引起問題,即使當前一切都按預期工作且沒有錯誤。
最后,這是我的整個配置類:
@Configuration
@EnableJms
public class MQConfig {
private static final Logger logger = LogManager.getLogger(MQConfig.class.getName());
@Value("${mq.hostName}")
String host;
@Value("${mq.port}")
Integer port;
@Value("${mq.queueManager}")
String queueManager;
@Value("${mq.queueName}")
String queueName;
@Value("${mq.channel}")
String channel;
@Autowired
Environment environment;
@Bean
public DefaultMessageListenerContainer defaultMessageListenerContainer() {
DefaultMessageListenerContainer jmsListenerContainer = new DefaultMessageListenerContainer();
jmsListenerContainer.setConnectionFactory(mqConnectionFactory());
jmsListenerContainer.setDestinationResolver(destinationResolver());
jmsListenerContainer.setDestinationName(queueName);
jmsListenerContainer.setConcurrency("1");
jmsListenerContainer.setErrorHandler(errorHandler());
jmsListenerContainer.setSessionTransacted(true);
jmsListenerContainer.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
jmsListenerContainer.setAutoStartup(false);
return jmsListenerContainer;
}
@Bean
public MQConnectionFactory mqConnectionFactory() {
MQConnectionFactory mqConnectionFactory = new MQConnectionFactory();
try {
mqConnectionFactory.setHostName(host);
mqConnectionFactory.setPort(port);
mqConnectionFactory.setQueueManager(queueManager);
mqConnectionFactory.setTransportType(1);
} catch (JMSException ex) {
logger.error(ex.getStackTrace());
}
return mqConnectionFactory;
}
@Bean
public DynamicDestinationResolver destinationResolver() {
DynamicDestinationResolver destinationResolver = new DynamicDestinationResolver();
try {
Connection connection = mqConnectionFactory().createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destinationResolver.resolveDestinationName(session, queueName, false);
} catch (JMSException ex) {
logger.error(ex.getStackTrace());
}
return destinationResolver;
}
@Bean
public MQQueue mqQueue() {
MQQueue mqQueue = new MQQueue();
try {
mqQueue.setBaseQueueName(queueName);
mqQueue.setBaseQueueManagerName(queueManager);
} catch (JMSException ex) {
logger.error(ex.getStackTrace());
}
return mqQueue;
}
@Bean
public JmsErrorHandler errorHandler(){
return new JmsErrorHandler();
}
@Bean
public MQManager mqHoldManager(){
return new MQManager(host, port, queueName,
queueManager, channel);
}
@Bean
public MQInitializer mqInitializer(){
return new MQInitializer(environment);
}
}
有什么想法嗎? 這很亂嗎?
編輯:JMS偵聽器
@Component
public class MQConsumer {
@Resource(name = "mqHoldManager")
private MQManager mqHoldManager;
@Resource(name = "defaultMessageListenerContainer")
private DefaultMessageListenerContainer listenerContainer;
@Autowired
MQInitializer mqInitializer; /* To ensure this bean executes before Listener Setup not necessarily for any particular usage*/
final Logger logger = LogManager.getLogger(MQConsumer.class.getName());
private static ReportManager reportManager = new ReportManager();
private static boolean isFirstQueue = true;
@JmsListener(destination = "${mq.queueName}")
public void processOrder(String message) throws Exception {...}
我很困惑。
DefaultJmsListenerContainerFactory
用於帶注釋的POJO方法:
@JmsListener(...)
public void foo(String bar) {...}
工廠用於為該方法創建偵聽器容器。
使用您的替換配置,我看不到您曾經在DefaultMessageListenerContainer
配置消息偵聽器。
通常,您將擁有container.setMessageListner(myListener)
,其中myListener
是MessageListener
, SessionAwareMessageListener
或包裝POJO偵聽器的MessageListenerAdapter
。
將autoStartup
設置為false,並且從不啟動容器,除了將容器Bean添加到上下文之外,不會執行任何操作。
我看不到如何通過該配置獲得任何消息。
編輯
您正在使用Spring Boot嗎? 如果是這樣,它將為您創建一個默認的jmsListenerContainerFactory
這是我的最佳猜測。
在這種情況下,您的停止代碼並沒有真正停止實際的容器-只是從未啟動過的“虛擬”容器。
我建議您給您的@JmsListener
一個id
,給@Autowire
JmsListenerEndpointRegistry
並調用registry.getListenerContainer("myListener").stop()
。
@JmsListener(id = "myListener", destination = "${mq.queueName}")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.