Spring portlet MVC. Validation before #ResourceMapping. #ResourceMapping -> #RenderMapping - validation

My case: a user can download files. There is a list of files he can select.
There is a spring mapping:
#ResourceMapping(DOWNLOAD)
public void downloadSelected(ResourceRequest request, ResourceResponse response, AuditView auditView, BindingResult bindingResult) {
}
auditView has a list of files.
If user didn't select any I need to validate and display the same page with error displayed.
i can validate: validator.validate(auditView, bindingResult);
The question is how to forward to Render phase in case of errors?

It might be late to answer but, It may be helpful to others.
There is no way you can forward a Request to RenderPhase from ResourcePhase.
Please refer this link for a solution to a similar requirement.

I only tested this with WebSphere Liberty Profile's portlet container, so I don't know if it works with other containers:
#ResourceMapping
public void downloadSelected(#Valid #ModelAttribute("entity") Entity entity, BindingResult bindingResult, ResourceResponse response)
{
if (bindingResult.hasErrors()) {
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, "302");
response.setProperty("Location", response.createRenderURL().toString());
} else {
response.setContentType("application/pdf");
response.setProperty("Content-disposition", "attachment; filename=\"mydownload.pdf\"");
/* ... */
}
}
However, it seems, that binding result gets lost and error messages aren't appearing in the render phase if Spring MVC's <form:errors /> JSP tag is used.

just check for errors and return the form view and annotate the AuditView with #Valid and #ModelAttribute anotations. #Valid annotation will triger validate method of controler validator. #ModelAttribute will put the AuditView into the model.
#ResourceMapping(DOWNLOAD)
public void downloadSelected(ResourceRequest request, ResourceResponse response,#Valid #ModelAttribute("auditView") AuditView auditView, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "thedownloadpage";
}

Related

Can we use BindingResult for REST API in Spring?

Usually, BindingResult is used in Spring MVC for the form validation. Recently I came to know that some developers are using BindingResult in the Spring REST API as well. I went through the official document but it's not clear to me whether it would be allowed to use BindingResult in REST API or not.
Any thoughts, please?
Of course it is allowed to use BindingResult in a RestAPI, especially if you have a Front-End and you want to do the validation of data in the back end.
A very simple example:
#PostMapping("/signup")
public ResponseEntity signUp(#Valid #RequestBody RegisteringUserDto registeringDto, BindingResult bindingResult)
{
if (bindingResult.hasErrors())
{
bindingResult
.getFieldErrors()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
return authService.signUp(registeringDto);
}
This is just printing the errors in the Console, but you can send them to the front end via the ResponseEntity.

How to stay at the same page if BindingResult has errors in Spring MVC

I would like to stay at the same page with the filled form with "wrong" data, if binding result has errors. I have this code, but i got npe and null object "employeeTripOrder". What i do wrong? I can't use the RedirectAttributes cause i have old spring version.
#RequestMapping("/editEmployeeTripOrder")
public String editEmployeeTripOrder(HttpServletRequest request,
#RequestParam("trip_cards") String tripCards,
#RequestParam("dependenceTypes") String dependenceType,
#RequestParam("dependenceOrderIds") String dependenceOrderId,
#Valid #ModelAttribute("trip_order") EmployeeTripOrder employeeTripOrder,
BindingResult bindingResult,
ModelMap modelMap) throws Exception {
if (bindingResult.hasErrors()){
modelMap.addAttribute("trip_cards", tripCards);
modelMap.addAttribute("dependenceTypes", dependenceType);
modelMap.addAttribute("dependenceOrderIds", dependenceOrderId);
modelMap.addAttribute("trip_order",employeeTripOrder);
return "redirect:/editEmployeeTripOrder";}
//*** }

Spring 4 MVC: passing multiple #modelattributes trough controllers

I'm looking for a solution to pass 2 #ModelAttributes from my GET controller to my POST controller without using Session. I'm using Spring Boot and Thymeleaf.
My view is bound only to one of those but the second controller need to use them both. The problem is that the second controller reinitialize the #ModelAttribute not used in view.
The controller:
//in this controller I've initialized the first #modelAttribute
#RequestMapping(value="/simulations", method=RequestMethod.POST)
public String checkSimulationsManagerForm(#Valid #ModelAttribute("sim_manager") Simulations_manager sim_manager, BindingResult bindingResult, final RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
return "set_simulations-manager_form";
}
redirectAttributes.addFlashAttribute("sim_manager", sim_manager);
return "redirect:/simulations2";
}
//GET
#RequestMapping(value="/simulations2", method=RequestMethod.GET)
public String showSimulationsClassForm(#ModelAttribute("sim_class") Simulations_class sim_class, #ModelAttribute("sim_manager") Simulations_manager sim_manager){
//Do some stuff
return "set_simulations-class_form";
}
//POST that reinitilize the firse #ModelAttribute
#RequestMapping(value="/simulations2", method=RequestMethod.POST)
public String checkSimulationsClassForm( #Valid #ModelAttribute("sim_class") Simulations_class sim_class, BindingResult bindingResult,#ModelAttribute("sim_manager") Simulations_manager manager,final RedirectAttributes redirectAttributes) {
//ERROR IS HERE, manager attributes are all null, even if they were not.
}
The view:
<form action="simulations2" th:action="#{/simulations2}" th:object="${sim_class}" method="post">
…
</form>

Handle (TaskId) Redirect in Spring MVC

User's controllers needs to concatenate the task ID to be obtained in a .js that is loaded by the Architecture (me) when the view is loaded. This mechanism is necessary to tasks control. In this context:
#RequestMapping(method = RequestMethod.POST)
public String create(#Valid Vote vote, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
uiModel.addAttribute("vote", vote);
addDateTimeFormatPatterns(uiModel);
return "votes/create";
}
uiModel.asMap().clear();
vote.persist();
return "redirect:/votes/" + encodeUrlPathSegment(vote.getId().toString(), httpServletRequest) +
"**?ArcSpring.idTask=" + httpServletRequest.getParameter("ArcSpring.idTask")**;
}
Is there a way to handle this redirect in the way I can concatenate the task ID to make it transparent for users?
I tried with a customized class extending from UrlBasedViewResolver, capturing the url and adding the attributes by my own, but with no kind of success.

Spring #ActionMapping syntax for Portlets

I know this works where the url contains the parameter 'deleteItem=6'
#ActionMapping(params="deleteItem")
public void deleteItem(#ModelAttribute("items") Items items, BindingResult bindingResult, #RequestParam int deleteItem) throws Exception {
items.getItems().remove(deleteItem);
...
}
but can I do something like this (use the value of the deleteItem parameter:
#ActionMapping(params="deleteItem={idx}")
public void deleteItem(#ModelAttribute("items") Items items, BindingResult bindingResult, #RequestParam int idx) throws Exception {
items.getItems().remove(idx);
...
}
No biggie, it's that the code is more readable because it shows that the parameter value is an index.
Thanks.
No, you can't use a dynamic param as a binding name like this #ActionMapping(params="deleteItem={idx}") because Spring Portlet MVC needs to bind a method to an action with a unique name.
Your first snippet is correct.

Resources