2

There is a red underlined with the message: Incompatible types. Required: ...model.Constants Found: java.util.Optional on jpa findById method.

I use findById is here:

Constants constants=constantsRepository.findById(1L);

And my model is:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "pkid")
private Long id;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

Any help please?

Here is my all code

ConstantsRepository interface

package com.destek.salaryCalculation.repository;

import com.destek.salaryCalculation.model.Constants;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ConstantsRepository extends  JpaRepository<Constants, Long>{

}

BesCreateController java

package com.destek.salaryCalculation.controller;

import com.destek.salaryCalculation.helper.BesCreateExcelHelper;
import com.destek.salaryCalculation.model.Personal;
import com.destek.salaryCalculation.repository.PersonalRepository;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@RestController
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping("/salarycalc")
public class BesCreateController {

    @Autowired
    private PersonalRepository personalRepository;

    @GetMapping("/besexcel/{group}")
    public void exportToExcelByGroup(HttpServletResponse response,@PathVariable String group) throws IOException, InvalidFormatException {
        response.setContentType("application/octet-stream");

        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=bes.xlsx";
        response.setHeader(headerKey, headerValue);
        List<Personal> listPersonal = personalRepository.getListPersonelByGroup(group);
        System.out.println(listPersonal);
        BesCreateExcelHelper excelExporter = new 
       BesCreateExcelHelper(listPersonal);
       excelExporter.export(response);
    }
}

And BesCreateHelper java

package com.destek.salaryCalculation.helper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Optional;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import com.destek.salaryCalculation.model.Constants;
import com.destek.salaryCalculation.model.Personal;
import com.destek.salaryCalculation.repository.ConstantsRepository;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;

public class BesCreateExcelHelper {
    private XSSFWorkbook workbook;
    private XSSFSheet sheet;
    private List<Personal> listPersonalBes;

    @Autowired
    private ConstantsRepository constantsRepository;
    public BesCreateExcelHelper(List<Personal> listPersonalBes) throws IOException, InvalidFormatException {
        FileInputStream inputStream = new FileInputStream(new File("bes.xlsx"));
        this.listPersonalBes = listPersonalBes;
        //workbook = new XSSFWorkbook();
        workbook = (XSSFWorkbook) WorkbookFactory.create(inputStream);
        sheet = workbook.getSheetAt(0);
        inputStream.close();
    }

    private void createCell(Row row, int columnCount, Object value, CellStyle style) {
        //sheet.autoSizeColumn(columnCount);
        Cell cell = row.createCell(columnCount);
        if (value instanceof Integer) {
            cell.setCellValue((Integer) value);
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        }else {
            cell.setCellValue((String) value);
        }
        cell.setCellStyle(style);
    }

