【问题标题】:How to specify custom JMS Message Listener in Spring Xml如何在 Spring Xml 中指定自定义 JMS 消息侦听器
【发布时间】:2013-10-09 19:00:28
【问题描述】:

我是 JMS 的新手,需要批处理请求以供侦听器处理。链接:http://sleeplessinslc.blogspot.in/2010/04/batchmessagelistenercontainer-using.html 给出了一个很好的解决方案。我坚持执行相同的操作。我没有使用默认容器,而是重写了容器类以使用这个新类:

<jms:listener-container container-class="org.bsnyder.spring.jms.listener.BatchMessageListenerContainer"
       acknowledge="transacted">
    <jms:listener destination="CHANDRA.BATCHTEST" ref="messageListener" />
</jms:listener-container>

<bean id="messageListener" class="org.bsnyder.spring.jms.listener.BatchMessageListener" />

这里的 BatchMessageListener 扩展了博客中提到的 SessionAwareBatchMessageListener。

我得到的错误是:

[ERROR] PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'messageListener' threw exception; 
nested exception is java.lang.IllegalArgumentException: Message listener needs to be of type [org.bsnyder.spring.jms.listener.SessionAwareBatchMessageListener]: 
Failed properties: Property 'messageListener' threw exception; nested exception is java.lang.IllegalArgumentException: Message listener needs to be of type [org.bsnyder.spring.jms.listener.SessionAwareBatchMessageListener]

我应该更改容器类型(默认为“默认”)吗? http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/jms.html 不包含有关如何设置的详细信息。

【问题讨论】:

    标签: java spring jms message-queue


    【解决方案1】:

    问题在于 jms 命名空间解析器正在创建一个 org.springframework.jms.listener.adapter.MessageListenerAdapter 实例,该实例带有一个引用您的 org.bsnyder.spring.jms.listener.BatchMessageListener 实例的 delegate 属性。因此,在BatchMessageListenerContainercheckMessageListener() 方法中,您需要更改:

    protected void checkMessageListener(Object messageListener) {
        if (!(messageListener instanceof SessionAwareBatchMessageListener)) {
            throw new IllegalArgumentException("Message listener needs to be of type ["
                    + SessionAwareBatchMessageListener.class.getName() + "]");
        }
    }
    

    ...到这个:

    protected void checkMessageListener(Object messageListener) {
        if (!(messageListener instanceof MessageListenerAdapter)) {
            throw new IllegalArgumentException("Message listener needs to be of type ["
                    + MessageListenerAdapter.class.getName() + "]");
        }
    }
    

    虽然,在验证已加载的类方面,这确实对您没有太大帮助。同样不幸的是MessageListenerAdaptergetDelegate()方法被保护了;否则,您可以检查委托的类型,这应该是您的自定义 SessionAwareBatchMessageListener 的一个实例。我想你可以使用反射。或者,您可以避免使用 jms 命名空间并创建自己的自定义 BatchMessageListenerAdapter 来实现 SessionAwareBatchMesageListener 并扩展 MessageListenerAdapter 并使用该自定义适配器而不是 jms 命名空间的默认实现。 (顺便说一句,没有办法覆盖这个默认值。)归根结底,它归结为你是否真的需要加载时验证。

    如果您想跳过验证,只需这样做:

    protected void checkMessageListener(Object messageListener) {
        // Do nothing...
    }
    

    这将使您的应用可以毫无问题地加载。

    【讨论】:

      【解决方案2】:

      为什么需要从队列中批量读取消息?在这种情况下,我强烈建议您使用 spring batch 而不是编写自定义批处理侦听器。 Spring 批处理很容易配置。

      【讨论】:

      • 好点杰伊。 Spring Batch 没有内置的持久层和故障转移设置。它都配置了现有的 ActiveMq 层,并希望重用它。
      • Spring 批处理具有非常明确的故障转移设置。它有一个存储所有批处理作业相关信息的作业存储库。如果您需要任何持久层,您可以轻松插入 spring-jdbc 或 hibernate。
      • 天啊,还需要从多个客户端获取请求。将消息放入队列听起来对客户来说更容易。
      • 你有使用spring batch批量读取消息的例子吗?
      猜你喜欢
      • 2019-03-24
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多