Issue
I'm a bit new to Spring Boot and I'm trying to create model/repo/service/serviceImp/controller type of architecture.
After I try to make a this get request:
http://localhost:8080/api/v1/people/name?name=steve
and I get this error (I created a couple of people in DB):
"java.lang.NullPointerException: Cannot invoke \"com.project.Springbootbackend.service.PeopleService.findAllByName(String)\" because \"this.peopleService\" is null\r\n\tat com.project.Springbootbackend.controller.PeopleController.findAllByName(PeopleController.java:24)
This is my code: People(entity)
@Entity
public class People {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;
@Column(name = "email")
private String email;
...
//constructor + get/set
PeopleController
@RestController
@RequestMapping("/api/v1/people")
@RequiredArgsConstructor
public class PeopleController {
private PeopleService peopleService;
@GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(@RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
PeopleRepo
public interface PeopleRepository extends JpaRepository<People, Integer> {
List<People> findAllByName(String name);
}
PeopleService
public interface PeopleService {
List<People> findAllByName(String name);
}
PeopleServiceImp
@RequiredArgsConstructor
@Service
public class PeopleServiceImp implements PeopleService {
PeopleRepository peopleRepository;
@Override
public List findAllByName(String name) {
return (List) ResponseEntity.ok(peopleRepository.findAllByName(name));
}
}
Thx guys in advance.
*SOLUTION:
Entity, service & repository is the same. ServiceImp and controller changes are down belowe:
Controller:
@RestController
@RequestMapping("/api/v1/people")
public class PeopleController {
private PeopleService peopleService;
public PeopleController(PeopleService peopleService) {
this.peopleService = peopleService;
}
@GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(@RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
ServiceImp
@Service
public class PeopleServiceImp implements PeopleService {
private PeopleRepository peopleRepository;
public PeopleServiceImp(PeopleRepository peopleRepository) {
this.peopleRepository = peopleRepository;
}
@Override
public List<People> findAllByName(String name) {
List<People> people = peopleRepository.findAllByName(name);
return people;
}
}
Solution
Your constructor does not inject the service, because of the RequiredArgsConstructor
(see Link) needs special treatment. Therefore, use final
:
@RestController
@RequestMapping("/api/v1/people")
@RequiredArgsConstructor
public class PeopleController {
private final PeopleService peopleService;
@GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(@RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
Same here:
@RequiredArgsConstructor
@Service
public class PeopleServiceImp implements PeopleService {
private final PeopleRepository peopleRepository;
@Override
public List findAllByName(String name) {
return (List) ResponseEntity.ok(peopleRepository.findAllByName(name));
}
}
Additional hint, use a typed list:
@Override
public List<People> findAllByName(String name) {
return ResponseEntity.ok(peopleRepository.findAllByName(name));
}
Answered By - Kevin Wallis
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)