开发者

Method not called when using Spring JMS namespace

I have an application which is built on Spring 3.0.5 and uses JMS for exchanging messages. The beans which receive the messages are configured by using the jms namespace. The class looks like this

class MyService {
    public void receive(String msg) {
        ...
    }
}

The Spring configuration looks like this

<jms:listener-container dest开发者_Python百科ination-type="queue">
  <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>

However, when I change the receive method to get a Message object the method is no longer called.

class MyService {
    public void receive(TextMessage msg) {
        ...
    }
}

I realize that I could just use the MessageListenerAdapter but it is more configuration overhead and I am just wondering why this doesn't work.

Any insight is greatly appreciated.

Frank


The <jms:listener> config automatically creates a MessageListenerAdapter for you, so it's not necesarry for you to configure that explicitly.

Your problem is that MessageListenerAdapter is designed to decouple your code from the JMS API altogether. The target method in <jms:listener> must declare one of the parameter types permitted by MessageListenerAdapter (see docs), which represent the possible payload types of a message, i.e. one of String, Serializable, byte[] or Map.

If you want to receive the raw JMS TextMessage object, then your listener class has to implement MessageListener or SessionAwareMessageListener. That makes it a "proper" JMS listener. In that case, the method config becomes redundant, and you can just use :

<jms:listener destination="queue.test" ref="myService"/>

I'm actually rather surprised that Spring didn't throw an exception when it found that your receive method had an invalid parameter type.


What I've figured out is that in order for the MessageListenerAdapter not to convert the message the messageConverter attribute must be set to null. However, when using the namespace configuration it is not possible to disable the default message converter that is automatically created.

The code in the AbstractListenerContainerParser checks if the message-converter attribute of the <jms:listener-container> is either not set or points to a valid bean. Otherwise a SimpleMessageAdapter is instantiated.

To work around this problem I've created a NoopMessageConverter which solves the problem

public class NoopMessageConverter implements MessageConverter {
    @Override
    public Message toMessage(Object object, Session session) 
        throws JMSException, MessageConversionException {
        return (Message) object;
    }

    @Override
    public Object fromMessage(Message message) 
        throws JMSException, MessageConversionException {
        return message;
    }
}

Then configure the <jms:listener-container> like this

<bean id="noopMessageConverter" class="NoopMessageConverter"/>

<jms:listener-container message-converter="noopMessageConverter">
    <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>

Then you can create your bean as follows and the receive method is called

class MyService {
    public void receive(TextMessage msg) {
        ...
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