Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null pointer exception for autowired class method

I am new to Apache Camel and trying to build an api. It has three classes.

Class A - this is for reading application.properties file as below

@Configuration
@ConfigurationProperties(prefix="api")
public class A{

private String username;

public String getUsername(){
    return username
}

Class B - Apache Camel Route.

Class C - Bean class where class A is autowired.

@Component
public class b extends RouteBuilder{
    @Autowired
    ClassC customC;

    public void configure{
        from("direct:start")
            .bean(customC)
            .to("log:first-timer")
    }
}

@Component
class C{
    @Autowired
    ClassA config;

    String username=config.getUsername();
}

Whenever IDE executes the api, it throws Null pointer exception in the line String username=config.getUsername(); .I have verified that spring boot is able to load application.properties.

I am not sure why calling method of autowired class is throwing null pointer exception.

like image 962
user15345826 Avatar asked Apr 09 '26 00:04

user15345826


1 Answers

The problem is in your C class.

@Component
class C{
    @Autowired
    A config;

    String username = config.gtUsername();
}

The sequence during Spring's initialization was like this:

  1. Create an instance of C
    (by calling new C())
    This constructor calls username = config.gtUsername() and fails with a NullPointerException because config is still null.
  2. Process the @Autowired
    (initialize your config property)
    But of course it doesn't get this far because the exception already happened in step 1.

You can fix this problem by removing the initialization of your username property from the constructor and instead put it into a separate method (let's call it init()) and annotate it with @PostConstruct. See also Spring PostConstruct and PreDestroy Annotations.

@Component
class C{
    @Autowired
    A config;

    String username;
    
    @PostConstruct
    void init() {
        username = config.getUsername();
    }
}

Then the sequence during Spring's initialition will be like this:

  1. Create a C instance
    (by calling new C())
  2. Process the @Autowired.
    (This initializes your config property)
  3. Call the @PostConstruct-annotated method.
    (This initializes your username property using the already initialized config property)

Another even simpler way to fix your problem, is to use constructor injection (as @Ferry already suggested in his comment):

Instead of relying on the implicit default constructor, you provide an @Autowired-annotated constructor which can take an A config parameter. Furthermore: By doing so, you will not need the A config property anymore.

@Component
class C{ 
    String username;

    @Autowired
    C(A config) {
        username = config.getUsername();
    }
}

Then the sequence during Spring's initialization will be like this:

  1. Process the @Autowired
    (create an instance of C by calling new C(config) where config is an A instance previously created during the autowiring process)
    This initializes your username property using the config received by the constructor.
like image 71
Thomas Fritsch Avatar answered Apr 10 '26 14:04

Thomas Fritsch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!