NullPointerException при попытке получить ResponseEntity из другого сервиса на spring boot

Рейтинг: -1Ответов: 1Опубликовано: 25.06.2023

Спринг выдаёт NullPointerException в запросе, обновляющем сразу две таблицы. GET- запрос с аналогичными данными, но использующий только один сервис, полностью рабочий. Можете подсказать, что не так, пожалуйста?

Классы сервисов:


import com.example.uralsibtest.enums.Position;
import com.example.uralsibtest.exceptions.DepartmentNotFoundException;
import com.example.uralsibtest.exceptions.EmployeeNotFoundException;
import com.example.uralsibtest.exceptions.PositionNotFoundException;
import com.example.uralsibtest.model.Employee;
import com.example.uralsibtest.repository.DepartmentRepository;
import com.example.uralsibtest.repository.EmployeeRepository;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Override
    public Employee updateEmployeePosition(Integer employeeId, String newPosition)
            throws EmployeeNotFoundException, PositionNotFoundException, DepartmentNotFoundException, ParseException {
        Employee employee = (Employee) employeeRepository.findById(employeeId)
                .orElseThrow(() -> new EmployeeNotFoundException(employeeId));
        
        String strNewPosition = JsonParser.getJsonValue(newPosition, "newPosition");
        
        if (strNewPosition.equals(Position.CONSULTANT.getPositionValue()) ||
                strNewPosition.equals(Position.MIDDLE_DEVELOPER.getPositionValue()) ||
                strNewPosition.equals(Position.SENIOR_DEVELOPER.getPositionValue()) || 
        strNewPosition.equals(Position.JUNIOR_DEVELOPER.getPositionValue())) {
            DepartmentServiceImpl departmentService = new DepartmentServiceImpl();

            if (!departmentService.returnDepartmentByPosition(employee.getPosition())
                    .equals(departmentService.returnDepartmentByPosition(strNewPosition))) {
                Integer departmentId = departmentService.returnDepartmentByPosition(strNewPosition);

                //this
                if (departmentService.updateEmployeesCount(departmentId)) {
                    //
                    return employee;
                } else {
                    throw new DepartmentNotFoundException(departmentId);
                }
            }

            employee.setPosition(strNewPosition);
            employeeRepository.save(employee);
        } else {
            throw new PositionNotFoundException(newPosition);
        }
        return null;
    }

    public Employee updateEmployeeName(Integer employeeId, String newName) throws
            EmployeeNotFoundException{
        Employee employee = (Employee) employeeRepository.findById(employeeId)
                .orElseThrow(() -> new EmployeeNotFoundException(employeeId));
        employee.setName(newName);
        employeeRepository.save(employee);
        return employee;
    }

    public Employee createEmployee(Employee employee) throws PositionNotFoundException{
        if (employee.getPosition().equals(Position.CONSULTANT.getPositionValue()) 
                || employee.getPosition().equals(Position.MIDDLE_DEVELOPER.getPositionValue()) ||
        employee.getPosition().equals(Position.JUNIOR_DEVELOPER.getPositionValue()) ||
        employee.getPosition().equals(Position.SENIOR_DEVELOPER.getPositionValue())) {
            employeeRepository.save(employee);
            return employee;
        } else {
            throw new PositionNotFoundException(employee.getPosition());
        }
    }

    public Employee getEmployeeById(Integer employeeId) throws EmployeeNotFoundException{
        return (Employee) employeeRepository.findById(employeeId)
                .orElseThrow(() -> new EmployeeNotFoundException(employeeId));

    }
}

