Spring MVC Form Object Dont Initialize Correct Data - java

I have developed part of a application with Spring MVC.
In here i am loading some values from database to this jsp.
<div class="row">
<div class="col-sm-4">
<label class="input-label">Answer</label>
</div>
<div class="col-sm-8">
<div class="input-group">
<form:input class="form-control required" type="text" id="securityQuestionAnswer1" path="userSecurityQuestionList[0].securityQuestionAnswer"/>
</div>
</div>
</div>
This Jsp have one form and two submit buttons. I have added two different names and call the controller via those names.
and catch it with
#RequestMapping(method = RequestMethod.POST, params = {"next"})
#RequestMapping(method = RequestMethod.POST, params = {"update"})
after changing first loaded values in jsp (Security answer) when i submit the form it comes to correct controller. but it dont catch changed data in that text inputs. it catches old data what loaded when jsp loads. I have gone many debug tests. but same result.
my controller method is like this
#RequestMapping(method = RequestMethod.POST, params = {"update"})
public String updateSecurityQuections(#Valid #ModelAttribute(value = "userForm")ForogtPasswordForm forogtPasswordForm, BindingResult result,
ModelMap model, final RedirectAttributes redirectAttributes) throws AccountAlreadyRegisteredException,
AccountNotFoundException {
I want to know how to correctly catch(initialize) all the correct input data to this form in controller class.
Thanks in advance

Try putting method parameters in following order. It worked for me, sounds like yours is similar case.
RequestMapping(method = RequestMethod.POST, params = {"update"})
public String updateSecurityQuections(ModelMap model,#Valid #ModelAttribute(value = "userForm")ForogtPasswordForm forogtPasswordForm,
BindingResult result,
final RedirectAttributes redirectAttributes) throws AccountAlreadyRegisteredException,
AccountNotFoundException {

Related

How to bind form data into a model using Spring Boot?

I have this form:
<form action="/my-path" method="post">
<div class="form-group">
<label for="domain">Domain</label>
<input class="form-control" id="domain" type="text" value="" name="domain">
<label for="color">Color</label>
<input class="form-control" id="color" type="text" value="" name="color">
</div>
<button class="btn btn-primary" type="submit">Filter</button>
</form>
which I'm trying to process in Spring MVC:
#PostMapping(
path = ["/my-path"],
produces = [MediaType.TEXT_HTML_VALUE])
public ResponseEntity<String> doSomething(ModelMap map) {
// ...
}
but I just can't get this working, I see no data coming from the POST even when I fill the form with data and submit it.
I tried binding the values to my own dto:
#PostMapping(
path = ["/my-path"],
produces = [MediaType.TEXT_HTML_VALUE])
public ResponseEntity<String> doSomething(#RequestBody MyDto dto) {
// ...
}
but in this case I get an exception because the method is unsupported (url encoded form). I'm at a loss here, I've tried 10 different ways to get the form data out of the request but it doesn't work, I either get exceptions or I get no data at all.
How do I make this pretty basic use case working with Spring Boot?
If you want to get all the request parameters in a map, you can add a #RequestParam Map parameter to the function, like this:
#PostMapping(
path = ["/my-path"],
produces = [MediaType.TEXT_HTML_VALUE])
public ResponseEntity<String> doSomething(#RequestParam Map allRequestParams) {
// ...
}
If you want to get each form component in a different variable, you could use something like this:
#PostMapping(
path = ["/my-path"],
produces = [MediaType.TEXT_HTML_VALUE])
public ResponseEntity<String> doSomething(String domain, String color) {
// ...
}
Spring automagically will bind the form inputs to your parameters matching the inputs 'id' attribute with the parameter names.

How to add validation to a spring boot java form

