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.
Related
I have two hidden input fields to implement Friend system. I pass user and friend's ids in Model and then use them in thymeleaf page to pass them in form to PostMapping and save changes. However, PostMapping cannot see my second #RequestParam.
Both customer and friend are properly passed to model as I tried to output them on website using th:text
Snippets of code:
Adding both users to model:
#GetMapping("/customer/{customerId}")
public String getCustomer(Model theModel, #PathVariable int customerId, #AuthenticationPrincipal MyUserDetails user) {
Customer currUser = customerService.findById(user.getCustomer().getId());
Customer foundCustomer = customerService.findById(customerId);
theModel.addAttribute("friend", foundCustomer);
theModel.addAttribute("customer", currUser);
return "customerdetails";
Snippet of Thymeleaf code:
<form action="#" th:action="#{/home/addFriend}" th:object="${friend}" method="post">
<input type="hidden" th:field="${friend.id}" th:attr="name='friendId'" />
<input type="hidden" th:field="${customer.id}" th:attr="name='customerId'" />
<input type="submit" value="Add Friend" class="btn btn-primary flex-grow-1" />
</form>
PostMapping (where issue occurs):
#PostMapping("/addFriend")
public String getPost(#RequestParam("friendId") int friendId, #RequestParam("customerId") int customerId) {
Customer friendCustomer = customerService.findById(friendId);
Customer currCustomer = customerService.findById(customerId);
System.out.println(currCustomer.getFirstName());
System.out.println(friendCustomer.getFirstName());
return "redirect:/home";
}
Code of error:
[org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'friendId' for method parameter type int is not present]
It will be a lot easier to implement using a custom form object.
For example, create this class:
public class AssignFriendFormData {
private String friendId;
private String customerId;
// getter and setters here
}
Use this in your #GetMappping:
#GetMapping("/customer/{customerId}")
public String getCustomer(Model theModel, #PathVariable int customerId, #AuthenticationPrincipal MyUserDetails user) {
Customer currUser = customerService.findById(user.getCustomer().getId());
Customer foundCustomer = customerService.findById(customerId);
AssignFriendFormData formData = new AssignFriendFormData();
formData.setFriendId(foundCustomer.getId());
formData.setCustomerId(currUser.getId());
theModel.addAttribute("formData", formData);
return "customerdetails";
Change the form to this:
<form action="#" th:action="#{/home/addFriend}" th:object="${formData}" method="post">
<input type="hidden" th:field="*{friendId}" />
<input type="hidden" th:field="*{customerId}" />
<input type="submit" value="Add Friend" class="btn btn-primary flex-grow-1" />
</form>
Finally, update the #PostMapping to use the form data object:
#PostMapping("/addFriend")
public String getPost(#Valid #ModelAttribute("formData") AssignFriendFormData formData) {
Customer friendCustomer = customerService.findById(formData.getFriendId());
Customer currCustomer = customerService.findById(formData.getCustomerId());
System.out.println(currCustomer.getFirstName());
System.out.println(friendCustomer.getFirstName());
return "redirect:/home";
}
See Form handling with Thymeleaf for a more in-depth tutorial on this.
I made a Form using Thymeleaf but running into this issue.
I read many articles but didn't find any solution.
Any solution you can suggest ?
Project Controller ->
#Controller
public class Controllers {
#GetMapping("/home")
public ModelAndView home(){
System.out.println("User is in Homepage");
return new ModelAndView("index");
}
#GetMapping("/service")
public ModelAndView service(){
System.out.println("User is in Service Page");
return new ModelAndView("service");
}
#GetMapping("/about")
public ModelAndView about(){
System.out.println("User is in About page");
return new ModelAndView("about");
}
Here's Controller Class for submitting form ->
#Controller
public class SavingUser{
#Autowired
private UserRepository userRepository;
#PostMapping("/registerUser")
public ModelAndView user(#ModelAttribute Customer customer, ModelMap model){
System.out.println("User in registration page..");
userRepository.save(customer);
model.addAttribute("saveUser", customer);
return new ModelAndView("index");
}
}
And here's my HTML Form -
<div id="form">
<form action="registerUser" th:action="#{/registerUser}" th:object="${saveUser}" method="POST">
<br />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<label for="name">Your Name:</label><br />
<input type="text" th:field="*{name}" placeholder="" /><br />
<label for="suburb">Your Suburb</label><br />
<input type="text" th:field="*{suburb}" placeholder="" /><br />
<input class="submit" type="submit" value="Submit" />
<br /><br />
</div>
</form>
</div>
I tried to remove action="", still it didn't work.
Well, from what I see in the code you miss the #GetMapping method in your controller to actually display the page. Not very clear in what step you get 405 status. It would be useful if you also add the relevant exception message from the console.
Edit:
to answer the original question, you get 405 because in the Post Controller you make a POST request to "/services" which dosen't exists (only the GET exists for services).
#PostMapping("/registerUser")
public ModelAndView user(#Valid #ModelAttribute Customer customer, BindingResult result, ModelMap model){
[...]
return new ModelAndView("service"); // this makes a POST to "service" endpoint!
}
To correct that, you must make a redirect to the page like this:
#PostMapping("/registerUser")
public ModelAndView user(#Valid #ModelAttribute Customer customer, BindingResult result, ModelMap model){
[...]
return new ModelAndView("redirect:/service"); // this makes a GET to "service" endpoint
}
Leaving that aside, there are many things that can be imporoved. First of all, you are not using Thymeleaf in your project. No Thymeleaf markup will be processed. To use it you must add first the dependency, then configure Thymeleaf as your HTML resolver. The proper way to do all that is detailed here.
Also, I really recommend reading Thymeleaf documentation and follow a few tutorials to understand how things work.
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.
I am trying to get the value of a form from a jsp to use in a function in the controller and display another jsp
<form action="/uc">
<input name="cnp" type="text">
<br>
<br>
<input type="submit" value="Find">
</form>
This one is my Controller method
#RequestMapping(value = "/uc", method = RequestMethod.GET)
public String userContracts(#RequestParam("cnp") String cnp, Model model)
{
List<Contract> ContractList = new ArrayList<Contract>();
ContractList = cl.getContractsOfUser(cnp);
model.addAttribute("ContractList", ContractList);
System.out.println("In uc");
return "UserContracts";
}
Thanks pedram ezzati for the help!
The problem was that I had to use
<form action="http://localhost:8080/SpringWebTemplate/uc.html">
My previous attempts where either without the .html or just using /uc
Make sure your package is scan while spring come up.
In app-config.xml file check below tag
context:component-scan base-package="com.test.ashok"
I'm a trainee java-dev and this is my first question here so please, don't judge me!
I have a Controller class which works with jsp files. The first jsp (userinput.jsp) has 3 text fields (lat, lon, radius) and 2 buttons (submit, apply default values). The second jsp is just an HTML table filled with data (depends on user input), and a reset button which should return you to the starter page (userinput.jsp) and delete all existing data. How should I do this?
Bonus question: If I try to refresh the page at the second state (html table), the browser generates a warning that says I'll lose all data and I shouldn't refresh. How can I get rid of this?
#Controller
#EnableAutoConfiguration
class SpringBootController implements InitLogger {
#GetMapping(value="/geohash")
public String getUserInput(ModelMap model) {
model.put("command", new Tuple());
return "UserInput";
}
#PostMapping(value="/geohash", params="SubmitWithDefault")
public String defaultUserInput(ModelMap model) {
model.put("command", tupleFill (48.104564, 20.800041, 6) );
return "UserInput";
}
#PostMapping(value = "/geohash", params="Submit")
public String printHash(#ModelAttribute("user")Tuple tuple,ModelMap model) {
GetData.setLat1(tuple.getFirstCoordinate());
GetData.setLon1(tuple.getSecondCoordinate());
GetData.setRad1(tuple.getRadius());
LocationExecute.calculate();
model.addAttribute("geoItemList", LocationExecute.getTupleList());
model.addAttribute("listSize", LocationExecute.getTupleList().size());
return "Geohash";
}
#PostMapping(value = "/geohash", params="reset", method = RequestMethod.GET)
public ModelAndView method() {
return new ModelAndView("redirect:geohash");
}
}
userinput.jsp - buttons
<input type="submit" name="Submit" value="Submit" style="height:25px; width:100px"/>
<input type="submit" name="SubmitWithDefault" value="Default Values" style="height:25px; width:100px">
geohash.jsp - (html table) reset button
<input type="reset" name="reset" value="Reset" style="height:30px; width:100px">
You need to implement PRG(Post -Redirect-Get) design pattern in MVC to solve the issue.
Please go through the below for more information
http://www.c-sharpcorner.com/UploadFile/dacca2/implement-prg-pattern-in-mvc-architecture/
So instead of returning view name redirect it so your problem will be solved, if you want some data to be sent to redirect method then use flashAttributes of spring
Solved it this way:
geohash.jsp
(added form:form tags)
<form:form action="/geohash">
<th> <input type="submit" name="reset" value="Reset" style="height:30px; width:100px"> </th>
</form:form>
Controller
(changed method to post)
#RequestMapping(value = "/geohash", params="reset", method = RequestMethod.POST)
public ModelAndView method() {
return new ModelAndView("redirect:geohash");
}