Use @RequestBody with optional body in latest Spring v4
Asked Answered
J

4

67

How do I make body optional in REST API calls when using @RequestBody annotation in Spring?

With Spring's latest version, if you use @RequestBody annotation, it makes client to send body all the time without making it optional.

I tried @RequestBody (required=false) but that didn't work & still my request comes as null.

How do I manage to get request converted to proper required object without making body mandatory?

For eg:

@RequestMapping(value="/add/employee", method=RequestMethod.POST)
public void addEmployee(@RequestBody Employee employee){
    // ...
}

Here, I want to add employee using POST but without body. How do I do that? Spring latest version throws error "body missing" if I send empty body...

Jataka answered 24/2, 2015 at 3:23 Comment(0)
S
70

@Santosh, I'm not sure which required argument you're referring. Mike already mentioned that he tried using @RequestBody (required=false) and request was still null. May be you can elaborate more & give example.

@Mike, probably you can try to have another separate converter that will serve your purpose.

Note: I noticed same issue with Spring v4.1.6 & Mike could be using that as he mentioned he is using latest version.

Sinkage answered 24/2, 2015 at 5:13 Comment(0)
D
18

I guess you are using spring version above 3.2 as there was a issue with the version. @RequestBody should have a required parameter to allow a request body to be optional

Have a look at following link Spring @RequestBody Anotation

@RequestBody Body takes and argument required which is true by default. Specifying it to false will help you

public abstract boolean required

Whether body content is required. Default is true, leading to an exception thrown in case there is no body content. Switch this to false if you prefer null to be passed when the body content is null.

Dygert answered 24/2, 2015 at 3:43 Comment(1)
When using a String as RequestBody(required = false) the default doesn't come as null, but as {} instead. Not sure why, but cost me some time and thought I'd share.Barmy
J
16

You can use java.util.Optional:

@RequestMapping(value="/add/employee", method=RequestMethod.POST)
public void addEmployee(@RequestBody Optional<Employee> employee){
    // ...
}
Jyoti answered 27/5, 2019 at 9:30 Comment(3)
it's not advisable to use Optional type for params, intellij gives the message see: wangler.io/blog/2017/….Every
@Every imo, that is a silly warning. Optional parameters can be very useful.Polarize
Optionals yes, but not as parametersRaynard
O
1

I had a similar problem where I was trying to deserialize to a class called Customer marked as an Entity. Because it contained a field pointing to another entity:

@Entity
public class Customer {
   // ...
   @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
   @JsonManagedReference
   private List<Order> orders;
}

I kept getting a 415 error stating that application/json wasn't supported when trying to hit the following endpoint

@RestController
@RequestMapping("api/v1/customer")
public class Customer {
    // ...
    @PostMapping
    public void addNewCustomer(@RequestBody Customer cust) {
        customerService.createCustomer(cust);
    }
}

Replacing it with this worked:

record NewCustomerRequest(String name) {}

@PostMapping
public void addNewCustomer(@RequestBody NewCustomerRequest request) {
    Customer cust = Customer.builder()
            .name(request.name())
            .build();
    customerService.createCustomer(cust);
}
Onceover answered 6/5, 2023 at 1:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.