0

I am facing the famous BeanNotOfRequiredTypeException exception while configuring ActiveMQ (5.14.0) on Tomcat 8 (8.5.4) to expose a JMS queue for a Spring (3.2.8) application.

Fixes suggested by several similar questions (to change AOP and proxy behvior) did not help: after applying the changes, the same error came up again:

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]

even if ActiveMQQueue is effectively of type Queue.


Current configuration:

The Spring application looks the queue up via JNDI:

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

The queue is referenced in the web.xml file:

<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>

On server side, the queue is configured in the Tomcat server.xml file as a GlobalNamingResources as:

<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"
    />  

That's the minimal configuration applied so far. The same approach has been applied for a data source and a mail service (server.xml + web.xml + JNDI) working fine, however failing on queue configuration.

Question(s): why Spring keeps on seeing it as a wrong type? Is any further configuration required to set-up ActiveMQ on Tomcat 8 and expose a queue via JNDI?

Community
  • 1
  • 1
A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128

2 Answers2

0

Isn't it the fact that you are declaring two different types on server and client side?

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

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

To better explain: you are downcasting here: you declare a Queue Interface as type in your app web.xml and you receive something implementing it -> downcasting
It should be the contrary or have the server type set to queue

Community
  • 1
  • 1
Vale
  • 1,104
  • 1
  • 10
  • 29
  • Good point, although in all online tutorial (official ones included) the server side configuration comes as described. Simply changing it to the interface leads to another exception: `javax.naming.NameNotFoundException: Name [jms/NotificationProcessQueue] is not bound in this Context. Unable to find [jms]` – A_Di-Matteo Aug 25 '16 at 08:22
  • @A_Di-Matteo Have you tried to change the client side instead? Just to try. I'm also seeing that the following mistake may be given by the fact that you need to specify the exact class you're using, as it happened before in your original Tomcat configuration. I can't say why on the tutorial works while in your doesn't, though. – Vale Aug 25 '16 at 08:51
  • I solved it, check the answer I added. I was a classpath issue. The client keeps on referencing to the specs interface (which is good, no lock-in with implementation libraries like ApacheMQ, in this case), while the server configuration remain unchanged (here you need to reference the real implementation as part of its configuration and integration with the web server). Thanks anyway for your contributions and time. – A_Di-Matteo Aug 25 '16 at 14:10
0

Problem solved: it was a classpath issue.

Applying exactly the same configuration as reported in the question and by simply removing the javax.jms-api library from the deployed war, no exceptions anymore.

The following was applied to the pom.xml file of the application (to its war module actually):

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

Note: the same for required for javax.mail-api library.

This conflict was due to the usage of the activemq-all-5.14.0.jar dropped in the Tomcat lib folder, which also brings the javax.jms-api library with it and as such also comes as part of the application classpath at runtime. Changing the application dependency to scope provided it removed it from the final war file and as such avoiding conflicts on deployment and application start-up time.

A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128