Spring ModelAttribute not biding values Tomcat 9, Spring 5 MVC - spring-mvc

I migrated from Spring 3 to 5, upgraded to Tomcat 9. After upgrading not able to get the values from JSP to Controller. #ModelAttribute is not binding the values entered in JSP, while submitting the form.
JSP Code:
<form:form action="/login" modelAttribute="identity" id="loginForm" cssClass="clearfix nodisplay">
<div class="grouping text">
<label for="email">E-mail Address</label>
<form:input path="email" id="email" cssClass="regInput" cssErrorClass="error" />
<form:errors path="email" cssClass="errors" />
</div>
<div class="grouping text">
<label for="pwd">Password</label>
<form:password path="pwd" id="pwd" cssClass="regInput" cssErrorClass="error" autocomplete="off" />
<form:errors path="pwd" cssClass="errors" />
</div>
<div class="grouping remember">
<input type="checkbox" name="remember" id="remember" />
<label for="remember">Remember Me</label>
</div>
<div class="btns clearfix">
<span class="login-btn">
<input type="hidden" name="cookieExist" id="cookieExist" value="false" />
<button type="button" name="login" class="btn js-login-btn"><span class="pictos">K</span> Login</button>
</span>
<span class="password-forget">
I forgot my password
</span>
</div>
</form:form>
Controller Code
#Controller
public class LoginController {
#RequestMapping(method=RequestMethod.GET, value="/login")
public String loginGet(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap,
#ModelAttribute Identity identity){
// commented business logic code
return "login";
}
#RequestMapping(method=RequestMethod.POST, value="/login")
public String loginPost(HttpServletRequest request, HttpServletResponse response,
ModelMap modelMap, #ModelAttribute("identity") Identity identity, BindingResult bindingResult) {
//commented out business logic
return "dashboard";
}
#ModelAttribute("identity")
public Identity formBackingObject() {
return new Identity();
}
}
I have migrated with no webxml way, not sure what else i'm missing here?

No need of action here in the form tag. Mention method in the form tag. So chnage to:
<form:form modelAttribute="identity" method="post" id="loginForm" cssClass="clearfix nodisplay">
And also change your primary action button to:
<input type="submit" ... />

Related

How to pass a js variable to the controller in ASP.NET Core

I am sending an id in my js code and I want to pass that variable to my controller. Any advice on how I can do that?
<input class="btn_confirm" type="submit" id={i}
onclick="id_click(this.id)" value="Delete" />
var id;
function id_click(clicked_id) {
id = clicked_id;
}
I tried different things but nothing worked out.
I tried as below:
Model:
public class ReceiveModel
{
public int Id { get; set; }
public string Name { get; set; }
public string SomeKey { get; set; }
}
View:
<div class="row">
<div class="col-md-4">
<form id="form" asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input id="1" type="submit" value="Create" class="btn btn-primary" />
</div>
<div class="form-group">
<input id="2" type="submit" value="Create" class="btn btn-primary" />
</div>
<div class="form-group">
<input id="3" type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
$("input[type='submit']").click(function ()
{
var tempid = this.id
var tmpInput = $("<input type='text' name='SomeKey' hidden/>");
tmpInput.attr("value", tempid );
var form = $("#form")
form.append(tmpInput)
form.submit()
})
</script>
Result:
You can lookup API requests. If you want to send one parameter as a primitive type (string, integer, etc.) you can use query strings in your API calls. For example, let's assume you have an API endpoint like this: localhost:5000/api/YourController. You can send params via API get calls like this localhost:5000/api/YourController?yourParam=<param-value>. In this example your API call type is GET.
If you want to send complex types (like classes, objects) to your controller you can lookup POST API requests.
You can find more details in this documentation.

Spring MVN Controller works in GET but does not in POST

