我只想尝试自动装配下面的rabbitmq消费者:
@Component
public class SmsQueueConsumer {
//NOT SURE IF/ WHY THE CONFIG IS NULL...
@Autowired
Configuration config;
public SmsQueueConsumer() throws Exception {
//THIS IS WHERE THE NULL POINTER OCCURS (stack trace refers to line 54)
String rabbitMqHost = config.getString("rabbitMq.hostName");
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(rabbitMqHost);
com.rabbitmq.client.Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queueName, false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
//... handle deliv logic
};
}
}
上面的类在服务实现类中自动装配:
@Service
public class ServiceImpl implements Service {
//HERE IS THE ABOVE CLASS BEING AUTOWIRED
@Autowired(required=true)
private SmsQueueConsumer queueConsumer;
//NOTE THAT I ALSO AUTOWIRE THE CONFIG HERE TOO!
@Autowired(required=true)
private Configuration config;
@Override
public ServiceResponse doStuff(MyCoObj obj) throws Exception
{
//...
queueSmsMessage(simpleMessage);
//...
}
private void queueSmsMessage(SimpleSmsMessage simpleSmsMessage) {
String rabbitMqHostName = config.getString("rabbitMq.hostName");
String smsQueueName = config.getString("auctions.sms.queue.name");
Gson gson = new Gson();
String smsMessageJson = gson.toJson(simpleSmsMessage);
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(rabbitMqHostName);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(smsQueueName, false, false, false, null);
channel.basicPublish("", smsQueueName, null, smsMessageJson.getBytes());
channel.close();
connection.close();
} catch (Exception e) {
logger.warn("sms message could not be queued. TODO retry"); // TODO
}
}
}
我已经设置了一个testApplicationContext来包含所需的bean
<?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="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-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/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<context:component-scan base-package="com.myCompany.basePackageToScan" />
<context:annotation-config />
<bean id="config" class="org.apache.commons.configuration.PropertiesConfiguration">
<constructor-arg value = "some.properties"/>
</bean>
<bean id="smsQueueConsumer" class="com.myCompany.basePackageToScSmsQueueConsumer" />
</beans>
当我运行测试时,我得到以下堆栈跟踪:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'smsQueueConsumer' defined in class path resource [testApplicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.myCompany.basePackageToScan.SmsQueueConsumer]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1101)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.myCompany.basePackageToScan.SmsQueueConsumer]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1094)
... 43 more
Caused by: java.lang.NullPointerException
at com.myCompany.basePackageToScan.SmsQueueConsumer.<init>(SmsQueueConsumer.java:54)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 45 more
这与我在Tomcat 7中运行应用程序时获得的堆栈跟踪相同。 如果我需要提供任何其他详细信息,请与我们联系。
EDIT --- 我认为这个问题可能与RabbitMq启动消费者的方式有关......它就在那里等待消息。也许春天不能自动上课这个课程?
编辑2 --- 删除配置自动装配并在SmsQueueConsumer中为rabbitMqHost添加硬编码设置...现在为什么不能从配置中获取值?
答案 0 :(得分:0)
好吧,这有点hacky感觉,但我所做的不是使用默认构造函数,而是将Configuration类添加为构造函数的参数。
@Component
public class SmsQueueConsumer {
//I removed the autowiring of the config
//@Autowired
//Configuration config;
//and placed the config as an arg to the constructor
public SmsQueueConsumer(Configuration config) throws Exception {
//THIS IS WHERE THE NULL POINTER OCCURS (stack trace refers to line 54)
String rabbitMqHost = config.getString("rabbitMq.hostName");
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(rabbitMqHost);
com.rabbitmq.client.Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queueName, false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
//... handle deliv logic
};
}
}
然后我在applicationContext.xml中创建了一个注入配置的bean。
<bean id="config" class="org.apache.commons.configuration.PropertiesConfiguration">
<constructor-arg value = "some.properties"/>
</bean>
<bean id="bidsSmsQueueConsumer" class="com.myCompany.basePackage.SmsQueueConsumer">
<constructor-arg ref = "config" />
</bean>