1
votes

I am trying to get a simple Spring Integration test working to retrieve messages from a JMS queue hosted by HornetQ on JBoss EAP (version 6.4.0.GA running on Windows 7 Pro) running in standalone mode (standalone.bat -c standalone-full.xml).

The JMS test ran fine when using a simple Java JMS program; now, I'm trying to add Spring Integration and I get the following error:

18:29:03,197 ERROR [org.springframework.jms.listener.DefaultMessageListenerContainer]
(org.springframework.jms.listener.DefaultMessageListenerContainer#0-1) 
Could not refresh JMS Connection for destination 'anotherQueue' - 
retrying in 5000 ms. Cause: AOP configuration seems to be invalid: 
tried calling method [public abstract javax.jms.Connection javax.jms.ConnectionFactory.createConnection() 
throws javax.jms.JMSException] on target [HornetQQueue[anotherQueue]]; 
nested exception is java.lang.IllegalArgumentException: java.lang.ClassCastException@511504f4

The Spring config files are:

applicationContext-ordering-inbound-jms-spring-integration.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop=...

    <bean id="jndiTemplateBilling" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
            <props>
                <prop key="java.naming.factory.initial">org.jboss.as.naming.InitialContextFactory</prop>
                <prop key="java.naming.provider.url">remote://localhost:4447</prop>
            </props>
        </property>
    </bean>

    <bean id="jndiObjectFactoryBeanBilling" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref="jndiTemplateBilling" />

        <property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />
        <property name="lookupOnStartup" value="false" />
        <property name="proxyInterfaces">
            <list>
                <value>javax.jms.QueueConnectionFactory</value>
                <value>javax.jms.TopicConnectionFactory</value>
                <value>java.io.Externalizable</value>
            </list>
        </property>
    </bean>

    <bean id="jndiDestinationResolver"
        class="org.springframework.jms.support.destination.JndiDestinationResolver">
        <property name="jndiTemplate" ref="jndiTemplateBilling" />
        <property name="cache" value="true" />
    </bean>

    <int-jms:inbound-gateway
        request-destination-name="anotherQueue"
        request-channel="inboundOrderingBillingJms" 
        destination-resolver="jndiDestinationResolver"
        connection-factory="jndiObjectFactoryBeanBilling" />

    <int:channel id="inboundOrderingBillingJms" /> <!-- handled by OrderingBillingInboundEndpoint -->

    <context:component-scan base-package="com.att.ordering.endpoints.jms" />
    <context:annotation-config />
    <context:spring-configured />
    <int:annotation-config />

</beans>

and applicationContext-ordering-inbound-jms.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...">

    <context:annotation-config />
    <context:spring-configured />
    <int:annotation-config />

    <context:component-scan base-package="com.att.ordering.endpoints.jms"/>

</beans>

The ServiceActivator class:

package com.att.ordering.endpoints.jms;

    import javax.xml.bind.JAXBElement;

    import org.springframework.integration.annotation.ServiceActivator;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;

    @Component
    public class OrderingBillingInboundEndpoint
    {
        @ServiceActivator(inputChannel = "inboundOrderingBillingJms")
        //public void handleMessage(JAXBElement<String> accountNumber)
        public void handleMessage(String accountNumber)
        {
            System.out.println("In OrderingBillingInboundEndpoint.handleMessage - accountNumber=" + accountNumber);
        }
    }

I bootstrap spring with a WAR; WEB-INF/web.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>ordering-spring-bootstrap.war.context</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </context-param>

</web-app>

WEB-INF/classes/beanRefContext.xml is:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
    <bean id="ordering-spring-bootstrap.war.context"
        class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg>
            <list>
                <value>/applicationContext-ordering-inbound-jms-spring-integration.xml</value>
                <value>/applicationContext-ordering-inbound-jms.xml</value>
            </list>
        </constructor-arg>
    </bean>
</beans>

FOLLOWING ADDED AFTER ARTEM'S INITIAL REPLY

My JNDI name is java:jboss/exported/jms/queue/anotherQueue. It is bound to HornetQQueue[anotherQueue].

Following shows it in JBoss - note: there are 2 JNDI entries; I'm using the second one: enter image description here

This is correct - I was able to get a Java JMS program (without Spring Integration) working as follows:

final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, "remote://localhost:4447");
env.put(Context.SECURITY_PRINCIPAL, "appuser");
env.put(Context.SECURITY_CREDENTIALS, "appuser1!");
context = new InitialContext(env);

// JNDI name in JBoss is: java:jboss/exported/jms/queue/anotherQueue
connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
destination = (Destination) context.lookup("jms/queue/anotherQueue");
connection = connectionFactory.createConnection("appuser", "appuser1!");
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(destination);
consumer.setMessageListener(new MyListener());
connection.start();

I am now trying to get the same simple example working using Spring Integration.

Questions:

(A) Where should I put the user id and password?

(B) Is the following correct? If not, what should it exactly be?

<bean id="jndiTemplateBilling" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">org.jboss.as.naming.InitialContextFactory</prop>
            <prop key="java.naming.provider.url">remote://localhost:4447</prop>
        </props>
    </property>
</bean>

(C) How should I change the following? I removed the proxyInterfaces; what else should change? I don't know how to use jee:jndi-lookup

<bean id="jndiObjectFactoryBeanBilling" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref="jndiTemplateBilling" />
        <property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />
        <property name="lookupOnStartup" value="false" />
    </bean>

(D) Does the following stay the same?

<bean id="jndiDestinationResolver"
        class="org.springframework.jms.support.destination.JndiDestinationResolver">
        <property name="jndiTemplate" ref="jndiTemplateBilling" />
        <property name="cache" value="true" />
    </bean>

(E) Does the following change?

<int-jms:inbound-gateway
        request-destination-name="anotherQueue"
        request-channel="inboundOrderingBillingJms" 
        destination-resolver="jndiDestinationResolver"
        connection-factory="jndiObjectFactoryBeanBilling" />
1

1 Answers

0
votes

Looks like you are wrong with your jndiObjectFactoryBeanBilling bean definition. It is for

<property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />

what is confirmed by the logs:

on target [HornetQQueue[anotherQueue]];

But it really must be for the javax.jms.ConnectionFactory:

connection-factory="jndiObjectFactoryBeanBilling" 

So, just try to change the JNDI name to the correct one.

From other side I have never used all those proxyInterfaces options for JBOSS JNDI resources. They work well as is, e.g.:

<jee:jndi-lookup id="jndiMqConnectionFactory" jndi-name="${mqConnectionFactory}"/>

<jee:jndi-lookup id="auditQueue" jndi-name="queue/AuditQueue"/>