I have this simple Controller
#Controller
#RequestMapping("/login")
public class LoginController {
private ModelAndView model;
#RequestMapping(value="/loginUser/{username}/{password}", method=RequestMethod.GET)
public ModelAndView loginUser(#PathVariable(value="username") String username, #PathVariable(value="password") String password) {
try {
if( checkCredential( username , password ) ) {
model = new LoginResult( "loginOK" );
model.addObject( "msg" , username );
} else {
model = new LoginResult( "loginKO" );
model.addObject( "msg" , "Impossible to login the user " + username );
}
} catch(Exception e) {
e.printStackTrace();
}
return model;
}
}
and this simple JSP to execute the login
<form method="get" action="/login/loginUser">
<div class="div-top-end-space"> </div>
<div>
<label class="form-label"><i class="fa fa-chevron-right fa-1"></i> USERNAME:</label>
<input class="form-input" type="text" name="username" ng-model="username" />
</div>
<div>
<label class="form-label"><i class="fa fa-chevron-right fa-1"></i> PASSWORD:</label>
<input class="form-input" type="password" name="password" ng-model="password" />
</div>
<div class="div-separator"></div>
<div>
<input type="submit" value="LOGIN" ng-disabled="checkCredential()"/>
</div>
<div class="div-top-end-space"> </div>
</form>
This code works properly, but I have to put into the URL
http://localhost:9001/MY_APP/login/loginUser/aaa/bbb
But I do not want that username and password are shown into the browser's URL.
So I change the method into the form in method="post" and into the controller, method="RequestMethod.POST".
When I run my application and I insert my username and password, it does not work, and into the URL I see this
http://localhost:9001/login/loginUser
Where did my application's name go???
How I can solve it?
Thanks to everybody.
Daniele.

spring+ thymeleaf unable to update

Hi I am working with spring MVC and thymeleaf and I am not able to update data from my controller as I have following code.The main problem I am facing is that my put method is not getting called.
#GetMapping("/{id}/edit")
public String editUser(#PathVariable("id") int id, Model model) {
logger.info("++++++++++++[edit User]\n\n" + userService.findById(id));
model.addAttribute("user", userService.findById(id));
return "user/edit";
}
#PutMapping("/{id}/edit")
public String updateUser(#PathVariable("id") int id, #ModelAttribute("user") User user, Model model) {
logger.info("\n\n+++++++++++++++++inside Update");
User toUpdate = userService.findById(user.getId());
user.setUserName(user.getUserName() != null ? user.getUserName() : toUpdate.getUserName());
user.setName(user.getName() != null ? user.getName() : toUpdate.getName());
logger.info(user.toString());
userService.updateUser(user);
model.addAttribute("user", userService.findById(user.getId()));
return "redirect:/user/" + id;
}
and my html page
<form action="#" th:action="#{/user/__${user.id}__}" method="put"
th:object="${user}">
<div class="form-group">
<label for="txtUserName">User-name</label> <input
class="form-control" id="txtUserName" placeholder="User Name"
th:feild="${user.userName}" />
</div>
<div class="form-group">
<label for="txtName">First Name</label> <input
class="form-control" id="txtName" placeholder="Full Name"
th:feild="${user.name}" />
</div>
<div class="form-group">
<label for="calDob">Date of Birth</label> <input
class="form-control" id="calDob" placeholder="dd/MM/yyyy" />
</div>
<button type="submit" th:method="put" class="btn btn-success">Update</button>
<a href="#" th:href="#{/user/__${user.id}__}"
class="btn btn-primary">Cancel</a> <a th:method="delete"
href="javascript:deleteUser('${user.id}');" class="btn btn-danger">Delete</a>
</form>
any help will be usefull thanks
PUT is not a valid argument for method attibute of the form tag. See HTML specification.
Valid methods are GET and POST. And as it's not a REST API, you can use POST method to update.
So just update your mapping from:
#PutMapping("/{id}/edit")
to
#PostMapping("/{id}/edit")
And form tag to:
<form action="#" th:action="#{/user/__${user.id}__}/edit" method="post" th:object="${user}">

Spring Boot with Thymeleaf post list