import com.example.uralsibtest.enums.Position;
import com.example.uralsibtest.exceptions.DepartmentNotFoundException;
import com.example.uralsibtest.exceptions.PositionNotFoundException;
import com.example.uralsibtest.model.Department;
import com.example.uralsibtest.repository.DepartmentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DepartmentServiceImpl implements DepartmentService {

    @Autowired
    DepartmentRepository departmentRepository;

    public Integer returnDepartmentByPosition(String position) throws PositionNotFoundException {
        if (position.equals(Position.SENIOR_DEVELOPER.getPositionValue()) ||
                position.equals(Position.JUNIOR_DEVELOPER.getPositionValue()) ||
                position.equals(Position.MIDDLE_DEVELOPER.getPositionValue())) {
            return 1;
        } else if (position.equals(Position.CONSULTANT.getPositionValue())){
            return 2;
        } else {
            throw new PositionNotFoundException(position);

        }
    }

    public Boolean updateEmployeesCount(Integer id) throws DepartmentNotFoundException {
        Department department1 = findDepartmentById(id);
        Department department2 = findDepartmentById(id == 1 ? 2 : 1);

        System.out.println(department1.getEmployeesCount());

        department1.setEmployeesCount(department1.getEmployeesCount() - 1);
        department2.setEmployeesCount(department2.getEmployeesCount() + 1);
        departmentRepository.save(department1);
        departmentRepository.save(department2);
        return true;
    }

    public List findAllDepartments() {
        return departmentRepository.findAll();
    }

    public Department findDepartmentById(Integer id) throws DepartmentNotFoundException {
//        System.out.println(departmentRepository == null); false
        return (Department) departmentRepository.findById(id)
                .orElseThrow(() -> new DepartmentNotFoundException(id));
    }
}

Классы контроллеров:


import com.example.uralsibtest.exceptions.DepartmentNotFoundException;
import com.example.uralsibtest.model.Department;
import com.example.uralsibtest.service.DepartmentServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DepartmentController {

    @Autowired
    DepartmentServiceImpl departmentServiceImpl;

    @PutMapping("/department/{id}/update/supervisor")
    public ResponseEntity updateDepartmentSupervisor(@PathVariable (value = "id") Integer departmentId) {
        return null;
    }

    @PutMapping("/internal/department/{id}/employees-count/update")
    public Boolean updateEmployeesCount(@PathVariable(value = "id") Integer id) throws DepartmentNotFoundException {
        return departmentServiceImpl.updateEmployeesCount(id);
    }

    @GetMapping("/departments")
    public List findAllDepartments() {
        return departmentServiceImpl.findAllDepartments();
    }

    @GetMapping("department/{id}")
    public Department returnDepartmentById(@PathVariable(value = "id") Integer id) throws DepartmentNotFoundException{
        return departmentServiceImpl.findDepartmentById(id);
    }
}
import com.example.uralsibtest.exceptions.DepartmentNotFoundException;
import com.example.uralsibtest.exceptions.EmployeeNotFoundException;
import com.example.uralsibtest.exceptions.PositionNotFoundException;
import com.example.uralsibtest.model.Employee;
import com.example.uralsibtest.service.EmployeeServiceImpl;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class EmployeeController{

    @Autowired
    EmployeeServiceImpl employeeService;

    @GetMapping("employee/{id}")
    public Employee getEmployeeById(@PathVariable(value = "id")Integer employeeId) throws EmployeeNotFoundException{
        return employeeService.getEmployeeById(employeeId);

    }

    @PostMapping("/employee/create")
    public Employee createEmployee( @RequestBody Employee employee) throws PositionNotFoundException{
        return employeeService.createEmployee(employee);
    }

    @PutMapping("/employee/{id}/update/name")
    public Employee updateEmployeeName(@PathVariable(value = "id") Integer employeeId,
                                       @RequestBody String newName) throws
            EmployeeNotFoundException{
        return employeeService.updateEmployeeName(employeeId, newName);
    }

    @PutMapping("/employee/{id}/update/position")
    public Employee updateEmployeePosition(@PathVariable(value = "id") Integer employeeId,
                                           @RequestBody String newPosition) throws EmployeeNotFoundException,
            PositionNotFoundException, DepartmentNotFoundException, ParseException {
        return employeeService.updateEmployeePosition(employeeId, newPosition);
    }
}

Логи самой ошибки:

Hibernate: 
    select
        e1_0.id,
        e1_0.address,
        e1_0.department,
        e1_0.employment_date,
        e1_0.name,
        e1_0.phone,
        e1_0.position 
    from
        employee e1_0 
    where
        e1_0.id=?
