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.
I would like to recommend two methods of dependency injection using constructor. Please refer to the code below.
I hope it will be of help. :)