Form values are null in post request in play framework - java

I have html to post back a form, like this:
#(message: String)
#main("Contact") {
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/contact.css")">
<div id="pageContainer">
<div id="form">
<div id="topText">
<p>Have a question or need some assistance? Let us know and we'll get back to you ASAP.</p>
</div>
<br/>
<form method="POST" action="#routes.Home.contact()">
<div id="contactInfo">
<label class="contactLabel">First Name:</label><input type="text" name="firstName" id="firstName" class="contactInput" /> <br />
<label class="contactLabel">Last Name:</label><input type="text" name="lastName" id="lastName" class="contactInput" /> <br />
<label class="contactLabel">Email:</label><input type="text" name="email" id="email" firstName" class="contactInput" /> <br />
<label class="contactLabel">Company:</label><input type="text" id="company" name="company" class="contactInput" /> <br />
<input type="hidden" id="hidden" name = "hidden"></input>
<p id="crap">#message</p>
</div>
<br/>
<div id="message">
<label class="contactLabel">Message:</label><textarea cols="50" rows="10"></textarea>
</div>
<input type="submit" name="submit" id="submit" value="Submit"></input>
</form>
</div>
</div>
}
Back in the controller, it looks like this:
public static Result contact()
{
//Map<String,String[]> values = request().body();
DynamicForm form = form().bindFromRequest();
String first = "";
if(form.data().get("firstName") != null)
first = form.data().get("firstName").toString();
return ok(views.html.contact.render(first));
}
But when I look through the result of form().bindFromRequest(), it is always empty. Am I missing something?

Here is how I would do that:
template
#(message: String, contactForm: Form[Contact])
#import helper._
#main("Contact") {
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/contact.css")">
<div id="pageContainer">
<div id="form">
<div id="topText">
<p>Have a question or need some assistance? Let us know and we'll get back to you ASAP.</p>
</div>
<br/>
#form(routes.Home.contact()) {
<div id="contactInfo">
<label class="contactLabel">First Name:</label> #inputText(contactForm("firstName"), 'class -> "contactInput"') <br />
<label class="contactLabel">Last Name:</label> #inputText(contactForm("lastName"), 'class -> "contactInput"') <br />
<label class="contactLabel">Email:</label> #inputText(contactForm("email"), 'class -> "contactInput"') <br />
<label class="contactLabel">Company:</label> #inputText(contactForm("company"), 'class -> "contactInput"') <br />
<input type="hidden" id="hidden" name="hidden"></input>
<p id="crap">#message</p>
</div>
<br/>
<div id="message">
<label class="contactLabel">Message:</label><textarea cols="50" rows="10"></textarea>
</div>
<input type="submit" value="Submit" />
}
</div>
</div>
}
Class Contact
public class Contact {
public String firstName;
public String lastName;
public String email;
public String company;
// other stuff
}
Controller
public static Result contact() {
Form<Contact> contactForm = form(Contact.class).bindFromRequest();
if (contactForm.hasErrors()) {
// process
} else {
// contactForm.get().firstName should be filled with the correct data
return ok(views.html.contact.render("message", contactForm));
}
}
Does it work for you ?
You should take a look at the Play2 documentation about these topics:
JavaForms
JavaForm Helpers
Edit
if you can explain why the way I was doing it previously didn't work
I'm not sure about that, but I can see one problem in your code, you don't have to call data() on the dynamic form, using directly DynamicForm.get() is sufficient, so first = form.get("firstName") is sufficient.
Besides as you can see from the DynamicForm Javadoc
get(java.lang.String key)
Gets the concrete value if the submission was a success.
The internal map behind DynamicForm has values if there is no errors, so you may check with hasErrors before actually getting concrete values from field.
From my point of view, it is better and easier to use the form(Contact.class).bindFromRequest() style that will fill an instance of class Contact, this without saying that fields can be validated using Java annotations.

You must provide a Request to bindFromRequest() method. For example
DynamicForm form = form().bindFromRequest(request());
The request function provides the current Request for the current action.
Seems like bindFromRequest doesn't bind automatically the current Request
I was having the same problem and google brought me here, hope it helps.

Maybe not exactly the same problem but on my Windows developing Play 2.6 app I had similar issue. Binding did not work. I mean the Form's data field had proper values, but the values of model were empty. That was causing No such element exception: No value present. I've spent quite a while looking into this. What fixed the issue was cleaning project, recompiling and running it again. Ehh.

