Junjie
Junjie

Reputation: 1175

How to use spring 3.X annotation without any .xml configuration

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

Answers (2)

Roman Vottner
Roman Vottner

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

Avi
Avi

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

Related Questions