    private void writeDataLines() {
        int rowCount = sheet.getLastRowNum();

        CellStyle style = workbook.createCellStyle();
        XSSFFont font = workbook.createFont();
        font.setFontHeight(15);
        style.setFont(font);

       Optional<Constants> constants2 = constantsRepository.findById(1L);
       Constants constants = constants2.orElseThrow(() ->new RuntimeException("No such data found"));;

        for (Personal personal : listPersonalBes) {
            Row row = sheet.createRow(++rowCount);
            int columnCount = 0;
            int i = 1;
            createCell(row, columnCount++, i++, style);
            createCell(row, columnCount++, personal.getName(), style);
            createCell(row, columnCount++, personal.getIdentity().toString(), style);
            double besAmount=0;
            if(personal.getBes()==1){
                int numberDayOfMonth=constants.getDayOfWork();
           int sanitaryPermit=personal.getSanitaryPermit();
            double grossWages=0;
           if(sanitaryPermit<numberDayOfMonth) {
                grossWages = constants.getDailyWage() * (numberDayOfMonth - sanitaryPermit);
           }
               float socialHelp=constants.getSocialHelp();
               float mealBonus=constants.getMealBonus();
               float tisSupport=constants.getTisSupport();
               double deservedVehicleHelp=0;
               if(numberDayOfMonth>0){
                   int dayOfWork=numberDayOfMonth-sanitaryPermit-personal.getAnnualPermit();
                   // TODO: 11.01.2021 busTicketHelp tekrar hesaplatılacak.
                   double busTicketHelp=3.25*numberDayOfMonth;
                    deservedVehicleHelp=busTicketHelp*dayOfWork/numberDayOfMonth;
               }
               double mealPrice=(constants.getDayOfWork()-(personal.getSanitaryPermit()- Math.floor(personal.getSanitaryPermit()/7)*2)-personal.getAnnualPermit())*constants.getMealBonus();
               double extraWorkHourPrice=Math.ceil(personal.getExtraWorkHour()*constants.getDailyWage()/5);
               double extraWorkHourPriceSpecial=Math.ceil(personal.getExtraWorkHourSpecial()*constants.getDailyWage()/7.5*1.5);
               double mealException=constants.getMinimumWage()/30*6/100*mealPrice;
               double sgkPrimBaseAmount=grossWages+socialHelp+mealBonus+tisSupport+deservedVehicleHelp+mealPrice+extraWorkHourPrice+extraWorkHourPriceSpecial+mealException;
               besAmount=sgkPrimBaseAmount*0.03;
               }
            createCell(row, columnCount++, String.valueOf(besAmount), style);
        }
    }
    public void export(HttpServletResponse response) throws IOException {
        //writeHeaderLine();
        writeDataLines();
        ServletOutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        // workbook.close();
        outputStream.close();
    }
}
hkngndz47
  • 63
  • 1
  • 8
  • my constantsRepository extends JpaRepository – hkngndz47 Jan 11 '21 at 13:03
  • 2
    The error message is pretty clear: `findById` returns an `Optional` ... – Henry Jan 11 '21 at 13:05
  • 3
    I think the error is pretty clear: findById method returns Optional. What is exactly you don't understand? – m0skit0 Jan 11 '21 at 13:06
  • 1
    Since spring data jpa 2.0, the some methods was modified and return Optional instaed of the value, please read this https://stackoverflow.com/questions/49316751/spring-data-jpa-findone-change-to-optional-how-to-use-this – Marcos Echagüe Jan 11 '21 at 13:17

3 Answers3

5

As @AnishB states you need to resolve the value from the optional but I would not use

... = constants.get(); 

straight away since this is dangerous constants.get() would throw NoSuchElementException if value does not exist

You should use:

Constants value = constants.orElse(null); 

or even

Constants value = constants.orElseThrow(() -> new CustomException()); 

this line would throw exception but on that case you control the exception handling not something behind the scenes

BTW, You are getting a NullPointerException when try to call constantsRepository.findById(1L); because the BesCreateExcelHelper is not a Spring dependency so you can not inject other spring dependencies into it at that case constantsRepository will be null

You have 2 options:

#1, Annotate that BesCreateExcelHelper with @Component annotation this will make BesCreateExcelHelper a spring dependency thus constantsRepository will be injected normally BUT you must convert BesCreateExcelHelper constructor into a method since constructors are used by Spring starting from version 4.3 to inject dependencies.

BesCreateExcelHelper would be like :

@Component
public class BesCreateExcelHelper {
...
public void init(List<Personal> listPersonalBes) { // notice this was the constructor logic
  .......
}
}

And then you inject BesCreateExcelHelper into the BesCreateController and replace that ..new BesCreateController() line with besCreateExcelHelper.init(listPersonal)


#2 You can keep the BesCreateExcelHelper as it is but remove that Constant fetch line and pass the constant value from outside, ofcourse outside here means some other Spring component as you do in exportToExcelByGroup so simply you will execute constantsRepository.findById(1L); in the controller then pass it as a second constructor argument to the Helper class

...

constant = ...constantsRepository.findById(1L);
excelExporter = new 
       BesCreateExcelHelper(listPersonal, constant);

I like first option more

