No, Java allows it, but @RestController does not.
While this is valid Java code...
@PostMapping("/account")
public ResponseEntity<Void> postAccount(SavingsAccount account) {
log.info("savings account posted");
// process savings account
return ResponseEntity.ok().build();
}
@PostMapping("/account")
public ResponseEntity<Void> postAccount(CurrentAccount account) {
log.info("current account posted");
// process current account
return ResponseEntity.ok().build();
}
...you will get an error like this at startup, because you can not have two methods with the same path and method:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Ambiguous mapping. Cannot map 'demoController' method
org.example.restdemo.DemoController#postAccount(SavingsAccount)
to {POST [/account]}: There is already 'demoController' bean method
...
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'demoController' method
org.example.restdemo.DemoController#postAccount(SavingsAccount)
to {POST [/account]}: There is already 'demoController' bean method
org.example.restdemo.DemoController#postAccount(CurrentAccount) mapped.
What you can do is use inheritance, meaning you let your method receive a common base class of SavingsAccount and BankAccount and add a discriminator property, so Spring is able to use the corresponding type automatically (it won't work without it). This is equivalent to using oneOf with discriminator in an OpenAPI definition.
A minimal example for the base class with an accountType discriminator could look like this (the annotations are from package com.fasterxml.jackson.annotation):
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "accountType")
@JsonSubTypes({
@JsonSubTypes.Type(value = CurrentAccount.class, name = "currentAccount"),
@JsonSubTypes.Type(value = SavingsAccount.class, name = "savingsAccount")
})
public interface BaseAccount {
public String getAccountType();
}
Your SavingsAccount and BankAccount would need to have implements BaseAccount.
And a minimal example of the corresponding postAccount method:
@PostMapping(value = "/account", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> postAccount(BaseAccount account) {
if (account instanceof SavingsAccount savingsAccount) {
// process savingsAccount
}
else if (account instanceof CurrentAccount currentAccount) {
// process currentAccount
}
else {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}
return ResponseEntity.ok().build();
}
However, personally, I do not recommend to do it that way. It bears the risk of accidental invalid submissions from your API consumers, if validation is not implemented carefully. Since your API consumers should know which account type they want to submit, they should be able to call a distinct endpoint /savingsAccount or /currentAccount respectively.