-1

I am getting a null pointer exception while auto wiring one of my classes.

I have tried using different annotations such as @Component and @ComponentScan

public class ClassA {
    public final String str = "String";

    public ClassA(){
        System.out.println("Class A initiated");
    }
}


public class ClassB {

    @Autowired
    public ClassA classA;

    public ClassB(){
     System.out.println(classA.str);
    }


}

@Configuration
public class Config {

    @Bean
    public ClassA classA(){
        return new ClassA();
    }

    @Bean
    public ClassB classB(){
        return new ClassB();
    }
}

Stacktrace :

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'classB' defined in class path resource [com/test/demo/Config.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.test.demo.ClassB]: Factory method 'classB' threw exception; nested exception is java.lang.NullPointerException
Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39
techgeek99
  • 17
  • 1
  • 5
  • 1
    How could a field that is not initialized anywhere be not null inside the constructor of the class? Spring can't autowire a field of an object if the object hasn't been constructed yet. – JB Nizet Oct 09 '19 at 21:14

4 Answers4

3

Instead of using @Autowired. Inject ClassA through ClassB's constructor.

public class ClassB {
private final ClassA classA;

public ClassB(ClassA classA){
     this.classA = classA;
     System.out.println(classA.str);
}

Then change ClassB's Bean configuration to take ClassA.

Steven Diamante
  • 207
  • 2
  • 7
2

The constructor is run before Spring injects auto-wired fields so the classA field is still null.

Move your code outside the constructor (and field initializers) and you should see proper values.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
1

You could use constructor injection instead of field injection if you want the value to be extracted in the constructor itself like :

public class ClassB {
    public ClassA classA;

    @Autowired
    public ClassB(ClassA classA){
     this.classA = classA;
     System.out.println(classA.str);
    }
}

As of Spring 4.3, classes with a single constructor can omit the @Autowired annotation.Spring will encounter our 'ClassB' class while doing a package scan and will initialize its instance by calling the @Autowired annotated constructor.

In your code , the autowiring happens after the no args constructor is invoked.So when you try to access the 'str' using classA object it causes null pointer exception as classA is yet to be autowired.

Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39
-1

Try place @Component or @Service on ClassA

@Component
public class ClassA {
    public final String str = "String";

    public ClassA(){
        System.out.println("Class A initiated");
    }
}

This happened because of class ClassA is not a Spring Bean.

João Zarate
  • 362
  • 1
  • 12