I currently have the following method within my controller that takes the users form input and passes it to an SQL query to return a list of matches.
#RequestMapping(value = "/resultsPage", method = RequestMethod.GET)
public ModelAndView newSearch(HttpServletRequest request)
{
int id = Integer.parseInt(request.getParameter("id"));
List<newobject> listSearch = newDAO.loadSearch(id);
ModelAndView model = new ModelAndView("results");
model.addObject("listSearch", listSearch);
return model;
}
I have added #NotNull to the ID filed in the newObject however I am unsure on how to modify my method above to check the variable entered (or not entered) by the user.
I am also unsure how to display the error on the html page. My existing code is below:
<form method="get" th:action="#{/results}">
<input id="search" name="id" class="search" placeholder="Ref..."
type="text" maxlength="10" title="Numerical values only" />
<button type="submit" method="post" style="display:none;" id="search">Search</button>
</form>
Can anyone give me some advice on how I would add the validation as I am just getting errors with everything I try.

How to get inputs from thymeleaf without Ambigous Handler error?

I am trying to get a value from thymeleaf input into my java class.
Simple script from thymeleaf
<h1>Form</h1>
<form action="#" th:action="#{/index}" th:object="${emails}" method="post">
<p>Enter Emails: <input type="text" th:field="*{email}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
How would I be able to retrieve emails into my java class?
Controller
#Controller
#RequestMapping(method = RequestMethod.GET)
public class IndexController {
#RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView getdata() throws IOException {
ModelAndView model = new ModelAndView("index");
model.addObject("emails", new MailModel());
return model;
}
#PostMapping("/index")
public String emailSubmit(#ModelAttribute MailModel emails) {
System.out.println(emails.getEmail());
return "index";
}
Error Message
Ambiguous handler methods mapped for HTTP path 'http://localhost:8080/': {public org.springframework.web.servlet.ModelAndView com.spring.web.controller.IndexController.getdata() throws java.io.IOException, public java.lang.String com.spring.web.controller.IndexController.emailSumbit(com.spring.web.model.MailModel)}
My Application is created with Springboot, Java, and Thymeleaf. What am I doing wrong? Is it possible that ModelandView does not work with PostMapping? I also followed https://spring.io/guides/gs/handling-form-submission/ and I got that sample working, but when I tried to follow the logic and implement into my project. It did not work.
Before declaring your controller, you are setting the RequestMethod to GET everywhere. On the methods you are setting them again, which is ambigous.
Remove the #RequestMapping(method = RequestMethod.GET) in line 2. This should fix the mentioned problem.

Spring Form Tag Error (Binding Result)

I am teaching myself Spring Form tags, and have run into what is probably a simple error that I haven't been able to solve. I get the following error when I launch this app in a browser:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'index' available as request attribute
I've tried most of the fixes that came up in a Google search to no avail. Can someone spot where I went wrong? Below are the relevant components. Thanks very much.
Controller:
#Controller
#RequestMapping("/registration")
public class LoginController {
#RequestMapping(method = RequestMethod.GET)
public String setupForm(ModelMap model) {
Registration registration = new Registration();
model.addAttribute("registration", registration);
return "index";
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, Map model) {
return "success";
}
}
JSP (/index.jsp):
<form:form commandName="index">
<table border="0" cellspacing="12">
<tr>
<td>
<form:input path="email"/>
</td>
</tr>
<tr>
<td>
<form:password path="password"/>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
Command Object (Registration.java) :
public class Registration {
private String password;
private String email;
// getters,setters
Facing same issue few days back, What i understood from hit and trail is, Index page is a static page and no processing happens before the same is rendered. In case i want to use a form model binding in index page i should have a controller's handler method which will create a Registration object and place the same in ModelAndView before index.jsp is rendered
add a method in your controller like the below and try
#RequestMapping(method = RequestMethod.GET, value="/")
public ModelAndView initiate(){
ModelAndView objModView = new ModelAndView("/index.jsp");
objModView.addObject("registration",new Registration());
return objModView;
}
In your index page correct the following and try
<form:form commandName="index"> to <form:form commandName="registration">
You can also do it like this if the above does not work
<form:form modelAttribute="registration" commandName="registration">
Thanks
The error which is seen is because when you submit the form you have to have a Binding Result associated with the #ModelAttribute annotation.
Try changing you code to this :
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, BindingResult result, Map model){
return "success";
}
Also note that the Binding Result object should be followed immediately after the Model Attribute.
And if you are using two #ModelAttributes then each one should have its own binding result object which follows it.
Please refer the spring source guide for all the related documentation
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html

