【问题标题】:Tomcat8 and ActiveMQ: Bean named 'someQueue' must be of type [javax.jms.Queue], but was actually of type [org.apache.activemq.command.ActiveMQQueue]Tomcat8 和 ActiveMQ:名为“someQueue”的 Bean 必须是 [javax.jms.Queue] 类型,但实际上是 [org.apache.activemq.command.ActiveMQQueue] 类型
【发布时间】:2016-12-31 19:42:42
【问题描述】:

我在 Tomcat 8 (8.5.4) 上配置 ActiveMQ (5.14.0) 以公开 JMS 队列时遇到 famous BeanNotOfRequiredTypeException 异常Spring (3.2.8) 应用程序。

several 类似问题建议的修复(更改 AOP 和代理行为)没有帮助:应用更改后,再次出现相同的错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'notificationService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'someQueue' must be of type [javax.jms.Queue], but was actually of type [org.apache.activemq.command.ActiveMQQueue]

即使ActiveMQQueue 实际上是Queue 类型。


当前配置:

Spring 应用程序通过 JNDI 查找队列:

<jee:jndi-lookup jndi-name="jms/someQueue" id="someQueue" />

队列在web.xml文件中被引用:

<resource-ref>
    <description>Factory</description>
    <res-ref-name>jms/someConnectionFactory</res-ref-name>
    <res-type>javax.jms.QueueConnectionFactory</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

<resource-ref>
    <description>Queue</description>
    <res-ref-name>jms/someProcessQueue</res-ref-name>
    <res-type>javax.jms.Queue</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

在服务器端,队列在 Tomcat server.xml 文件中配置为 GlobalNamingResources 为:

<Resource name="jms/someConnectionFactory" 
        auth="Container" 
        type="org.apache.activemq.ActiveMQConnectionFactory" 
        factory="org.apache.activemq.jndi.JNDIReferenceFactory" 
        description="JMS Connection Factory" 
        brokerURL="vm://localhost" 
        brokerName="LocalActiveMQBroker" 
        useEmbeddedBroker="true"
    />

<Resource name="jms/someQueue"
        auth="Container"
        type="org.apache.activemq.command.ActiveMQQueue"
        description="JMS queue"
        factory="org.apache.activemq.jndi.JNDIReferenceFactory"
        physicalName="SOME.QUEUE"
    />  

这是迄今为止应用的最小配置。相同的方法已应用于数据源和邮件服务 (server.xml + web.xml + JNDI) 工作正常,但在队列配置上失败。

问题:为什么 Spring 一直将其视为错误类型?在 Tomcat 8 上设置 ActiveMQ 并通过 JNDI 公开队列是否需要任何进一步的配置?

【问题讨论】:

  • 您的 JNDI 正在寻找 jms/someQueue 但其他示例看起来像是将其命名为 jms/someProcessQueue
  • @Gandalf 输入问题时出现错误,感谢您的吐槽

标签: java spring tomcat activemq tomcat8


【解决方案1】:

难道不是你在服务器端和客户端声明了两种不同的类型吗?

//On the Tomcat side
type="org.apache.activemq.command.ActiveMQQueue"

//In the web.xml of your app
<res-type>javax.jms.Queue</res-type>

为了更好地解释:你在这里向下转换:你在你的应用程序 web.xml 中声明一个队列接口作为类型,你会收到一些实现它的东西 -> downcasting
应该是相反的或者将服务器类型设置为队列

【讨论】:

  • 好点,尽管在所有在线教程(包括官方教程)中,服务器端配置都如所述。简单地将其更改为接口会导致另一个异常:javax.naming.NameNotFoundException: Name [jms/NotificationProcessQueue] is not bound in this Context. Unable to find [jms]
  • @A_Di-Matteo 您是否尝试过更改客户端?只是想试试。我还看到以下错误可能是由于您需要指定您正在使用的确切类这一事实,就像以前在原始 Tomcat 配置中发生的那样。不过,我不能说为什么在教程中有效,而在你的无效。
  • 我解决了,检查我添加的答案。我是一个类路径问题。客户端继续引用规范接口(这很好,在这种情况下,没有锁定像 ApacheMQ 这样的实现库),而服务器配置保持不变(这里您需要引用真实的实现作为其配置的一部分和与网络服务器集成)。无论如何感谢您的贡献和时间。
【解决方案2】:

问题已解决:这是一个类路径问题

应用与问题中报告的完全相同的配置,只需从已部署的 war 中删除 javax.jms-api 库,不再有例外。

以下内容应用于应用程序的pom.xml 文件(实际上应用于其war 模块):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>javax.jms</groupId>
            <artifactId>javax.jms-api</artifactId>
            <version>2.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

注意:javax.mail-api 库的要求相同。

此冲突是由于使用了 Tomcat lib 文件夹中的 activemq-all-5.14.0.jar,该文件夹还带来了 javax.jms-api 库,因此也作为运行时应用程序类路径的一部分出现。将应用程序依赖项更改为provided 范围,它将它从最终的war 文件中删除,从而避免了部署和应用程序启动时间的冲突。

【讨论】:

    猜你喜欢
    • 2012-01-13
    • 2013-01-10
    • 1970-01-01
    • 2018-10-05
    • 2021-03-21
    • 2018-09-18
    • 2014-12-09
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多