3

I have a bean mongoService which looks like as

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <context:property-placeholder location="file:///storage//local.properties"/>
    <bean id="mongoService" class="com.business.persist.MongoService">
    <constructor-arg value="${host}"/>
    <constructor-arg value="${port}"/>
    <constructor-arg value="${database}"/>
    </bean>
</beans>   
  • I need to include this bean in a separate project so I created a jar for this project and added as maven dependency which looks like

        <dependency>
            <groupId>com.project</groupId>
            <artifactId>business</artifactId>
            <version>master-SNAPSHOT</version>
        </dependency>   
    
  • Now in the file where I need to inject this field, I do the following

public class DocumentSaver implements IDocumentSaver {
    @Resource
    private MongoService mongoService;

    public boolean addDocument(Document doc) {
       // do other things

       // add document to mongo   
       mongoService.putDocument(document);

       return true;
    }
}  

and then I run the test as follows

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/com/wireup.xml")
public class DocumentSaverTest extends DocumentCase {

    @Test
    public void loadAndSave() {
             DocumentSaver saver = new DocumentSaver();
             Document doc = new Document();
             // fill the doc
             saver.addDocument(doc);
        }
}  

I see the NullPointerException when I run this on the like saver.addDocument(doc);

Please tell me what is that I am doing incorrectly

Thank you

daydreamer
  • 87,243
  • 191
  • 450
  • 722

5 Answers5

2

You should not create "DocumentSaver" with NEW operator as follows, get that from Spring Application Context.

DocumentSaver saver = new DocumentSaver();

If you use NEW operation , Spring would not inject the dependent objects.

1

My hunch is that your DocumentSaver is not managed by spring, therefore the MongoService is not autowired. You could either define DocumentSaver as a spring bean in the spring xml file + wire the MongoService reference into it, or annotate it (for example as a @Repository or @Component) and then use component-scan in the xml file.

Secondly, it seems that you're creating DocumentSaver object through the new operator. The bean should have been fetched from spring context to have the MongoService autowired. Or another option if you dont want DocumentSaver to be a spring bean is to use @Configurable in your DocumentSaver which makes use of aspect weaving.

Bertie
  • 17,277
  • 45
  • 129
  • 182
1
  1. Annotate your Saver with @Component. Alternative here would declare this as another regular Bean on your XML file.
  2. @Autowired your MongoService;
  3. @Autowired your DocumentSaver to saver on your test class.

Edited classes follows.

Your component would be like this:

@Component
public class DocumentSaver implements IDocumentSaver {

    @Autowired
    private MongoService mongoService;

    public boolean addDocument(Document doc) {
        // do other things

        // add document to mongo   
        mongoService.putDocument(document);

        return true;
    }
}  

and your test to be like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/com/wireup.xml")
public class DocumentSaverTest extends DocumentCase {

    @Autowired
    DocumentSaver saver;

    @Test
    public void loadAndSave() {
        Document doc = new Document();
        // fill the doc
        saver.addDocument(doc);
    }
}  
Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
1

If you instanciate your DocumentSaver with a new, you do not put it into the Spring context. So Spring does not know it and injection is not done.

You should let it instanciate by Spring if you want to have a MongoService into it.

Add in your wireup.xml file :

<bean id="documentSaver" class="com....DocumentSaver" />

Then inject this documentSaver into your test :

@Autowired
private DocumentSaver documentSaver;

Your naming convention is bad.

Your DocumentSaver class seems to be a DAO (because it's purpose is to persist a Document). Thus, annotate it with @Repository and name it DocumentSaverDAO.

Combine my answer and Spaeth's one and it will work and be well packaged.

Jean-Philippe Briend
  • 3,455
  • 29
  • 41
1

DocumentSaver should be managed by Spring (currently, it is not, since you create it by new), or weaved, so that dependencies, such as MongoService are injected. See this answer for more details about dependency injection into objects created using new.

Community
  • 1
  • 1
omnomnom
  • 8,911
  • 4
  • 41
  • 50