Related

How to get value from html input radio and put it in input hidden field in jsp java [duplicate]

This question already has answers here:
How to transfer data from JSP to servlet when submitting HTML form
(4 answers)
Closed 2 years ago.
I have the code for radio buttons
<input type="radio" name="opt" id="1" value="1"/><label for="1">${dto.quesOpt1}</label>
<br/>
<input type="radio" name="opt" id="2" value="2"/><label for="2">${dto.quesOpt2}</label>
<br/>
<input type="radio" name="opt" id="3" value="3"/><label for="3">${dto.quesOpt3}</label>
<br/>
<input type="radio" name="opt" id="4" value="4"/><label for="4">${dto.quesOpt4}</label>
And I want to put the value here so I can pass it to my Servlet
<form action="MainController" method="POST">
<input type="hidden" name="quesNum" value="${requestScope.QUESNUM}"/>
<input type="hidden" name="quesId" value="${dto.quesId}"/>
<input type="hidden" name="quesChoice" value="${param.opt}"/> <--------- here
<input type="hidden" name="amount" value="${requestScope.AMOUNT}"/>
<input type="hidden" name="action" value="Previous Question"/>
<input type="submit" value="Previous" <c:if test="${requestScope.QUESNUM == 0}">disabled</c:if>/>
</form>
I always get null value in Servlet
request.getParameter("quesChoice")
I don't know how to pass the value. Please guide me. Thank you.
What you're trying to do is execute server side code (like ${dto.quesId}) inside the browser. You cannot do that.
What you're trying to do is super nasty and is probably not the right way to go. You probably don't need to copy the values from the radio to the form as you can put the radios directly inside the form.
JSPs are a super old technology that most companies have already abandoned years ago and those that still use it, plan to abandon it.
If you really have to use JSPs, your life would be much easier if you used JSTL libraries and MKYoung has some awesome tutorial on how to handle a lot of old java issues, including the one you're struggling with right now: https://mkyong.com/spring-mvc/spring-mvc-radiobutton-and-radiobuttons-example/
If you say "fuck it, I want to code it the way I was planning to do that all along anyway", you still need JavaScript to copy your values as this is the JavaScript that handles the browser-side actions.
Having said all that, this is how you can do it with pure JS:
<html>
<script>
function copyValue() {
let allOptions = Array.prototype.slice.call(document.getElementsByName('opt'));
let selectedOption = allOptions.filter(opt => opt.checked)[0];
let selectedOptionValue = selectedOption ? selectedOption.value : undefined;
document.getElementById('quesNum').value = selectedOptionValue;
}
</script>
<body>
<input type="radio" name="opt" id="1" value="1"/><label for="1">${dto.quesOpt1}</label>
<br/>
<input type="radio" name="opt" id="2" value="2"/><label for="2">${dto.quesOpt2}</label>
<br/>
<input type="radio" name="opt" id="3" value="3"/><label for="3">${dto.quesOpt3}</label>
<br/>
<input type="radio" name="opt" id="4" value="4"/><label for="4">${dto.quesOpt4}</label>
<input type="hidden" name="quesNum" id="quesNum" value="${requestScope.QUESNUM}"/>
<input type="button" value="Copy Value" onClick="copyValue()"/>
</body>
</html>
Note how I had to add the id="quesNum" and then the onClick="copyValue()" to trigger an action.
Here's the example in JSFiddle if you want to play with it: https://jsfiddle.net/kgjanowski/5ymubn6v/22/

Why missing <fieldset> tag will cause controller cannot get form value?

I am developing a WebApp which uses Spring-MVC & Thymeleaf as template engine.
In my HTML,I got a form like this
<form action="/submit" method="POST">
First name: <input type="text" name="fname"/>
Last name: <input type="text" name="lname"/>
<input type="text" id="taskId" name="taskId" th:value="${taskId}" />
<input type="submit" value="Submit"/>
</form>
And I have a controller
#RequestMapping("/submit")
public void addUser(String taskId, String fname, String lname, ModelMap map) {
//save to db...
}
At first I expect taskId, fname, lname will contains the value from the form, but they are all null
Finally I try to wrap all the input field by <fieldset>tag, and it suddenly works. i.e:
<form action="/submit" method="POST">
<fieldset>
First name: <input type="text" name="fname"/>
Last name: <input type="text" name="lname"/>
<input type="text" id="taskId" name="taskId" th:value="${taskId}" />
<input type="submit" value="Submit"/>
</fieldset>
</form>
I would like to know:
Why adding <fieldset> will make everything works?
The HTML - <fieldset> tag is used to group related elements in a form.
Basically the <fieldset> tag draws a box around the related elements in a form.
Most online forms are poorly designed, disorganized, and hard to use. One thing you can do to make your forms better is to organize them into logical sections. The <fieldset> element provides an easy way to break forms down into logical sections.
For more information you can always got to - https://html.com/tags/fieldset/