I want to post a list of strings to my controller.
But it always only take the first selected value.
my thymeleaf html form:
<form action="/add" method="post">
<div class="form-group">
<label for="roleId">ID</label> <input type="text" class="form-control" id="roleId" name="id" required="required" />
</div>
<div class="form-group">
<label for="rolePrivileges">Privileges</label>
<select class="form-control" id="rolePrivileges" name="privileges" multiple="multiple" size="10" required="required">
<option th:each="type : ${privilegesList}" th:value="${type}" th:text="${type}">Privilege</option>
</select>
</div>
<button type="submit" class="btn btn-default">Create</button>
</form>
my controller:
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addSomething(Model model, #ModelAttribute("id") String id,
#ModelAttribute("privileges") List<String> privileges) {
// add something with a service
return "redirect:/roles";
}
I think you have to Annotate the privilges with
#RequestParam("privileges")
It is not a ModelAttribute but you receive it from the request
Edit: two SO threads to better understand the difference between #RequestParam and #ModelAttribute.

multi form - form tag in foreach

In Spring MVC, I want to create multi form in same page. According to me, ıt is logically true. But it gives error as
ERROR: org.springframework.web.servlet.tags.form.HiddenInputTag -
Neither BindingResult nor plain target object for bean name 'cost'
available as request attribute
Controller
#RequestMapping(value = { "/vehicle_cost" }, method = RequestMethod.GET)
public String vehicleCost(Model model, #RequestParam(defaultValue="0") int vId) {
List<CostModel> _costs = null;
List<CurrencyModel> _currencies = accountingService.getCurrencyList();
List<IdElemModel> _cost_per_types = accountingService.getCostPerTypeList();
if(vId > 0){
_costs = operationService.getVehicleCostsByVehicleId(vId);
}
else{
}
model.addAttribute("costs", _costs);
model.addAttribute("currencies",_currencies);
model.addAttribute("cost_per_types",_cost_per_types);
return "vehicle_management/vehicle_cost";
}
View
<c:forEach items="${costs}" var="cost">
<form:form commandName="cost" method="POST" action="save_vehicle_cost" cssClass="form-horizontal" role="form">
<form:hidden path="costId" />
<form:hidden path="costCategoryId" />
<div class="form-group">
<div class="col-lg-2">
<form:input path="cost" cssClass="form-control" />
</div>
<div class="col-lg-1">
<form:input path="taxRatio" cssClass="form-control" />
</div>
<div class="col-xs-2">
<form:select path="currencyId" cssClass="form-control">
<option value="-1">Currency</option>
<form:options items="${currencies}" itemLabel="currency"
itemValue="currencyId" />
<form:options/>
</form:select>
</div>
<div class="col-lg-2">
<form:select path="costPerTypeId" cssClass="form-control">
<option value="-1">Per Type</option>
<form:options items="${cost_per_types}" itemLabel="elem"
itemValue="id" />
<form:options/>
</form:select>
</div>
<div class="col-lg-2">
<form:input path="periodBegin" cssClass="form-control dateInput" />
</div>
<div class="col-lg-2">
<form:input path="periodEnd" cssClass="form-control dateInput" />
</div>
<div class="col-lg-1"><button type="submit" class="btn btn-success">SAVE</button>
</div>
</div>
</form:form>
</c:forEach>
The form is expecting "cost" to be in the request, but your loop is not putting the object in the correct scope. Following standard Spring MVC pattern to prepopulating command objects in the controller, you can just preload them:
In your controller put each cost object into the correct scope, by loading them with a key like "cost_" + id:
for(CostModel c: _costs) {
model.addAttribute("cost_" + c.getId(), c);
}
In your jsp when you render the form, look for a "cost_${id}" in the request scope:
<c:forEach items="${costs}" var="cost">
<form:form commandName="cost_${cost.id}" method="POST" action="save_vehicle_cost" cssClass="form-horizontal" role="form">
...
...
</c:forEach>
I hope that helps.

Resources