I am able to successfully integrate ActiveMQ(in bound message driven channel) and Kafka (as outbound channel). It working fine.
Now, since Both ActiveMQ and MQ Series are JMS compliant, i thought transition would be easier. But, its throwing below error :
Setup of JMS Message listener invoker failed for destination 'queue://abcd' - trying to recover - Cause: JMSQ1112: The operation for a domain specific object was not valid. The operation 'createConsumer' is not valid for type 'com.ibm.mq.jms.MQQueue'
My spring integration config looks like below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/integration/jms"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:int-kafka="http://www.springframework.org/schema/integration/kafka"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/jms
http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/integration/kafka
http://www.springframework.org/schema/integration/kafka/spring-integration-kafka.xsd">
<jms:message-driven-channel-adapter id="requestChannelAdapter" channel="requestChannel"
container="requestListenerContainer" error-channel=""/>
<int-kafka:outbound-channel-adapter
id="kafkaOutboundChannelAdapter" kafka-template="kafkaTemplate"
auto-startup="true" sync="true" channel="inputToKafka" topic="test">
</int-kafka:outbound-channel-adapter>
</beans>
And my respective code looks like below:
public MQQueueConnectionFactory jmsConnectionfactory() {
MQQueueConnectionFactory jmsFactory = new MQQueueConnectionFactory();
jmsFactory.setHostName(hostname);
jmsFactory.setPort(1444);
jmsFactory.setQueueManager(//valid queue manager);
jmsFactory.setChannel(//valid channel name);
jmsFactory.setTransportType(1);
jmsFactory.setSSLCipherSuite(// valid suite);
return jmsFactory;
}
#Bean
public DefaultMessageListenerContainer requestListenerContainer() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(jmsConnectionfactory());
container.setSessionTransacted(true);
container.setDestination(helloJMSQueue());
return container;
}
#Bean
public Queue helloJMSQueue() {
return new MQQueue(HELLO_QUEUE);
}
Why I am getting this error ? I saw some posts that it is due to pubLocal value not available in jmsTemplate w.r.t MQQueue but that was dated back to 2005 and i noticed the change has been released.
Use just container.setDestinationName(HELLO_QUEUE) instead and let the container to resolve it properly over Session.
Related
I have requirement where I need receive message from MQ every seconds , the message will be in XML format , so i need to write a high effecient MDB. Problem here is I am new to MQ,JMS,Spring JMS and Spring Integration but not spring tough.
Based on google search so far I am able to write below code
MDB
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MyMessageListener implements MessageListener{
#Override
public void onMessage(Message m) {
TextMessage message=(TextMessage)m;
try{
System.out.println(message.getText());
}catch (Exception e) {e.printStackTrace(); }
}
}
XMl config
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="tcp://localhost:61616" />
<bean id="listener" class="com.springexample.MyMessageListener"></bean>
<jms:listener-container container-type="default" connection-factory="connectionFactory"
acknowledge="auto">
<jms:listener destination="myfirstqueue" ref="listener" method="onMessage"></jms:listener>
</jms:listener-container>
</beans>
I know what i have written is very basic one but i dont know what is the efficient one , how to provide transaction support and how to handle such load where i am going to recieve message every seconds.
Should i use Spring JMS or Spring Integration any help is much appreciated.
The question you asked is which to use: definitely go Spring JMS
I am trying to start a simple websocket server in a spring integration application.
I build my application thanks to the following dependancies :
dependencies {
compile("org.springframework.boot:spring-boot-starter-integration")
compile("org.springframework:spring-websocket")
compile("org.springframework.integration:spring-integration-ip")
compile("org.springframework.integration:spring-integration-websocket")
compile('com.fasterxml.jackson.core:jackson-databind')
compile("org.springframework.integration:spring-integration-feed")
}
I launch my application thanks to the following Java file :
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
org.springframework.integration.annotation.IntegrationComponentScan;
#Configuration
#EnableAutoConfiguration
#IntegrationComponentScan
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = new SpringApplication("/integration.xml").run(args);
System.out.println("Hit Enter to terminate");
System.in.read();
ctx.close();
}
}
Here is my "integartion.xml" :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:file="http://www.springframework.org/schema/integration/file"
xmlns:feed="http://www.springframework.org/schema/integration/feed"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:ws="http://www.springframework.org/schema/integration/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/integration/feed http://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/websocket http://www.springframework.org/schema/integration/websocket/spring-integration-websocket.xsd">
<int-ip:udp-inbound-channel-adapter id="udpReceiver"
channel="udpOutChannel"
port="11111"
receive-buffer-size="500"
multicast="true"
multicast-address="225.6.7.8"/>
<int:object-to-string-transformer input-channel="udpOutChannel" output-channel="stringified"/>
<bean id="nmeaParser" class="transformers.NMEAParser"/>
<int:transformer input-channel="stringified" ref="nmeaParser" output-channel="parsedData"/>
<int:channel id="jsondata"/>
<int:object-to-json-transformer input-channel="parsedData" output-channel="jsondata"/>
<ws:server-container id="server" path="/position"/>
<ws:outbound-channel-adapter container="server" channel="jsondata"/>
</beans>
As you can see, I create an UDP inbound channel. This channels works like a charm. I am able to see that data are sucessfully passed to my "NMEAParser" bean.
I think that my Websocket server doesn't work because :
I can't connect to it with wscat... When I try to do :
wscat -c ws://127.0.0.1:8080/position
I receive a "CONNECTION REFUSED", the same message I receive when nothing is launched.
In the Spring log's I can read this :
Starting beans in phase 0
Adding {object-to-string-transformer} as a subscriber to the 'udpOutChannel' channel
Channel 'application:8080.udpOutChannel' has 1 subscriber(s).
started org.springframework.integration.config.ConsumerEndpointFactoryBean#0
Adding {transformer} as a subscriber to the 'stringified' channel
Channel 'application:8080.stringified' has 1 subscriber(s).
started org.springframework.integration.config.ConsumerEndpointFactoryBean#1
Adding {object-to-json-transformer} as a subscriber to the 'parsedData' channel
Channel 'application:8080.parsedData' has 1 subscriber(s).
started org.springframework.integration.config.ConsumerEndpointFactoryBean#2
Adding {websocket:outbound-channel-adapter} as a subscriber to the 'jsondata' channel
Channel 'application:8080.jsondata' has 1 subscriber(s).
started org.springframework.integration.config.ConsumerEndpointFactoryBean#3
Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
Channel 'application:8080.errorChannel' has 1 subscriber(s).
started _org.springframework.integration.errorLogger
Starting beans in phase 1073741823
started udpReceiver
Started Application in 0.792 seconds (JVM running for 1.121)
We can see here that all my beans are launched, except the bean "server" which is my server container. There is no trace of this bean in this log message.
To write my application I read carrefully this sampe and this doc.
What am I doing wrong, or what I forgot ?
As discussed in the chat after our lengthy comment back and forth, you need org.springframework.boot:spring-boot-starter-websocket in your dependencies, this will bring in spring-boot-starter-web and org.springframework.boot:spring-boot-starter-tomcat transitively, giving you a websocket runtime.
Could anyone suggest me how to configure connectionfactory in mule using connectionFactory-ref
I am trying to configure connectionfactory in mule using connectionFactory-ref[this is the url I am following ::: http://www.mulesoft.org/documentation-3.2/display/32X/JMS+Transport+Reference].
In the above mentioned documentation - mentioned -
Configuring the ConnectionFactory
One of the most important attributes is connectionFactory-ref. This is a reference to the ConnectionFactory object which creates new connections for your JMS provider. The object must implement the interface javax.jms.ConnectionFactory.
ConnectionFactory
So to implement the above below is my mule configuraion xml
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:smtps="http://www.mulesoft.org/schema/mule/smtps"
xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:https="http://www.mulesoft.org/schema/mule/https"
xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.5.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/smtps http://www.mulesoft.org/schema/mule/smtps/current/mule-smtps.xsd
http://www.mulesoft.org/schema/mule/https http://www.mulesoft.org/schema/mule/https/current/mule-https.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd">
<spring:bean name="connectionFactory" class="com.ers.connections.ConnectionFactoryImpl"/>
<jms:activemq-connector name="Active_MQForApex" connectionFactory-ref="connectionFactory" validateConnections="true" doc:name="Active MQ"/>
<flow name="apexwritequeueFlow1" doc:name="apexwritequeueFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="niviTest" doc:name="HTTP"/>
<logger message="Payload ::: #[payload]" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint queue="ANS.RecOps.Incoming" connector-ref="Active_MQForApex" doc:name="JMS"/>
</flow>
</mule>
Below java class
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory;
public class ConnectionFactoryImpl implements javax.jms.ConnectionFactory {
#Override
public Connection createConnection() throws JMSException {
// Create a ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("21233", "123", "ssl://xxxx.autonet-yyy.com:443");
return connectionFactory.createConnection();
}
#Override
public Connection createConnection(String arg0, String arg1)
throws JMSException {
// TODO Auto-generated method stub
return null;
}
}
However I am getting this error
. Root Exception was: Unsupported ConnectionFactory type: com.ers.connections.ConnectionFactoryImpl. Type: class java.lang.IllegalArgumentException
ERROR 2014-12-28 11:53:26,141 [main] org.mule.module.launcher.application.DefaultMuleApplication: null
java.lang.IllegalArgumentException: Unsupported ConnectionFactory type: com.ers.connections.ConnectionFactoryImpl
Thank you in advance.
Any suggestions most appreciated.
Thank you and regards
Nivi
If you don't have any really good reason, that you do not show in the post, to write your own ConenctionFactory implementation you should use the one provided by the JMS provider directly.
So you should use a bean definition like this
<spring:bean id="connectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</spring:bean>
You are using the ActiveMQ connector and it is expecting a factory class of type org.apache.activemq.ActiveMQConnectionFactory. If you really need a custom factory, your ConnectionFactoryImpl class should extend the activemq factory:
import org.apache.activemq.ActiveMQConnectionFactory;
public class ConnectionFactoryImpl extends ActiveMQConnectionFactory {
// Override the methods you need
}
Then you can reference it in connectionFactory-ref attribute of the connector.
Your implementation probably does not provide any special feature, if this is the case please just use the default connector:
<jms:activemq-connector name="JmsConnector" specification="1.1" />
However if you have some special behaviour that you want to use, with the activemq connector, you just need a connection factory that implements org.apache.activemq.ActiveMQConnectionFactory, this is because these two lines. Then just use something like the following:
<spring:beans>
<spring:bean name="myActiveMqConnectionFactory"
class="org.apache.activemq.spring.MyActiveMQConnectionFactory"
p:brokerURL="vm://esb-amq-broker" <--- Just some example property />
</spring:beans>
<jms:activemq-connector name="myJmsConnector"
specification="1.1"
connectionFactory-ref="AmqConnectionFactory"
persistentDelivery="true" />
However please twink twice about the need of doing this, the original activemq connector probably provides almost anything you need with the exeption of connection caching. If that is what you need please consider using this.
I wonder if anyone can help. My starter for 10 is that I know very little (next to nothing) about JMS and messaging in general - so please go easy with me with any answers/comments :)
Given that this is a learning exerise for me, I'm trying to put together a very basic Spring JMS config, and then write some integration tests to help me understand how it all works.
This is my current Spring context config with its JMS components:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="com.lv.gi.jmstest.ApplicationContextProvider" />
<!-- Embedded ActiveMQ Broker -->
<amq:broker id="broker" useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0" />
</amq:transportConnectors>
</amq:broker>
<!-- ActiveMQ Destination -->
<amq:queue id="destination" physicalName="myQueueName" />
<!-- JMS ConnectionFactory to use, configuring the embedded broker using XML -->
<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" />
<!-- JMS Producer Configuration -->
<bean id="jmsProducerConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
depends-on="broker"
p:targetConnectionFactory-ref="jmsFactory" />
<bean id="jmsProducerTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="jmsProducerConnectionFactory"
p:defaultDestination-ref="destination" />
<bean class="com.lv.gi.jmstest.JmsMessageProducer">
<constructor-arg index="0" ref="jmsProducerTemplate" />
</bean>
<!-- JMS Consumer Configuration -->
<bean id="jmsConsumerConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
depends-on="broker"
p:targetConnectionFactory-ref="jmsFactory" />
<jms:listener-container container-type="default"
connection-factory="jmsConsumerConnectionFactory"
acknowledge="auto">
<jms:listener destination="myQueueName" ref="jmsMessageListener" />
</jms:listener-container>
<bean id="jmsMessageListener" class="com.lv.gi.jmstest.JmsMessageListener" />
</beans>
My JmsMessageProducer class has a postMessage method as follows:
public void postMessage(final String message) {
template.send(new MessageCreator() {
#Override
public Message createMessage(final Session session) throws JMSException {
final TextMessage textMessage = session.createTextMessage(message);
LOGGER.info("Sending message: " + message);
return textMessage;
}
});
}
And my JmsMessageListener (implements MessageListener) has an onMessage method as follows:
public void onMessage(final Message message) {
try {
if (message instanceof TextMessage) {
final TextMessage tm = (TextMessage)message;
final String msg = tm.getText();
LOGGER.info("Received message '{}'", msg);
}
} catch (final JMSException e) {
LOGGER.error(e.getMessage(), e);
}
}
In my test class, I can fire up the Spring context, get the JmsMessageProducer bean, and call postMessage; and I see the message on the console as expected:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/com/lv/gi/jmstest/JmsMessageListenerTest-context.xml" })
public class TestJms {
private JmsMessageProducer jmsMessageProducer;
#Before
public void setup() {
jmsMessageProducer = ApplicationContextProvider.getApplicationContext().getBean(JmsMessageProducer.class);
}
#Test
public void doStuff() throws InterruptedException {
jmsMessageProducer.postMessage("message 1");
}
}
Whilst this works, its not really much of a test, because other than me visually seeing the message received on the console, I can't assert the message has been received.
We use mockito, so I'm wondering if there is a way within my test that I can replace the MessageListener bean with a mock, then call verify on it. I guess I could do it by providing a different Spring context file for the purpose of these tests, but that might not work well with my next requirement ...
My end goal with all of this is to create a Topic, where my message producer can fire a message onto the queue, and 1 of more MessageListeners will read the message off the queue, and when all registered listeners have read the message, the message is deleted from the queue. (I think Topic is the right terminology for this!)
To prove that this system would work, I would want a test where I can fire up the Spring context. The first thing I'd want to do is replace the listener with 3 mocks all wired to the same destination so that I can use verify on each of them. I'd post a message, then verify that each mock has received. Then I'd want to remove/disable 2 of the listeners, call postMessage, and verify the onMessage method was called on the one remaining mock listener. Then perhaps wait a while, and re-establish the 2 mocks, and verify their onMessage method was called. And finally, check the message is no longer on the queue (by virtue of the fact that the 3 registered listeners had all received the message)
With the above in mind, I think what I'm trying to do is register and de-register (or disable) listeners against the destination at runtime, and if I can do that, then I can register mocks.
Phew!, that's complicated!, but I hope it makes sense as to what I'm trying to do?
Any pointers as to how to achieve this? Many thanks in advance,
Nathan
In my opinion, as soon as you are doing integration testing, you should not try to mock anything.
On one hand you write unit tests. For example, you could test the behaviours of your consumer, by calling the onMessage method of jmsMessageListener directly from your tests. You typically don't use SpringJUnit4ClassRunner for this kind of test, and you typically use Mockito to mock the dependencies of the object you are testing.
On the other hand you have integration tests. These are testing the behaviour of your entire application. It would make sense to use SpringJUnit4ClassRunner.class here, but not Mockito. You should test that whatever your jmsListener was supposed to do has been done. For example, if your application was supposed to write logs about the incoming message, open the log file and check it.
Your example here is very simple, maybe this is why you are confused (in my opinion). With a more complex listener, it would be more natural to it isolated from the rest of the system.
I am trying to write channel adapter for JMS queue. I'd like to send message to JMS queue and receive it on Spring Integration's channel.
When I use plain JMS (with ActiveMQ), everything works properly, so I assume bug is somewhere in my Spring code.
So here's my Spring config file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jms="http://www.springframework.org/schema/integration/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jms
http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">
<!-- jms beans -->
<bean id="jms.msgQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="MSG_QUEUE" />
</bean>
<bean name="jms.connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<!-- spring integration beans -->
<int:channel id="channels.jms.allMessages">
<int:queue capacity="1000" />
</int:channel>
<jms:inbound-channel-adapter id="adapters.jms.msgAdapter"
connection-factory="jms.connectionFactory"
destination="jms.msgQueue"
channel="channels.jms.allMessages">
<int:poller fixed-rate="500" />
</jms:inbound-channel-adapter>
</beans>
Here is plain JMS sending-receiving code that works without problems:
#Test
public void testPlainJms() throws JMSException {
MessageProducer producer = session.createProducer(msgQueue);
MessageConsumer consumer = session.createConsumer(msgQueue);
// send to JMS queue
TextMessage textMessage = session.createTextMessage();
textMessage.setText("Message from JMS");
producer.send(textMessage);
connection.start();
javax.jms.Message message = consumer.receive(TIMEOUT);
assertEquals("Message from JMS", ((TextMessage) message).getText());
connection.stop();
}
And here is code using Spring's MessageChannel that usually doesn't work (it sometimes does but I am not able to determine when):
#Test
public void testInboundAdapter() throws JMSException {
MessageProducer producer = session.createProducer(msgQueue);
// send to JMS queue
TextMessage textMessage = session.createTextMessage();
textMessage.setText("Message from JMS");
producer.send(textMessage);
// receive in local channel (using inbound adapter)
Message<?> received = ((PollableChannel) msgChannel).receive(TIMEOUT);
String payload = (String) received.getPayload();
assertEquals("Message from JMS", payload);
}
I am getting NullPointerException on receiving message from pollable msgChannel. Here's how I autowired beans from Spring config to my test class:
#Autowired #Qualifier("jms.msgQueue")
Queue msgQueue;
#Autowired #Qualifier("channels.jms.allMessages")
MessageChannel msgChannel;
#Autowired
ConnectionFactory connectionFactory;
Strange, I am able to reproduce your issue, could be a bug with inbound-channel-adapter, I have something which consistently works though, by changing from an inbound-channel-adapter to message-driven-channel-adapter, try with this:
<jms:message-driven-channel-adapter id="adapters.jms.msgAdapter"
connection-factory="jms.connectionFactory"
destination="jms.msgQueue"
channel="channels.jms.allMessages" />
It fail when it timeout.
Message<?> received = ((PollableChannel) msgChannel).receive(TIMEOUT);
You must check received for null