Autowired annotation not working for Service Class

37 Views Asked by At

I'm creating a desktop app using spring and javafx. The issue that I'm facing is with a repository that I have. I'm using the Service component to create an excel file, but I have some issues with the Autowired repository that it is declared in it.

PersonnelRepository.java:

package com.pn.Shifter.repository;

import com.pn.Shifter.entity.Personnel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.util.List;

@Repository
public interface PersonnelRepository extends JpaRepository<Personnel, Integer> {
    Personnel findPersonnelByFirstNameAndLastName(String firstName, String lastName);

    List<Personnel> findPersonnelsByShift(Boolean shift);

    List<Personnel> findPersonnelsByPosition(String position);

}

PersonnelService.java:

package com.pn.Shifter.service;

import com.pn.Shifter.entity.Personnel;
import com.pn.Shifter.repository.PersonnelRepository;
import jakarta.transaction.Transactional;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class PersonnelService {

    private final PersonnelRepository repository;

    public Personnel addPersonnel(Personnel personnel){
        return repository.save(personnel);
    }

    public Personnel updatePersonnel(String id, Personnel personnel){
        Personnel oldPersonnel = repository.getReferenceById(Integer.parseInt(id));
        return repository.save(personnel);
    }

    public Personnel getPersonnelByName(String firstName, String lastName){
        return repository.findPersonnelByFirstNameAndLastName(firstName, lastName);
    }

    public List<Personnel> getShiftablePersonnel(){
        return repository.findPersonnelsByShift(true);
    }

    public List<Personnel> getPersonnelByDayPosition(String position){
        return repository.findPersonnelsByPosition(position);
    }

    public void deletePersonnel(String id){
        repository.deleteById(Integer.parseInt(id));
    }
}

Functionality.java:

package com.pn.Shifter;

import com.pn.Shifter.entity.Personnel;
import com.pn.Shifter.repository.PersonnelRepository;
import com.pn.Shifter.service.PersonnelService;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

@Component
@Configurable
public class Functionality {

    @Autowired
    private PersonnelService personnelService;

    public void createShift() throws IOException {
        List<Personnel> shiftablePersonnel = personnelService.getShiftablePersonnel();
        int personnelSize = shiftablePersonnel.size();

        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet spreadsheet = workbook.createSheet("Programm");
        LocalDate start = LocalDate.of(2024, 3, 18);
        Map<String, Object[]> shifts = new TreeMap<String, Object[]>();

        shifts.put("1", new Object[] {start.toString(), start.plusDays(1).toString(), start.plusDays(2).toString()});

        XSSFRow row;
        Set<String> keyid = shifts.keySet();

        int rowid = 0;

        // writing the data into the sheets...

        for (String key : keyid) {

            row = spreadsheet.createRow(rowid++);
            Object[] objectArr = shifts.get(key);
            int cellid = 0;

            for (Object obj : objectArr) {
                Cell cell = row.createCell(cellid++);
                cell.setCellValue((String)obj);
            }
        }

        // .xlsx is the format for Excel Sheets...
        // writing the workbook into the file...
        FileOutputStream out = new FileOutputStream(
                new File("excelFileLocation"));

        workbook.write(out);
        out.close();
    }
}

HomePageUIController.java:

package com.pn.Shifter.controller;

import com.pn.Shifter.Functionality;
import javafx.event.Event;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import static com.pn.Shifter.JavafxApplication.getContext;

public class HomePageUIController implements Initializable {
    private Stage stage;
    private Scene scene;
    private Parent root;


    private final Functionality functionality = new Functionality();


    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    public void onAdd(Event event) throws IOException {
        Resource registerResource = getContext().getResource("ui/registerUI.fxml");
        root = FXMLLoader.load(registerResource.getURL());
        stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        scene = new Scene(root, 600, 600);
        stage.setScene(scene);
        stage.show();
    }

    public void onExtract(Event event) throws IOException {
        functionality.createShift();
    }
}

The program compiles fine, but when the onExtract method from the HomePageUIController gets triggered, I get a NullPointerException that says:

Error Log

Caused by: java.lang.NullPointerException: Cannot invoke "com.pn.Shifter.service.PersonnelService.getShiftablePersonnel()" because "this.personnelService" is null

In a previous implementation that I made, I got the service to be not null but then the repository was. I used a Config class where I was creating a Bean for the PersonnelService but then the Autowired annotation for the PersonnelRepository seemed not working.

1

There are 1 best solutions below

1
soonhankwon On
  • There is a problem with creating and using new Functionality in HomePageUIController.
  • Spring Beans must be used through dependency injection.

I would like to recommend two methods of dependency injection using constructor. Please refer to the code below.

package com.pn.Shifter.controller;

import com.pn.Shifter.Functionality;
import javafx.event.Event;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import static com.pn.Shifter.JavafxApplication.getContext;

public class HomePageUIController implements Initializable {
    private Stage stage;
    private Scene scene;
    private Parent root;

    private final Functionality functionality;
    
    // constructor dependency injection
    public HomePageUIController(Functionality functionality) {
        this.functionality = functionality;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    public void onAdd(Event event) throws IOException {
        Resource registerResource = getContext().getResource("ui/registerUI.fxml");
        root = FXMLLoader.load(registerResource.getURL());
        stage = (Stage)((Node)event.getSource()).getScene().getWindow();
        scene = new Scene(root, 600, 600);
        stage.setScene(scene);
        stage.show();
    }

    public void onExtract(Event event) throws IOException {
        functionality.createShift();
    }
}
  • It is also the same if you use the @RequiredArgsConstructor annotation.
  • I confirmed with test code that the above code solves the problem.

I hope it will be of help. :)