Youans
  • 4,801
  • 1
  • 31
  • 57
  • it did not work. I got java.lang.NullPointerException: null on the here Optional constants = constantsRepository.findById(1L); – hkngndz47 Jan 11 '21 at 14:03
  • i have record on my table with id=1 – hkngndz47 Jan 11 '21 at 14:04
  • @hkngndz47 Assuming you are 100% sure there is a record in that DB and it is the one you are connected to, It should get you that record Can you post the `ConstantRepository` just to confirm there is nothing wrong with it – Youans Jan 11 '21 at 14:50
  • yes i am sure there is a record in my db that have id=1 – hkngndz47 Jan 12 '21 at 07:41
  • Then please show the repo code and also the stacktrace of the `NullPointerException` – Youans Jan 12 '21 at 07:57
  • @Repository public interface ConstantsRepository extends JpaRepository{ } – hkngndz47 Jan 12 '21 at 08:02
  • java.lang.NullPointerException: null at com.destek.salaryCalculation.helper.BesCreateExcelHelper.writeDataLines(BesCreateExcelHelper.java:62) ~[classes/:na] at com.destek.salaryCalculation.helper.BesCreateExcelHelper.export(BesCreateExcelHelper.java:104) ~[classes/:na] at com.destek.salaryCalculation.controller.BesCreateController.exportToExcelByGroup(BesCreateController.java:47) ~[classes/:na] – hkngndz47 Jan 12 '21 at 08:05
  • Null happens with line 62 in BesCreateExcelHelper.java, can you show that also – Youans Jan 12 '21 at 08:07
  • Optional constants2 = constantsRepository.findById(1L); – hkngndz47 Jan 12 '21 at 08:11
  • Do you use Spring Boot? – Youans Jan 12 '21 at 08:14
  • Now as you can see the only object in that line is, `constantsRepository` that means there is something wrong with the injection I saw your comments on @Anish so I'd suggest look on some different reasons you can find them at that post , https://stackoverflow.com/questions/34367316/spring-boot-autowired-does-not-work-classes-in-different-package A strong reason might be that your repository is not scanned by Spring, means Spring does not consider it as a dependency so whenever you wire it, Spring will do nothing – Youans Jan 12 '21 at 08:17
  • Another reason that you may try to inject the repo into non-spring dependency, so at that case you must make sure `Optional constants2 = constantsRepository.findById(1L);` is executed in a Spring dependency (@Service annotated class) – Youans Jan 12 '21 at 08:18
  • I can not really tell what exactly is the problem without seeing the code structure with a full vision – Youans Jan 12 '21 at 08:19
  • You can show the package structure via a screenshot image, and post the full Class in which you execute that line `Optional constants2 = constantsRepository.findById(1L);` – Youans Jan 12 '21 at 08:27
  • I added my code to my question. Can you look please? – hkngndz47 Jan 12 '21 at 11:11
  • @hkngndz47 Updated answer post please re-check – Youans Jan 12 '21 at 12:42
  • @hkngndz47 added more code sample to make it clearer – Youans Jan 12 '21 at 12:51
  • Not at all, Glad I can help! – Youans Jan 20 '21 at 23:21
2

findById(ID id) method from JpaRepository returns a value of type Optional<T>.

To get the actual value from Optional<T>, you can use get() method but in some cases, data may not be there and you will get NoSuchElementException. So, you either return a default value with orElse() or you can throw an exception with orElseThrow().

Example :

With orElseThrow() :

Optional<Constants> constants = constantsRepository.findById(1L);
                           
Constants value = constants.orElseThrow(() -> 
                                new RuntimeException("No such data found"));

With orElse()

Optional<Constants> constants = constantsRepository.findById(1L);
                           
Constants value = constants.orElse(null);

if(value == null) {
  // write some logic
}
Anish B.
  • 9,111
  • 3
  • 21
  • 41
0

findById return a Optinal data.You need to get it like this.

Optional<Constants> constants=constantsRepository.findById(1L);