Search code examples
javaspringspring-mvcactivemq-classicjmstemplate

Unable to send JMS message to activemq Queue using Spring's JmsTemplate


I am a Developer returning to Java after about 5 years of .NET experience. Although I have knowledge of the MVC framework, I am entirely new to Spring MVC and the spring framework.

I have an assignment where I intended saving entities on an activemq JMS queue. I decided to try it out with a simple TextMessage first before sending a more complex object. Each time I attempt the send from a Controller mapped to an input button control on the view, I get a java.lang.NullPointerException in Tomcat. It does not show me much info other than that. It only shows me that it's source is from this line of code in the ApiMessageSender class.

jmsTemplate.send(new MessageCreator(){  

        @Override  
        public Message createMessage(Session session) throws JMSException {  
            return session.createTextMessage(message);  
        }  
    });  

The implementation within the spring web mvc web application is made up of three classes. 1) ApiMessageSender.java

import javax.jms.*;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.jms.core.JmsTemplate;  
import org.springframework.jms.core.MessageCreator;  
import org.springframework.stereotype.Component;  

@Component("messageSender")  
public class ApiMessageSender {  
@Autowired  
private JmsTemplate jmsTemplate;  
public void sendMessage(final String message){  
    jmsTemplate.send(new MessageCreator(){  

        @Override  
        public Message createMessage(Session session) throws JMSException {  
            return session.createTextMessage(message);  
        }  
    });  
}  
}  

2) WebAppConfig.java where the Spring IoC plumbing is done. This class is in lieu of the ApplicationContext.xml files, which is not used at all in this project. The Queue name was manually created from the ActiveMQ admin web interface prior to executing the application.

@Bean
    public org.apache.activemq.ActiveMQConnectionFactory connectionFactory() {
        org.apache.activemq.ActiveMQConnectionFactory connectionFactory = new org.apache.activemq.ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL("tcp://localhost:61616");
        return connectionFactory;
    }

    @Bean
    public org.springframework.jms.core.JmsTemplate jmsTemplate() {
        org.springframework.jms.core.JmsTemplate jmsTemplate = new org.springframework.jms.core.JmsTemplate(connectionFactory());
        jmsTemplate.setDefaultDestinationName("apiqueue");
        return jmsTemplate;
    }

3) ApiController.java

This action method in the controller that gets called when a button is clicked on the View. I have commented the particular code snippet out, so that I can proceed with other requirements.

@RequestMapping(value="/create", method=RequestMethod.POST)
    public ModelAndView createNewApi(@ModelAttribute @Valid Api api,
            BindingResult result,
            final RedirectAttributes redirectAttributes) {

        if (result.hasErrors())
            return new ModelAndView("api-new");

        ModelAndView mav = new ModelAndView();
        String message = "New api "+api.getApiKey()+" was successfully created.";

        apiService.create(api);

        //Send object to Queue.
        /*GenericXmlApplicationContext ctx=new GenericXmlApplicationContext();  
        ctx.load("classpath:applicationContext.xml");  
        ctx.refresh();*/  

       /* ApiMessageSender sender = new ApiMessageSender();  
        sender.sendMessage("hello jms3");*/
        //ctx.close();
        //End of messaging task. The message should be successfully in the JMS Queue.

        mav.setViewName("redirect:/api/list.html");

        redirectAttributes.addFlashAttribute("message", message);   
        return mav;     
    }

What could be the problem here? Why am I getting a java.lang.NullPointerException here? How can I get this working? Thank you very much.


Solution

  • Without the full stacktrace it's hard to completely tell you for sure but based on the commented out code, your problem is probably that you are using "ApiMessageSender sender = new ApiMessageSender();" to instantiate your ApiMessageSender. By doing this your jmsTemplate will never be autowired since you are not using Spring to instantiate your beans. So my best guess (without the stack trace being posted) is that when your code calls jmsTemplate.send it gets a null pointer because jmsTemplate was never set.

    The proper way to do this would be to use the SpringDispatcherServlet to set up your Spring MVC context and to initiate your beans. Then you could autowire your ApiMessageSender into your controller class instead of calling "new ApiMessageSender()"

    Take a look at the documentation here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

    You should not need to reference the application context directly in your controller method. Everything should be set up with Spring by your web.xml file.