1

I'm learning Spring and I'm having some problems trying to set up a relatively basic Spring project. I'm creating an application to simply read from a database, but I'm having problems with Autowiring, or lack thereof. My GetCustomerEvent class is throwing a null pointer exception in the GetCustomers() method, as the CustomerService variable hasn't been initialised. Can someone point me in the right direction here?

Application.class

package org.ben.test.main;
@Configuration
@ComponentScan(basePackages={"org.ben.test.persistence", "org.ben.test.main"})
public class Application {

    @Bean
    public CustomerService customerService() {
        return new CustomerService();
    }

    @Bean 
    public DataSource getDataSource() {
        DriverManagerDataSource dmds = new DriverManagerDataSource();
        dmds.setDriverClassName("org.postgresql.Driver");
        dmds.setUrl("jdbc:postgresql://localhost:5432/Customers");
        dmds.setUsername("postgres");
        dmds.setPassword("postgres");
        return dmds;

    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        DataSource ds = getDataSource();
        JdbcTemplate jdbc = new JdbcTemplate(ds);
        return jdbc;
    }

    public static void main(String[] args) {
        GetCustomerEvent ev = new GetCustomerEvent();
        ev.GetCustomers();
    }
}

CustomerService.class

package org.ben.test.persistence;

@Component
public class CustomerService {

    @Autowired JdbcTemplate jdbcTemplate;

    public CustomerService() {

    }

    public void getCustomers() {
        jdbcTemplate.query("SELECT * FROM Customers", new RowMapper() {
            @Override
            public Object mapRow(ResultSet arg0, int arg1) throws SQLException {
                System.out.println(arg0.getString("firstName"));
                return null;
            }
        });
    }

}

GetCustomerEvent.class

package org.ben.test.persistence;


@Component
public class GetCustomerEvent {

    @Autowired 
    CustomerService customerService;

    public GetCustomerEvent() {

    }

    public void GetCustomers() {
        customerService.getCustomers();
    }
}
Ben Harris
  • 1,734
  • 3
  • 15
  • 24

3 Answers3

2

Problem is with below line

GetCustomerEvent ev = new GetCustomerEvent();

You manually created instance using "new". Spring does not have idea about this object. See Why is my Spring @Autowired field null? for details.

Community
  • 1
  • 1
2

You are not initializing the Spring Container.

You need to create your context in order for it to work.

Evandro Pomatti
  • 13,341
  • 16
  • 97
  • 165
  • This is sometihng that has confused me a lot about Spring - I was under the assumption that when using Annotations you didn't need to set a context, and I've also read that context.getBean() manual bean finding was bad? There's so much information about Spring, both XML and Annotations, that it's hard to follow what I should be doing. – Ben Harris Aug 14 '14 at 01:02
  • The context needs to exist, either your access it directly or not. Usually when doing it under a Web Container a listener is used so all the injection is done without the need for you do create a context manually. About Annotations, they are just a "better" way of doing the same thing with XML. When you write `@Autowired` basically it is the same as telling Spring to do it with XML. About the `context.getBean()` manually it really depends on what problem you need to solve, but doing it once in your system wont do any harm as well, and the same for having one single XML component-scan. =) – Evandro Pomatti Aug 14 '14 at 01:19
  • Yeah - I think I understand where I've been going wrong. The tutorials I've done so far have been Spring Boot applications, which to my understanding doesn't need any context loading, whereas I'm doing a standard Spring application so the Context requires loading. – Ben Harris Aug 14 '14 at 01:25
  • @BenHarris Wait, Spring Boot works for not-web as well. You can still use it and it looks good, [check this tutorial](https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-simple). You can use something like this too (not tested) `new AnnotationConfigApplicationContext() ctx.register(Application .class) ctx.refresh()`. – Evandro Pomatti Aug 14 '14 at 01:36
0

You need to create the application context no matter if you are using xml or annotation based configuration. If your application is a web application, see this post Loading context in Spring using web.xml to load the application context

Once you have the application you can get the bean using context.getBean() method

Also, spring container does not manage the objects you create using new operator. In your example you need to autowire the GetCustomerEvent bean

@Autowired GetCustomerEvent getCustomerEvent;
//and call
getCustomerEvent.getCustomers();
Community
  • 1
  • 1
Naresh Vavilala
  • 598
  • 4
  • 14