Home > database >  My update function doesn't work : Spring CRUD API
My update function doesn't work : Spring CRUD API

Time:09-02

I'm creating a CRUD API with Spring to manage students. Here is my service:

package com.example.demo.student;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
public class StudentService {

    private final StudentRepository studentRepository;
    @Autowired
    public StudentService(StudentRepository studentRepository) {
        this.studentRepository = studentRepository;
    }
    public List<Student> getStudents(){

        return studentRepository.findAll();
    }

    public void addNewStudent(Student student) {
        Optional<Student> studentByName = studentRepository.findStudentByName(student.getName());
        if(studentByName.isPresent()){
            try {
                throw new Exception("name taken");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
        studentRepository.save(student);
    }

    public void deleteStudent(Long studentId) {
        boolean exists = studentRepository.existsById(studentId);
        if (!exists){
            throw new RuntimeException("student with id"   studentId   " does not exist.");
        }
        studentRepository.deleteById(studentId);

    }

    @Transactional
    public Student updateStudent(Long studentId, String name) {
        Student student = studentRepository.findById(studentId).orElseThrow(() -> new RuntimeException(
                "student with Id"   studentId   " does not exist"
                )
        );
        if(name != null && name.length() > 0 && !Objects.equals(student.getName(), name)){
            student.setName(name);
            return studentRepository.save(student);
        }
        return student;
    }


    public Optional<Student> getStudent(Long studentId) {
        Student student = studentRepository.findById(studentId).orElseThrow(() -> new RuntimeException(
                        "student with Id"   studentId   " does not exist"
                )
        );
        return studentRepository.findById(studentId);

    }
}

And my controller:

package com.example.demo.student;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping(path="api/student")
public class StudentController {

    private final StudentService studentService;

    @Autowired
    public StudentController(StudentService studentService) {
        this.studentService = studentService;
    }


    @GetMapping
    public List<Student> getStudents(){
        return studentService.getStudents();

    }

    @GetMapping(path="/{studentId}")
    public Optional<Student> getStudent(@PathVariable("studentId")Long studentId){
        return studentService.getStudent(studentId);

    }

    @PostMapping
    public void registerNewStudent(@RequestBody Student student){
        studentService.addNewStudent(student);
    }

    @DeleteMapping(path="{studentId}")
    public void deleteStudent(@PathVariable("studentId")Long studentId){
        studentService.deleteStudent(studentId);
    }

    // only update name
    @PutMapping(path="{studentId}")
    public void updateStudent(
            @PathVariable("studentId")Long studentId,
            @RequestParam(required = false) String name)

    {
        studentService.updateStudent(studentId, name );
    }
}
 

But when I go on postman, and try to update for example student 3 with this url: http://localhost:8080/api/student/3, it doesn't change anything, even if the response is 1.

Can anyone helps me ? Thanks in advance

CodePudding user response:

You are ignoring the payload sent with the PUT. In the Controller for the PUT endpoint, you are not using the @RequestBody.

You are using only the @RequestParam annotation. So with the code you wrote you are able only to change the name by sending it as part of the URL.

Nevertheless, in the request that you are sending you are not specifying the name @RequestParam. If you want to see your code working just send a PUT to this URL: localhost:8080/api/student/3?name=jean.

In my opinion you should remove the name @RequestParam and add the @RequestBody as you are doing in the POST.

CodePudding user response:

I would not mix @RequestParam AND @PathVariable in the same endpoint. Even so, try calling

PUT http://localhost:8080/api/student/3?name=Jones

Does that work?

Or change your controller method signature to

@PutMapping("/{studentId}/{name}")
    public void updateStudent( @PathVariable("studentId")Long studentId, @PathVariable("name") String name)

...and call

PUT http://localhost:8080/api/student/3/Jones

This may be tangental, but I would abstract out an interface IStudentService (or other naming convention) with just the method declarations, no implementations. Then update the class as

public class StudentService implements IStudentService;

Assuming that StudentRepository is a Jpa/CrudRepository interface, then in StudentService all you need is

@Autowired StudentRepository studentRepository; 

You don't need that verbose constructor injection. And in the controller all you need is

@Autowired IStudentService studentService; 

(the name of the interface not the implementation class).

  • Related