NullPointerException usando @Autowired en la vista

Hola a todos, ya tengo tiempo atorado quierendo resolver un NullPointerException al querer inyectar el repositorio a mi vista y al momento de utilizarlo me marca ese error.

En la consola de información si me marca que se encontró el repositorio:

2019-03-17 16:47:27.114  INFO 52388 --- [  restartedMain]
 .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 18ms. Found 1 repository interfaces.

si funciona en la clase de inicialización de la aplicación.

@SpringBootApplication
public class Application extends SpringBootServletInitializer implements CommandLineRunner {

  @Autowired
  private StudentRepository repository;
  
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
  
  @Override
  public void run(String... args) throws Exception {
    System.out.println("students count: " + repository.count());
  }
}

pero no me funciona al usarlo en la vista:

@Route(value = "student", layout = MainLayout.class)
public class StudentView extends FlexLayout {
  private List<Student> items;
  
  @Autowired
  private StudentRepository repository;
  
  public StudentView() {
    setSizeFull();
    setJustifyContentMode(JustifyContentMode.CENTER);
    setAlignItems(Alignment.CENTER);
    
    doRefresh();
    add(createGrid());
  }
  
  private void doRefresh() {
    items = repository.findAll();
  }
  
  private Component createGrid() {
    Grid<Student> grid = new Grid<>();
    grid.setSelectionMode(SelectionMode.SINGLE);
    grid.setSizeFull();
  
    grid.addColumn(Student::getCode).setHeader("Matricula");
    grid.addColumn(Student::getLastname).setHeader("Apellido");
    grid.addColumn(Student::getFirstname).setHeader("Nombres");
    grid.addColumn(Student::getGrade).setHeader("Grado");
    grid.addColumn(student -> student.getActive() != null && student.getActive() ? "SI" : "NO").setHeader("activo");
  
    grid.addItemClickListener(event -> onClickGridItemListener(event.getItem()));
  
    grid.setItems(items);
    return grid;
  }
  
  private void onClickGridItemListener(Student item) {
    System.out.println("item: "+item);
  }  
}

aqui esta la interface del repositorio:

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

}

Espero me puedan ayudar con este problema ya que no se que me falta por configurar o definir en mi aplicación.

Gracias de antemano!
Marco

Hola Marco

Sorry for writing in English - my Spanish is good enough to understand your problem but I can’t write it.

@Autowired fields (“field injection”) will be injected after the constructor is finished! You can not use these fields in the constructor.

You can fix your NullPointerException by doing one of the following (hacer solo uno, no ambos):

  • Inject the repository directly into the constructor (“constructor injection”)
  • Add a method with the annotation @PostConstruct where you can call doRefresh(). The repository will exist at this time.

Constructor Injection:
(Si no entendiste nada, prueba esto aquí :slight_smile: )

// no @Autowired annotation here
private StudentRepository repository;
  
@Autowired
public StudentView(StudentRepository repository) { 
    this.repository = repository;
    setSizeFull();
    setJustifyContentMode(JustifyContentMode.CENTER);
    setAlignItems(Alignment.CENTER);
    
    doRefresh(); // repository is not null now!
    add(createGrid());
  }

Using a post constructor:

@Autowired
private StudentRepository repository;
  
public StudentView() {
  setSizeFull();
  setJustifyContentMode(JustifyContentMode.CENTER);
  setAlignItems(Alignment.CENTER);
    
  //doRefresh();  // do not call doRefresh yet, repository is null
  add(createGrid());
}

@PostConstruct
public void postConstruct(){
  doRefresh();
  grid.setItems(items);  // grid.setItems needs to be removed from createGrid(), because items will be empty there.
}

I hope this was of help, even if it was in English

Hi Kaspar, thanks for your reply and it works perfectly.

Regards!
Marco