Problems getting spring:bind status.errorMessage to populate

I've got a Groovy project using Spring framework and its validators doing sanity-checking on my forms' input values. I would like to have Spring populate error messages next to my input form fields via the built-in ${status.errorMessage}; however, I can only get it to populate "errorMessages" in my Model object (from the controller.) So let's take a look at some code.
login.jsp:
<form method="post" action="<c:url value="/login" />">
<spring:bind path="request.username">
<label for="username"><fmt:message key="login.username"/>:
<input type="text" id="username" size="20" maxlength="50" name="username" value="${request.username}"/>
</label>
<%-- This part does NOT display the validation errors. --%>
<c:if test="${status.error}"><span class="error">${status.errorMessage}</span></c:if>
</spring:bind>
<spring:bind path="request.password">
<label for="password"><fmt:message key="login.password"/>:
<input type="password" id="password" size="20" maxlength="30" name="password" />
</label>
<%-- This part does NOT display the validation errors. --%>
<c:if test="${status.error}"><span class="error">${status.errorMessage}</span></c:if>
</spring:bind>
<input id="login" type="submit" value="Login"/>
</form>
<%-- This part does display the validation errors. --%>
<c:if test="${ec > 0}">
<p>
<c:forEach items="${errorCodes}" var="error">
<span class="error"><fmt:message key="${error.defaultMessage}"/></span><br/>
</c:forEach>
</p>
</c:if>
LoginController.groovy:
#RequestMapping(method = RequestMethod.GET, value = '/')
ModelAndView defaultView() {
ModelMap model = new ModelMap()
model.addAttribute('request', new LoginRequest())
new ModelAndView('login', model)
}
#RequestMapping(method = RequestMethod.POST, value = '/login')
ModelAndView login(
LoginRequest loginRequest, HttpServletResponse response,
HttpSession session, BindingResult br, ModelMap model
) {
validator.validate(loginRequest, br)
if (br.hasErrors()) {
model.addAttribute('request', loginRequest)
return returnWithError(br, model, 'login')
}
...
}
private ModelAndView returnWithError(BindingResult br, ModelMap model, String redirectTo) {
br.allErrors.each {error ->
log.error(error.toString())
}
def objectErrors = br.allErrors.findAll {e -> e instanceof ObjectError}
model.addAttribute('ec', br.errorCount)
model.addAttribute('errorCodes', objectErrors)
new ModelAndView(redirectTo, model)
}
LoginRequestValidator.groovy:
#Override
void validate(Object o, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, 'username', 'username.empty', 'username.empty')
ValidationUtils.rejectIfEmpty(errors, 'password', 'password.empty', 'password.empty')
}
Which part of the Spring Magic [TM] am I missing?
I think your BindingResult object should be the argument immediately following your LoginRequest object. See http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html#mvc-ann-requestmapping and specifically Example 15.1. Invalid ordering of BindingResult and #ModelAttribute
Review the Javadoc on #RequestMapping as I find it the best on the subject:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/bind/annotation/RequestMapping.html
Try the following:
ModelAndView login(
#Valid LoginRequest loginRequest, HttpServletResponse response,
HttpSession session, BindingResult br, ModelMap model
) {}
See What does the #Valid annotation indicate in Spring?
If that doesn't work you should try translating some of your code to plain Java and running the debugger to see whats happening (I know its not an answer but just an idea).
Maybe you will find these post from kgiannakakis very usefull.
It explains the purpose of these functionnality and how to deal with is explained in Spring 3.1 documentation.
Adding something like that will probably do the trick, isn't it ?
#Controller
public class MyController {
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new FooValidator());
}
#RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo(#Valid Foo foo) { ... }
}
Take a look at SpringSource blog and especially these post about new features around data binding. It could add some new look about your validation process.

Categories

Resources