TAGS :Viewed: 8 - Published at: a few seconds ago

[ Service Class not being instantiated during @Autowire call ]

I am attempting to use a @Service class in my messaging application, however the class is not instantiated via @Autowire when I try from a generic class. It is only instantiated when I use the Controller.

Here is my controller:

    package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import hello.Application;

@Controller
public class HelloController {


    @Autowired
    private MessageSender sender;

    @RequestMapping(value="/", method=RequestMethod.GET)
    public String index() {
        return "index";
    }

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        System.out.println("Sending message...");
        beginRoute(message.getName());
        sender.greet("thunder");
        return new Greeting("Hello, " + message.getName() + "!");
    }

    public void beginRoute(String message) {
        Application.startBody(message);
    }
}

The above call to sender.greet is successful.

Here is the other class I attempt to use the service in:

package com.routing.integration;

import hello.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;


@Component
public class modifier {

    @Autowired
    private MessageSender sender;

    public boolean adder(String words) throws Exception {

        sender.greet(words);
    }
}

When I attempt to call sender.greet as above, I get a NullPointerException and when debugging, I find that sender is null at the time of the call to sender.greet. Is the service class not instantiating in modifier?

Finally, here is the MessageSender service class:

@Service
public class MessageSender {

    @Autowired
    private SimpMessagingTemplate template;


    @RequestMapping(value="/hello", method=RequestMethod.POST)
    public void greet(String greeting) {
        Greeting text = new  Greeting("Goodbye, " + greeting + "!");
        this.template.convertAndSend("/topic/greetings", text);
    }

}

How can I ensure that @Autowire instantiates the MessageSender in every class?

EDIT

Here is where the call to modifier is made. It is made from a camel route:

    <?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:camel="http://camel.apache.org/schema/spring"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:core="http://activemq.apache.org/schema/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context     http://www.springframework.org/schema/context/spring-context.xsd
    http://camel.apache.org/schema/osgi http://camel.apache.org/schema/osgi/camel-osgi.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core">

<camelContext xmlns="http://camel.apache.org/schema/spring">

<route>
        <from uri="activemq:queue:testQSource"/>

        <choice>
            <when>
                <method ref="securityBean"/>
                <log message="Routing message from testQSource to testQDestination queue with data ${body}"/>

                <to uri="activemq:queue:testQDestination"/>
                <to uri="activationBean"/>
                <to uri="accountVerificationBean"/>
                <to uri="billingCheckingBean"/>
                <to uri="deviceConnectorBean"/>
                <to uri="deviceActivatorBean"/>
                <log message="Account activated: ${body}"/>
            </when>
            <otherwise>
                <log message="message went to stomp: ${body}"/>
            </otherwise>
        </choice>
</route>
</camelContext>


<camel:camelContext id="camel-client">
    <camel:template id="camelTemplate" />
</camel:camelContext>

<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="browserBean" class="hello.HelloController"/>
<bean id="securityBean" class="com.routing.integration.modifier"/>
<bean id="activationBean" class="com.routing.integration.ActionApp"/>
<bean id="accountVerificationBean" class="com.routing.integration.AccountVerifier"/>
<bean id="billingCheckingBean" class="com.routing.integration.BillingChecker"/>
<bean id="deviceConnectorBean" class="com.routing.integration.DeviceConnector"/>
<bean id="deviceActivatorBean" class="com.routing.integration.DeviceActivator"/>

</beans>

Here is the stacktrace:

Stacktrace
---------------------------------------------------------------------------------------    ------------------------------------------------
java.lang.NullPointerException
at com.routing.integration.modifier.adder(modifier.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:407)
at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:278)
at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:251)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:166)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67)
at     org.apache.camel.language.bean.BeanExpression$InvokeProcessor.process(BeanExpression.java:1    89)
at org.apache.camel.language.bean.BeanExpression.evaluate(BeanExpression.java:123)
at org.apache.camel.language.bean.BeanExpression.matches(BeanExpression.java:137)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:    72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:87)
at     org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja    va:103)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(Abstract    MessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMe    ssageListenerContainer.java:500)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(Abstrac    tMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecut    e(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(    AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.run(DefaultMessageListenerContainer.java:991)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
WARN : org.apache.camel.component.jms.EndpointMessageListener - Execution of JMS     message     listener failed. Caused by: [org.apache.camel.RuntimeCamelException -         java.lang.NullPointerException]
org.apache.camel.RuntimeCamelException: java.lang.NullPointerException
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1363)
at     org.apache.camel.component.jms.EndpointMessageListener$EndpointMessageListenerAsyncCallback    .done(EndpointMessageListener.java:186)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja    va:107)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(Abstract    MessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMe    ssageListenerContainer.java:500)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(Abstrac    tMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecut    e(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(    AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoke    r.run(DefaultMessageListenerContainer.java:991)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at com.routing.integration.modifier.adder(modifier.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:407)
at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:278)
at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:251)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:166)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67)
at org.apache.camel.language.bean.BeanExpression$InvokeProcessor.process(BeanExpression.java:1    89)
at org.apache.camel.language.bean.BeanExpression.evaluate(BeanExpression.java:123)
at org.apache.camel.language.bean.BeanExpression.matches(BeanExpression.java:137)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:    72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:87)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.ja    va:103)
... 11 more

EDIT 2

Here is my main class that calls ComponentScan:

package hello;

import org.apache.camel.ProducerTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = {"hello", "com.routing.integration"})
public class Application {
    static ApplicationContext context = null;
    static ProducerTemplate camelTemplate = null;
    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);
        System.out.println("----------------------\nSpringBootComplete\n----------------------");
        startBody("startup");
    }

    public static void startBody(String message) {
        if (context == null) {
            context = new ClassPathXmlApplicationContext("camelspring.xml");
            camelTemplate = context.getBean("camelTemplate", ProducerTemplate.class);
        }
        if (message != "startup"){
            camelTemplate.sendBody("activemq:queue:testQSource", message);
        }
    }           
}

Answer 1


Your Application class should look like this:

@Configuration
@ComponentScan(basePackages = {"hello", "com.routing.integration"})
@EnableAutoConfiguration
@ImportResource("classpath:camel.xml")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Where camel.xml is the xml configuration file that contains your camel definitions. If you need any of the beans defined in the xml configuration, like camelTemplate in your xml, you can get a reference of it like this, for example:

package hello;

import javax.annotation.Resource;

import org.apache.camel.ProducerTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Resource(name="camelTemplate")
    private ProducerTemplate template;

    @RequestMapping("/")
    String home() {
        System.out.println(template);
        return "Hello World!";
    }
}

As I said in the comments, don't create an app context manually. Register the beans you want with @Component, @Service, @Configuration and @Bean etc. If you need xml configuration that is difficult to reproduce in Java code, use @ImportResource.

In the xml config file you have, you can replace browserBean bean with a @Controller annotation placed on the hello.HelloController class.

Your activemq bean could translate to something like this in Java Config:

@Configuration
public class Config {

    @Bean
    public ActiveMQComponent activemq() {
        ActiveMQComponent comp = new ActiveMQComponent();
        comp.setBrokerUrl("tcp://localhost:61616");

        return comp;
    }
}