Should the name of a @ModelAttribute be the same as a model before it would be saved in a session? I have a an attribute with a different name from the model but it is not saving in the session.
DesignTacoController
@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("tacoOrder")
public class DesignTacoController {
@ModelAttribute(name = "tacoOrder")
public TacoOrderData order(){
return new TacoOrderData();
}
@ModelAttribute(name = "taco")
public TacoData taco(){
return new TacoData();
}
@GetMapping
public String showDesignForm(){
return "view/design";
}
@PostMapping
public String processOrder(@Valid TacoData taco,
Errors errors, @ModelAttribute TacoOrderData tacoOrder, HttpSession Session){
if (errors.hasErrors()){
return "view/design";
}
tacoOrder.addTaco(taco);
System.out.println("Processing taco: {}", taco);
System.out.println("tacoOrder model in session: "+ Session.getAttribute("tacoOrder"));
return "redirect:/orders/current";
}
}
OrderController
@Slf4j
@Controller
@RequestMapping("/orders")
@SessionAttributes("tacoOrder")
public class OrderController {
@GetMapping("/current")
public String orderForm(){
return "view/orderForm";
}
@PostMapping
public String processOrder(@Valid TacoOrderData order,
Errors error, SessionStatus sessionStatus) {
if (error.hasErrors()){return "view/orderForm";}
log.info("Order submitted: {}", order);
sessionStatus.setComplete();
return "redirect:/";
}
}
Taco Model
@Data
public class TacoData {
private Long id;
private Date createdAt;
@NotNull
@Size(min = 5, message = "Name must be at least 5 characters long")
private String name;
@NotNull
@Size(min = 1, message = "You must choose at least 1 IngredientData")
private List<IngredientData> ingredients;
}
TacoOrder Model*
@Data
public class TacoOrderData {
private Long id;
private Date placedAt;
private String deliveryName;
private String deliveryCity;
private String deliveryStreet;
private String deliveryState;
private String deliveryZip;
private String ccNumber;
private String ccExpiration;
private String ccCVV;
private List<TacoData> tacos = new ArrayList<>();
public void addTaco(TacoData taco){
this.tacos.add(taco);
}
}
Results when Post action in DesignTacoController is executed
Processing taco: TacoData(id=null, createdAt=null, name=tacos, ingredients=[IngredientData(id=FLTO, name=Flour Tortilla, type=WRAP), IngredientData(id=CHED, name=Cheddar, type=CHEESE), IngredientData(id=SLSA, name=Salsa, type=SAUCE)])
tacoOrder model in session: TacoOrderData(id=null, placedAt=null, deliveryName=null, deliveryCity=null, deliveryStreet=null, deliveryState=null, deliveryZip=null, ccNumber=null, ccExpiration=null, ccCVV=null, tacos=[])
In Spring MVC, when you use
@SessionAttributesto store a model attribute in the session, the name specified in@ModelAttribute(name = "...")should match the name of the attribute in the model. In your case, it seems that the names do not match:DesignTacoController, you have:Here, you are specifying the names "tacoOrder" and "taco" for your model attributes.
processOrdermethod, you are using the@ModelAttributeannotation without specifying the name:In this method, you should specify the name using
@ModelAttribute("tacoOrder")to match the name specified in@SessionAttributes.Here's the modified
processOrdermethod:With this change, Spring will correctly associate the "tacoOrder" attribute in the session with the
tacoOrderparameter in yourprocessOrdermethod. Make sure to apply a similar change if needed in yourOrderControlleras well.Also, ensure that your view templates are using the correct attribute names when rendering the forms, as the name consistency is crucial for the data to be properly saved and retrieved from the session.