0
votes

I'm trying to inject a bean in a simple java project but I'm getting a NullPointerException for ProductInformationServiceImpl.

These are the classes I'm using:

AppConfig.java (Spring configuration class)

package com.test.testing.config;

@Configuration
@ComponentScan(basePackages = "com.test")
public class AppConfig {
}

TestService.java interface:

package com.test.testing.service;

public interface TestService {
    String doIt();
}

TestService.java implementation:

package com.test.testing.service;

@Service
public class TestServiceImpl implements TestService {
    public String doIt() {
        return "you did it!";
    }
}

Main class:

package com.test.testing;

public class App {
    public static void main( String[] args ){
        Test w = new Test();
        System.out.println(w.getTestService().doIt());
    }
}

class Test {
    @Autowired
    private TestService testServiceImpl;

    public TestService getTestService() {
        return testServiceImpl;
    }

    public void setTestService(TestService testServiceImpl) {
        this.testServiceImpl = testServiceImpl;
    }
}

I did some tests retrieving the bean using:

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TestService app = (TestService)context.getBean("testServiceImpl");

But that is something I'd like to avoid.

1
Autowired will work only if you get bean from context. You can use JUnit with @RunWith(SpringJUnit4ClassRunner.class) and @ContextConfiguration for testing, it is a right way.user1516873
Try to use a Debugger to see which beans are in your context.Jens
Sorry, it's not a @Test what I'm trying to achieve. This is a simple standalone application. Using ´´context´´ is what I'm trying to avoid, I'd just like to do the Autowiring..Tomarto
You still need a context, without an ApplicationContext nothing will happen (just like now). You need a spring container.M. Deinum

1 Answers

0
votes

I found that the general suggestion id to use constructor injection instead of field injection, that helps you a lot with the testability.

@Component
@RequiredArgsConstructor(onConstructor=@__(@Autowired))
public class Animal {
    private final Sound sound;
    public String makeSound() {
        return sound.make();
    }
}

In the test you can pass the mocks or whatever in the constructor, while when you run your application the constructor injection will be taken care of automatically. Here's a tiny test app which a showcase of the constructor injection.