How to get inputs from my view to my controller - SPRING JAVA JPA THYMELEAF

I'm developing a webApp in java, maven, JPA and thymeleaf and I have this problem:
I have this method in my controller:
#RequestMapping(value = "/admin/searchResults", method = RequestMethod.GET)
public String listResults(#ModelAttribute Step step,Model model,#PathVariable("dateStart") Date dateStart,#PathVariable("dateEnd") Date dateEnd){
model.addAttribute("dateStart", dateStart);
model.addAttribute("dateStart", dateEnd);
return "thisAreTheDates";
}
And this is a fragment of the view that in theory has to send the 2 date parameters to my fancy controller:
<div class="container">
<form class="form-inline" data-th-action="#{/admin/searchResults}" method="get" >
<div class="input-group">
<div class="form-group">
<label>From:</label>
<input type="date" id="dateStart" class="form-control"/>
<label>To:</label>
<input type="date" id = "dateEnd" class="form-control"/>
</div>
</div>
<br/>
<button type="submit" class="button">Generate Report</button>
</form>
</div>
Everything goes so good, until I go to that view, fill the fields with 2 dates and when I press the button of generate report, this error appears:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun May 28 10:54:07 BOT 2017
There was an unexpected error (type=Internal Server Error, status=500).
Missing URI template variable 'dateStart' for method parameter of type Date
In your HTML, you need to add name="dateStart" and name="dateEnd" to each of your dateStart and dateEnd input fields, respectively. This will allow your form connect to your model attribute.
Additionally, you will want to add a method to your controller annotated with #PostMapping to actually handle what you want to be done with your form input.
Finally, you will not want to use get on your HTML form but more likely, post.
So:
#GetMapping("/admin/searchResults") //use the shorthand
public String listResults(#ModelAttribute("step") Step step,
#PathVariable("dateStart") Date dateStart,
#PathVariable("dateEnd") Date dateEnd,
Model model) {
Step step = new Step(); //or however you are creating this
model.addAttribute("step", step);
model.addAttribute("dateStart", dateStart);
model.addAttribute("dateStart", dateEnd);
return "thisAreTheDates";
}
Your Post Mapping:
#PostMapping("/admin/searchResults") //use the shorthand
public String postResults(#ModelAttribute("step") Step step,
Errors result) {
//validate your step bean
someValidator.validate(step, result);
//persist it, do whatever
someService.save(step);
return "confirmationPage";
}
Updated HTML:
<div class="container">
<form class="form-inline" th:object="${step}" th:action="#{/admin/searchResults}" method="post" >
<div class="input-group">
<div class="form-group">
<label>From:</label>
<input type="date" name="dateStart" id="dateStart" class="form-control"/>
<label>To:</label>
<input type="date" name="dateEnd" id="dateEnd" class="form-control"/>
</div>
</div>
<br/>
<button type="submit" class="button">Generate Report</button>
</form>
</div>

How to pass object from th:each loop to controller