2023-06-25T03:47:59.739+03:00 ERROR 11288 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.example.uralsibtest.repository.DepartmentRepository.findById(Object)" because "this.departmentRepository" is null] with root cause

java.lang.NullPointerException: Cannot invoke "com.example.uralsibtest.repository.DepartmentRepository.findById(Object)" because "this.departmentRepository" is null
    at com.example.uralsibtest.service.DepartmentServiceImpl.findDepartmentById(DepartmentServiceImpl.java:51) ~[classes/:na]
    at com.example.uralsibtest.service.DepartmentServiceImpl.updateEmployeesCount(DepartmentServiceImpl.java:33) ~[classes/:na]
    at com.example.uralsibtest.service.EmployeeServiceImpl.updateEmployeePosition(EmployeeServiceImpl.java:42) ~[classes/:na]
    at com.example.uralsibtest.controller.EmployeeController.updateEmployeePosition(EmployeeController.java:40) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:578) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[spring-web-6.0.9.jar:6.0.9]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[spring-web-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:925) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:593) ~[tomcat-embed-core-10.1.8.jar:6.0]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.0.9.jar:6.0.9]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.8.jar:6.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.9.jar:6.0.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.9.jar:6.0.9]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.9.jar:6.0.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.9.jar:6.0.9]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.9.jar:6.0.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.9.jar:6.0.9]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.8.jar:10.1.8]
    at java.base/java.lang.Thread.run(Thread.java:1623) ~[na:na]

Ответы

▲ 1

В логах же написано

java.lang.NullPointerException: Cannot invoke "com.example.uralsibtest.repository.DepartmentRepository.findById(Object)" because "this.departmentRepository" is null at com.example.uralsibtest.service.DepartmentServiceImpl.findDepartmentById(DepartmentServiceImpl.java:51) ~[classes/:na] at com.example.uralsibtest.service.DepartmentServiceImpl.updateEmployeesCount(DepartmentServiceImpl.java:33) ~[classes/:na] at com.example.uralsibtest.service.EmployeeServiceImpl.updateEmployeePosition(EmployeeServiceImpl.java:42) ~[classes/:na]

То есть вы зачем-то создаёте экземпляр сервиса DepartmentServiceImpl локально при вызове метода EmployeeServiceImpl::updateEmployeePosition, НЕ используя механизмы Spring и НЕ передавая экземпляр репозитория при помощи конструктора, соответственно в этом экземпляре значение репозитория departmentRepository остаётся null-овым.

Если у вас есть зависимость на другой сервис, имеет смысл вынести эту переменную на уровень класса и сделать её Autowired полем, убрав создание нового экземпляра при помощи new DepartmentService():

public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private DepartmentService departmentService;

    // ...

    @Override
    public Employee updateEmployeePosition(Integer employeeId, String newPosition)
            throws EmployeeNotFoundException, PositionNotFoundException, DepartmentNotFoundException, ParseException {
        Employee employee = (Employee) employeeRepository.findById(employeeId)
                .orElseThrow(() -> new EmployeeNotFoundException(employeeId));
        
        String strNewPosition = JsonParser.getJsonValue(newPosition, "newPosition");
        
        if (strNewPosition.equals(Position.CONSULTANT.getPositionValue()) ||
                strNewPosition.equals(Position.MIDDLE_DEVELOPER.getPositionValue()) ||
                strNewPosition.equals(Position.SENIOR_DEVELOPER.getPositionValue()) || 
        strNewPosition.equals(Position.JUNIOR_DEVELOPER.getPositionValue())) {
//  УБРАТЬ DepartmentServiceImpl departmentService = new DepartmentServiceImpl();

            if (!departmentService.returnDepartmentByPosition(employee.getPosition())
                    .equals(departmentService.returnDepartmentByPosition(strNewPosition))) {
                Integer departmentId = departmentService.returnDepartmentByPosition(strNewPosition);
        // ...
}