I am trying to create an immutable DTO.
Therefore I have added the @Builder
and @Getter
Lombok annotation for creating immutable objects from Pizza.class
. To prevent the ingredients field to be initialized with a mutable List, I have added the @Singular
Lombok annotation.
DTO
@Builder
@Getter
public class Pizza {
private final String name;
@Singular
private final List<String> ingredients;
}
Now if I create an API endpoint and try to send a pizza JSON to that endpoint, it somehow gets unmarshalled by Spring, but the result of that process is a mutable ingredient list.
Controller
@RestController
@RequestMapping("/api/v1/demo")
public class DemoController {
@PostMapping("/pizza")
Pizza addPizza(@RequestBody Pizza pizza) {
pizza.getIngredients().add("Honey");
return pizza;
}
}
Request/ Response
Request body:
{
"name": "Hawaii",
"ingredients": ["Pineapple"]
}
Response body:
{
"name": "Hawaii",
"ingredients": [
"Pineapple",
"Honey"
]
}
The below code snippet is throwing a java.lang.UnsupportedOperationException
, which indicates to me that the ingredients field is an unmodifiable list.
Code snippet
var ingredients = new ArrayList<String>();
ingredients.add("Pinapple");
var pizza2 = Pizza.builder().name("Hawaii").ingredients(ingredients).build();
pizza2.getIngredients().add("Honey");
My questions:
- How is Spring Boot doing the marshalling/ unmarshalling of the request body/ response body?
- How can I prevent Spring Boot from initializing the ingredients field with a modifiable list?