wick3d
wick3d

Reputation: 1392

How to pass not null values @RequestParameter in controller?

I am trying to update an Entity by using spring boot 2.5.3 in the controller method.

http://localhost:5000/api/v1/student/1

with the following payload.

{
    "name":"abc",
    "email":"[email protected]",
    "dob":"2000-06-14"
}

These values are not updated. They are getting null values when I inspected them using a debugger. Here is my controller method.

@PutMapping(path = "/{id}")
public ResponseEntity<?> updateStudent(@PathVariable("id") Long id, @RequestParam(required = false) String name, @RequestParam(required = false) String email) {
    Student savedStudent = studentService.updateStudent(id, name, email);
    return ResponseEntity.ok(savedStudent);
}

Email and name are optional.

In debugger: name:null,email:null. Why are they getting null values? What is the correct way to pass values from the controller?

@Transactional
// We are not using any query from the repository because we have the service method with transactional annotation.
public Student updateStudent(Long studentId, String name, String email) {
    Student student = studentRepository.findById(studentId).orElseThrow(()->new EntityNotFoundException("Student with id " + studentId + " does not exists."));
    if (name!= null && name.length()>0 && !Objects.equals(name,student.getName())){
        student.setName(name);
    }
    
    if (email!= null && email.length()>0 && !Objects.equals(email,student.getEmail())){
        Optional<Student> optionalStudent = studentRepository.findStudentByEmail(email);
        if (optionalStudent.isPresent()){
            throw new IllegalStateException("Email is already taken");
        }
        student.setEmail(email);
    }
    System.out.println(student);
    Student savedStudent= studentRepository.save(student);
    return savedStudent;
}

Upvotes: 1

Views: 1914

Answers (3)

tmarwen
tmarwen

Reputation: 16354

Since you are POSTing an HTTP request with a content body (being in JSON in your case), you need to map the body using the @RequestBody annotation:

@PutMapping(path = "/{id}")
public ResponseEntity<?> updateStudent(@PathVariable("id") Long id, @RequestBody StudentDTO student) {
    Student savedStudent = studentService.updateStudent(
            id, student.getName(), student.getEmail());
    return ResponseEntity.ok(savedStudent);
}

The StudentDTO would be a lightweight type reflecting your input payload:

public class StudentDTO {
    private String name;
    private String email;
    private String dob;
    // setters and getters
}

Otherwise, to keep your RestController signature and use the @RequestParametrized fields, you should send a request of following shape:

http://localhost:5000/api/v1/student/1?name=abc&[email protected]&dob=2000-06-14

Upvotes: 1

Nikolas
Nikolas

Reputation: 44398

{
    "name":"abc",
    "email":"[email protected]",
    "dob":"2000-06-14"
}

This is not a request parameter but the request body. You need to create a class and use @RequestBody annotation.

@Data
public class UpdateStudentRequest {
    private String id;
    private String name;
    private String email;
}
@PutMapping(path = "/{id}")
public ResponseEntity<?> updateStudent(@PathVariable("id") Long id, @RequestBody UpdateStudentRequest request) {
    Student savedStudent = studentService.updateStudent(
            request.getId(), request.getName(), request.getEmail());
    return ResponseEntity.ok(savedStudent);
}

If you want to send the request parameters as... URL parameters:

http://localhost:5000/api/v1/student/1?name=abc&[email protected]

Upvotes: 1

jediz
jediz

Reputation: 4717

You aren't sending it as a param (after ?). http://localhost:5000/api/v1/student/1?name=John Could do the trick.

Upvotes: 1

Related Questions