Disclaimer: On the technicalness continuum, this post is way over into “impossibly technical”. But I needed somewhere to jot this down (a text file on one’s desktop can only last so long…)
It was blowing up…
When we started up an application context that had a Spring DefaultMessageListenerContainer, and the JMS Queue that listenercontainer pointed to already had messages in it, the messagelistenercontainer (fairly reproducibly, it seemed) called our listener before our listener’s beans were all initialized by Spring (i.e., before it was “wired”). This resulted in a Java NullPointerException.
An indignant pause
Imagine! Not being able to trust a big-name Inversion of Control container like Spring to do its job properly! But before reporting a bug, we wanted to put a minimal test together demonstrating the problem.
Complicating factors were:
- The error was happening inside an AOP around advice method before it even got into the MessageListener’s onMessage method; and
- The process was running on an application server
So… was the problem simply with Spring? Or was it something about the AOP setup? Or was it something that would only show up in the context of running on an app server? I (with Keith’s help) came up with a plan to root out the cause of the error.
Diagnostic Test Plan
Level A: Message already in queue (NON app server, NON AOP version)
We’d try the simplest test first to see if we could reproduce the issue without being on an app server and without AOP.
- Create a small Java app that puts a text message in the JMS Queue
- Upon receiving a message, the Messagelistener (in a separate Java app) calls its helloWorld bean’s sayHello() method, passing the string from the JMS text message. The listener thread would create the application context and then sleep for a while.
Level B: Add AOP advice
If Level A didn’t reproduce the problem, we’d add AOP around advice to the MessageListener’s onMessage method, and the around advice would need to internally use a Spring bean
Level C: Do Level A test in an app server environment
Level D: Do Level B test in an app server environment
Potential Post-D levels, if we still can’t reproduce the problem:
– Maybe it only happens with JMS Object messages…?
An Unexpectedly Quick Resolution
I was getting the Level A test put together when Keith had a thought. Our Spring context bootstrap code – in what order were we loading things there?
We looked, and what do you know – the Spring context that contained the MessageListenerContainer that was starting up “too early” and blowing up if messages were already in the queue depended on something in another Spring context, which at that point our bootstrap code had not loaded yet. The problem was in our bootstrap code, a simple ordering problem!
Being new and slow with this stuff, it took me a while to write the test to confirm this, but that was the issue.