Reputation: 1175
I'm new to Spring and I don't like to use .xml as the spring configuration. So I want to use only annotation. Following is my test code, it works well without spring, but if I use DI and add annotation "@Resource", I get NullPointException, could anyone help with it, thanks a lot.
I have imported related jar of spring already. It's a producer-consumer case, and I want to inject the resource-pool to producer and consumer.
Producer.java
import javax.annotation.Resource;
public class Producer implements Runnable{
@Resource
private ResourcePool qs;
@Override
public void run() {
while (true) {
for(int i = 0;i < Integer.MAX_VALUE; i++) {
try {
qs.produce(i);
System.out.println("Add index = " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Consumer.java
import javax.annotation.Resource;
public class Consumer implements Runnable {
@Resource
private ResourcePool qs;
@Override
public void run() {
while(true) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("Remove index = " + qs.comsume());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ResourcePool.java
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ResourcePool {
private BlockingQueue<Integer> aBlockingQueue = new ArrayBlockingQueue<Integer>(11);
public void produce(Integer ins) throws InterruptedException{
aBlockingQueue.put(ins);
}
public int comsume() throws InterruptedException{
return aBlockingQueue.take();
}
}
The main function
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPC {
public static void main(String[] args){
ExecutorService aExecutor = Executors.newFixedThreadPool(2);
Producer productor = new Producer();
Consumer consumer = new Consumer();
aExecutor.execute(productor);
aExecutor.execute(consumer);
}
}
Exception message:
Exception in thread "pool-1-thread-2" java.lang.NullPointerException at testbq.Consumer.run(Consumer.java:14) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Exception in thread "pool-1-thread-1" java.lang.NullPointerException at testbq.Producer.run(Producer.java:14) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
Thanks
Upvotes: 3
Views: 7486
Reputation: 12839
On searching "XML-less Spring configuration" or Java-based Spring configuration you should have probably figured it out yourself within a couple of minutes.
You haven't defined any bean-creatiion method which is hosted by a class that is annotated with @Configuration
- so Spring is able to know what you actually want to inject.
@Configuration
// optional @ComponentScan(basePackages = {"name.your.package.here"}
public class AppConfig
{
@Bean // or @Bean(name = "nameOfYourBean")
public ResourcePool getResourcePool()
{
return new ResourcePool();
}
}
Within your main method you should then create a Spring context and load your AppConfig in to your context:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfic.class);
HTH
Upvotes: 4
Reputation: 21858
You can't use new Producer()
because it will create a new Producer
and not use spring at all. You need to load the application context as an annotation context and load Producer
from the context:
public class TestPC {
public static void main(String[] args){
ExecutorService aExecutor = Executors.newFixedThreadPool(2);
ApplicationContext ctx =
new AnnotationConfigApplicationContext("your.package.com");
Producer producer = ctx.getBean(Producer.class);
Consumer consumer = ctx.getBean(Consumer.class);
aExecutor.execute(productor);
aExecutor.execute(consumer);
}
}
You have to replace your.package.com
with the base package where Producer
and Consumer
classes reside.
Upvotes: 2