2

I have just started learning Spring Boot. I have an error in my code which says

Error creating bean with name 'alien' defined in file [E:\Programing\Java\boot\Project1\target\classes\com\example\demo\Alien.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.Alien]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "com.example.demo.Laptop.compile()" because "this.laptop" is null

Below is my code

MainClass

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Project1Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context= SpringApplication.run(Project1Application.class, args);
        
        Alien a=context.getBean(Alien.class);
        a.show();
    }

}

Alien Class

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Alien {

    private int id;
    private String name;
    private String tech;
    @Autowired
    private Laptop laptop;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTech() {
        return tech;
    }
    public void setTech(String tech) {
        this.tech = tech;
    }
    
    public void show() {
        System.out.println("in show..........");
    }
    public Alien() {
        super();
        System.out.println("Object Created......");
        laptop.compile();
    }
    
}

Laptop class

package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class Laptop {

    private int lid;
    private String brand;
    
    @Override
    public String toString() {
        return "Laptop [lid=" + lid + ", brand=" + brand + "]";
    }
    public int getLid() {
        return lid;
    }
    public void setLid(int lid) {
        this.lid = lid;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    
    public void compile() {
        System.out.println("Compiling..");
    }
    
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Sharman Jeurkar
  • 136
  • 1
  • 4
  • 13
  • Does this answer your question? [Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException:](https://stackoverflow.com/questions/38424567/instantiation-of-bean-failed-nested-exception-is-org-springframework-beans-bean) – Unknown Aug 06 '21 at 10:36

1 Answers1

5

The problem is that you call laptop.compile() within the constructor of Alien. At that time, Spring didn't inject the Laptop bean yet, so this.laptop is null.

There are a few ways to solve this.

First of all, you could move the laptop.compile() to a separate method, annotated with @PostConstruct. For example:

@Component
public class Alien {
    private int id;
    private String name;
    private String tech;
    @Autowired
    private Laptop laptop;
    
    // Getters + Setters
    
    public void show() {
        System.out.println("in show..........");
    }

    // Add this method
    @PostConstruct
    public void initialize() {
        laptop.compile();
    }

    public Alien() {
        super();
        System.out.println("Object Created......");
    }
}

Alternatively, you could replace field injection with constructor injection:

@Component
public class Alien {
    private int id;
    private String name;
    private String tech;
    private Laptop laptop; // Remove @Autowired
    
    // Getters + Setters
    
    public void show() {
        System.out.println("in show..........");
    }


    @Autowired // Put @Autowired here
    public Alien(Laptop laptop) {
        super();
        this.laptop = laptop;
        System.out.println("Object Created......");
        this.laptop.compile();
    }
}

Nowadays, constructor injection is the prefered way of injecting beans, so this would be a viable solution. Note that even though I added the @Autowired annotation on top of the constructor, it's not necessary if this is your only constructor.

g00glen00b
  • 41,995
  • 13
  • 95
  • 133