JmsTemplate中的空指针异常?

时间:2014-01-18 05:30:40

标签: java spring jms spring-jms

我尝试运行简单的spring jmstemplate示例。这里是发送者的源代码,

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class MessageSender {

    @Autowired
    private JmsTemplate jmsTemplate;

    public void setJmsTemplate(JmsTemplate jmsTemplate)
    {
        this.jmsTemplate = jmsTemplate;
    }
    public void sendMessage()
    {
        jmsTemplate.send(new MessageCreator() {
            public Message createMessage(Session session)
            {
                TextMessage message = null;
                try
                {
                    message = session.createTextMessage();
                    message.setStringProperty("text", "Hello World");
                }
                catch (JMSException e)
                {
                    e.printStackTrace();
                }
                return message;
        }
    });
    }
}

这是用于将spring与jmstemplate集成的配置文件。

<?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:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/tx 
                        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd                        
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.0.xsd
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <!-- Spring AOP -->
    <context:component-scan base-package="com.test"/>
    <aop:aspectj-autoproxy />
    <bean id="messageListener" class="com.test.QueuereceiverDB" />   

    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
            <props>
                <prop key="java.naming.provider.url">jnp://localhost:1099</prop>
                <prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
                <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
            </props>
        </property>
    </bean>

    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate">
            <ref bean="jndiTemplate" />
        </property>
        <property name="jndiName">
            <value>ConnectionFactory</value>
        </property>
    </bean>

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

    <bean id="QueueTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory">
            <ref bean="queueConnectionFactory" />
        </property>
        <property name="destinationResolver">
            <ref bean="jmsDestinationResolver" />
        </property>
    </bean>
    <bean id="jmsSender" class="com.test.MessageSender">
        <property name="jmsTemplate"> <ref bean="QueueTemplate" />
        </property>

    </bean>

    <bean id="Queue" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate"> <ref bean="jndiTemplate" />
        </property>
        <property name="jndiName">
            <value>queue/MyQueue</value>
        </property>
    </bean>
    <!-- JmsTemplate Definition -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="queueConnectionFactory" />
         <property name="defaultDestination" ref="Queue" /> 
    </bean>
    <bean id="jmscontainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="concurrentConsumers" value="5" />
        <property name="connectionFactory" ref="queueConnectionFactory" />
        <property name="destination" ref="Queue" />
        <property name="messageListener" ref="messageListener" />
    </bean> 

</beans>

如果我运行下面的例子是相应的stacktrace

SEVERE [com.sun.jersey.spi.container.ContainerResponse] The RuntimeException could not be mapped to a response, re-throwing to the HTTP container: java.lang.NullPointerException
    at com.test.MessageSender.sendMessage(MessageSender.java:30) [:]
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149) [:]
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) [:3.1.0.RELEASE]
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:50) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50) [:3.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) [:3.1.0.RELEASE]
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80) [:3.1.0.RELEASE]

在我调试代码后,我发现问题所在, jmsTemplate.send(new MessageCreator(){执行此行时会显示Null指针。

我认为我们需要从xml文件初始化jmstemplate。但是我不知道如何实现这个目标? 请帮助我。

我在以下文件中配置了队列,该文件将放在jboss / server / default / server文件夹中 mdb-hornetq-xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="urn:hornetq"
    xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd" >

    <queue name="MyQueue2" >
        <entry name="/queue/MyQueue" />
    </queue>

</configuration> 

1 个答案:

答案 0 :(得分:0)

我觉得奇怪的是你宣布了两个JmsTemplate bean。我有一个更简单的配置工作。涉及两个JNDI名称,一个是目标(队列)名称,另一个是连接工厂名称。

假设您的队列是 MyQueue ,您的连接工厂是 MyCF 。要发送消息,您需要声明两个spring bean:

<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="MyCF"/>
    <property name="lookupOnStartup" value="false"/>
    <property name="cache" value="true"/>
    <property name="proxyInterface" value="javax.jms.ConnectionFactory"/>
</bean>

<bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
        <ref bean="jmsConnectionFactory"/>
    </property>
    <property name="defaultDestinationName" value="MyQueue" /> 
</bean> 

发件人类中的源代码将包含:

@Autowired
private JmsTemplate jmsTemplate;

private void sendTextMessage(final String message)
    MessageCreator messageCreator = new MessageCreator() {
        @Override
        public Message createMessage(Session session) throws JMSException {
            return session.createTextMessage(message);
        }
    };
    jmsTemplate.send(messageCreator);
}

缺少的是que连接工厂和队列的HornetQ配置。该配置定义了JNDI名称。就我而言,HornetQ运行嵌入了JBoss Application Server。因此,我在JBoss AS配置中配置了连接工厂和队列(例如,在standalone.xml文件中)。以下是片段:

<pooled-connection-factory name="hornetq-local">
    <transaction mode="local"/>
    <connectors>
        <connector-ref connector-name="in-vm"/>
    </connectors>
    <entries>
        <entry name="java:/MyCF"/>
    </entries>
</pooled-connection-factory>

<jms-destinations>
    <jms-queue name="MyQueue">
        <entry name="java:jboss/queues/a/b/SomeQueue"/>
        <durable>true</durable>
    </jms-queue>
</jms-destinations>

我相信你在独立模式下使用HornetQ。应该很容易将这些设置映射到工厂和队列配置。