I have form and corresponding controller to which list of objects is passed. After that this list is redirected as an attribute to another method and displayed in a website. After that I would like to pass object from this list via form in a carSearchResult.html file to controller. I was trying to do like it is described here Spring and Thymeleaf: Sending an object to a controller from a th:each table but it does not work properly. It is sending an object to controller but with fields property and model set as blank (but they are not null).
searchCar form
<form action="#" th:action="#{/user/searchCar}" method="post">
<input type="radio" name="type" value="hatch" /> Hatchback <br/>
<input type="radio" name="type" value="sedan" /> Sedan <br/>
<input type="radio" name="type" value="combi" /> Kombi <br/>
<input type="radio" name="type" value="sport" /> Sport <br/>
<input type="radio" name="type" value="cabrio" /> Cabrio <br/>
<input type="text" name="dailyPrice" placeholder="Price" /> <br/>
<input type="date" name="dateOfRent" placeholder="Date of rent" /> <br/>
<input type="date" name="dateOfReturn" placeholder="Date of return" /> <br/>
<input type="submit" value="Show" />
</form>
Controller method for searchCar post request
#PostMapping("/user/searchCar")
public String searchCar(Model model, #RequestParam String type, #RequestParam double dailyPrice,
#RequestParam Date dateOfRent, #RequestParam Date dateOfReturn, RedirectAttributes redirectAttr) {
List<Car> allCarsList = carDao.getAllCars(type, dailyPrice, dateOfRent, dateOfReturn);
redirectAttr.addFlashAttribute("carList", allCarsList);
return "redirect:/user/carSearchResults";
}
Method where list is redirected
#GetMapping("/user/carSearchResults")
public String showCarSearchResults(Model model) {
model.addAttribute("car", new Car());
return "user/carSearchResults";
}
Form where list is displayed
<div th:each="car: ${carList}">
<h3 th:text="${car.producer}"></h3>
<h3 th:text="${car.model}"></h3>
<form action="#" th:action="#{/user/showCarDetails}" method="post" th:object="${car}">
<input type="hidden" th:field="*{producer}" /> <br/>
<input type="hidden" th:field="*{model}" /> <br/>
<input type="submit" value="Show" />
</form>
</div>
Method to which I want to send object from th:each loop
#PostMapping("/user/showCarDetails")
public String showCarDetails(#ModelAttribute Car car) {
System.out.println(car);
return "user/showCarDetails";
}
After printing information about car in console I receive object below. It looks like it is passed but with parameters as a blank space. Can anyone help me? Many thanks.
Car [id=null, producer=, model=, seatsNumber=null, type=null, registrationNumber=null, dailyPrice=null, description=null]
EDIT
I have changed the form. Option with th:attr and th:value works but I do not really understand why th:field does not work and what is the difference between them. As I understand from documentation th:value is some kind of older version of th:field?
<div th:each="car: ${carList}" th:object="${car}">
<h3 th:text="*{producer}"></h3>
<h3 th:text="*{model}"></h3>
<form action="#" th:action="#{/user/showCarDetails}" method="post">
<input type="hidden" th:value="*{producer}" name="producer" /> <br/> <!-- It works -->
<input type="hidden" th:attr="value=*{producer}" name="producer" /> <br/> <!-- It works -->
<input type="hidden" th:field="*{producer}" /> <!-- It does not work -->
<input type="submit" value="Pokaż" />
</form>
</div>
th:object works differently when you use it on a <form>, vs. when you use it other places. When you use it in a form, it expects it to resolve to a single variable on the model. You cannot use it with a temporary variable (like {$car} -- which isn't on the model, it's just a temporary variable created byth:each) because the attribute just isn't built to work like that.
th:field generates both the value and name tags -- but again, it has to work within the same limitations as th:object. The reason manually adding name and value attributes work, is because they happen to line up with what spring is expecting in a post and it's able to create the object based on the names.
As for how to solve the original problem... I think you have two options:
Create a command object which has a List of Cars as a property. That way you can use the th:object and th:field properties. You'll have to have the submit button to supply which car is being edited.
Continue manually creating the name and value fields like you already are.

Getting Null from post data from jsp

<center>
<form class="form-horizontal" action="${pageContext.servletContext.contextPath}/LargeLandmarkListGet" method="post">
<div class="form-group">
<label class="control-label col-sm-2" for="SLLRID">SLLRID:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="SLLRID" placeholder="Enter SLLRID...">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
</center>
That is the particular definition of the action in the JSP.
String SLLRID = request.getParameter("SLLRID");
This is how I am trying to get it in the servlet, within the doPost method. However, SLLRID is always null. I've tried everything I can think of but I cannot get it to return the inputted value. However, if I hardcode the value, everything works perfectly, so I think there is something wrong when communicating between the JSP and the servlet.
What I Have Tried:
Changing the name in for in the label definition, so that id and for are named differently
Adding an id value to the button
Hardcoding the value to verify the servlet
Trying a get rather than a post (though that seemed wildly inappropriate)
Testing other servlets with the same JSP (this worked, though not with this particular submission id)
Ensuring that everything that needed entries in web.xml had said entries made
The form sends the data based on the name attribute. So instead put: <input type="text" class="form-control" id="SLLRID" name="SLLRID" placeholder="Enter SLLRID...">

Categories