#RequestMapping with #PathVariable URI is different - java

hi i have a problem i am learnig how to pass values with PathVariable, i have a form with a input text and a button when you press the buttom it takes you to other page and show the value but it dont work when i press the buttom it takes me to this URL:
http://localhost:8080/appThyme/shoForm1.html?firstname=MyName&submit=
and i get this error HTTP 404 - /appThyme/showForm1.html
but if i put this URL: http://localhost:8080/appThyme/respuesta/Myname it works it shows me my page with my name, how can i make that work with only pressing the buttom, why when i press the buttom it add question marks and equals symbols to my URI
#Controller
public class HomeController {
#RequestMapping(value = "/form1", method = RequestMethod.GET)
public String showFormulario2(Model model) {
logger.info("***PAG formulario***");
return "form1.html";
}
#RequestMapping(value = "/showForm1/{id}", method = RequestMethod.GET)
public String showForm(Model model, #PathVariable("id") String id)
{
String theId= id;
model.addAttribute("TheID", theId);
return "showForm1.html";
}
my form1.html page
<form id="guestForm" th:action="#{/showForm1.html}" method="get">
<div>
<input type="text" name="firstname" id="firstname"></input>
</div>
<div>
<button type="submit" name="submit">Submit</button>
</div>
</form>
my showForm1.html page
enter code here
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The value is ${nombre} </P>
</body>
</html>

Form submissions are not intended to work with the #PathVariable construct you are using here. #PathVariable is intended for use with REST-style URI's, and that is not what is generated on a form submit.
If you change your controller signature to look like this:
#RequestMapping("/showForm1.html", method = RequestMethod.GET)
public String showForm(Model model, #RequestParam("firstname") String id)
{
String theId= id;
model.addAttribute("TheID", theId);
return "showForm1.html";
}
then the method should be called correctly on form submission.

Related

"Request method 'POST' not supported" when I try to save Person due to <form method="POST">

Controller methods where can be mistaken:
Here I go to URL "/create" with <form method="POST>
#GetMapping("/create")
public ModelAndView create() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/create.jsp");
return modelAndView;
}
This is create.jsp
<%# page isELIgnored="false"%>
<%# page contentType="text/html; charset=UTF-8" %>
<html>
<head>
<title>Create</title>
</head>
<body>
<h1>Create author</h1>
<form method="POST" action="">
Id <input name="userId"> <br>
Last name: <input name="lastName"> <br>
First name: <input name="firstName"> <br>
Second name: <input name="secondName"> <br>
Phone: <input name="phone"> <br>
Hobby: <input name="hobby"> <br>
BitBucketUrl: <input name="bitBucketUrl"> <br>
<input type="submit" value="Create">
</form>
</body>
</html>
And finally #Postmapping method
#PostMapping
public ModelAndView createPerson(
#RequestParam("id") String id,
#RequestParam("lastName") String lastName,
#RequestParam("firstName") String firstName,
#RequestParam("secondName") String secondName,
#RequestParam("phone") String phone,
#RequestParam("hobby") String hobby,
#RequestParam("bitBucketUrl") String bitBucketUrl) {
personCache.create(Person.builder()
.setId(id)
.setFirstName(firstName)
.setLastName(lastName)
.setSecondName(secondName)
.setPhone(phone)
.setHobby(hobby)
.setBitBucketUrl(bitBucketUrl)
.build());
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("id", id);
modelAndView.addObject("lastName", lastName);
modelAndView.addObject("firstName", firstName);
modelAndView.addObject("secondName", secondName);
modelAndView.addObject("phone", phone);
modelAndView.addObject("hobby", hobby);
modelAndView.addObject("bitBucketUrl", bitBucketUrl);
modelAndView.setViewName("/all.jsp");
return modelAndView;
}
Page all.jsp is working (realized in method #GetMapping("/all")).
I want, when the button "create" is pushed, go to page "/all", where I can see a new Person. But I take an error "Request method 'POST' not supported" in the terminal, and error "type=Method Not Allowed, status=405" in the browser.
Also I create default page index.jsp, and try modelAndView.setViewName("/index.jsp") in #PostMapping method, but unfortunately, even in this case, when I push "create" browser don't go to index.jsp
By default browser does get-requests only, so create another controller method with get-mapping and add person object to the model so that you can set values in the view page and when you press submit give post-mapping so that you can assign values that are entered in view page to the person object.
Browser address bar sends GET requests.
You can use smth like Postman to send requests which you need.
Try giving form tag any other action other than root and also give that post-mapping the same action.
In create.jsp I was written:
Id <input name="userId"> <br>
And in #PostMapping
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("id", id)
Banal inattention

Thymeleaf request parameter null value problem

I have a problem,my web app have a passcode form, user will give a Passcode string and app will riderict user to questions page for a spesific event. my controller will find this even by this passcode. i tried with this way but my passcode field is always null.
<form method="get" th:action="#{/findEvent(passcode=${passcode})}">
Passcode:<br>
<input type="text" th:name="${passcode}"><br>
<div>
<button type="submit">Find</button>
</div>
</form>
#GetMapping(value = "/findEvent")
public String resetPassword(#RequestParam(value="passcode",required=false) String passcode) {
if(passcode==null)
return "passcode";
Event event=eventService.findByPassCode(passcode);
List<Question> questions=questionService.findQuestionsByPasscode(passcode);
return "questions";
}
#RequestMapping(value = "/findEvent", method = RequestMethod.POST)
public String findEvent(#RequestParam("passcode") String passcode) {
Event event=eventService.findByPassCode(passcode);
List<Question> questions=questionService.findQuestionsByPasscode(passcode);
return "questions";
}
Same problem with mine
Request parameter with thymeleaf
How can i achieve this ?? can you help me
Use name="passcode" instead
<input type="text" name="passcode" value="1234" />
Since its the same as the object name, just use
#RequestParam String passcode

How can I have a model attribute persist between redirects?

I am trying to write a password reset function for a website. I am running into an issue that I am using a couple of redirects to transition from postmappings to getmappings and they dont seem to be carrying the attributes they need to with them, namely the user object that I am trying to reset the password form, here is an example of one of my mappings:
#PostMapping("/user/forgot")
public String emailCheck (#RequestParam String email, Model model){
User user = userDao.findByEmail(email);
if (user==null){
model.addAttribute("wrongEmail", true);
return "redirect:/user/forgot";
}
else {
model.addAttribute("user", user);
return "redirect:/verifysecurity";
}
}
And here is the template where I then call the user attribute:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head th:replace="fragments/header :: header('Security', '')"></head>
<body>
<div th:replace="fragments/navbar :: navbar"></div>
<h1 th:if="${wrongAnswer}">Answer does not match record on file, please try again</h1>
<h1>Please answer your security question: WHat is your best friends name?</h1>
<form id="passwordForm" th:action="#{/verifysecurity}" th:method="post">
<label for="answer">Answer</label>
<br/>
<input type="text" id="answer" name="answer"/>
<input type="hidden" name="user" id="user" th:value="${user}"/>
<input type="submit" class="btn btn-block btn-primary" value="Request"/>
</form>
</body>
</html>
Then on the next mapping afterwards I get a null pointer exception for the user:
#PostMapping("/verifysecurity")
public String verify (Model model, #RequestParam User user, #RequestParam String answer){
String security = user.getSecurity_question();
if (answer.equals(security)){
model.addAttribute("user", user);
return "redirect:/reset/password";
} else {
model.addAttribute("wrongAnswer", true);
model.addAttribute("user", user);
return "redirect:/verifysecurity";
}
}
How can I fix this, and if model attributes won't work what should I be doing instead?
Use spring RedirectAttributes.addFlashAttribute(), as name suggested it's stored in flashmap which internally uses user session to pass on this data to next redirect, and removes ones data is used.
Example from spring doc:
#RequestMapping(value = "/accounts", method = RequestMethod.POST)
public String handle(Account account, BindingResult result, RedirectAttributes redirectAttrs) {
// Save account ...
redirectAttrs.addFlashAttribute("message", "Account created!");
return "redirect:/accounts/{id}";
}

Creating and persisting a new User based on html input. Spring MVC, JPA Hibernate, Thymeleaf

Searched all over the Internet and tryed different solutions, but somehow no one worked in my case.
I have following html template for a view where you should register yourself:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" type="text/css" th:href="#{/css/style.css}" />
<!-- Page title -->
<title> Register</title>
</head>
<body>
<form action="#" th:action="#{/registeruser}" th:object="${user}" method="post">
<input type="text" th:field="*{username}" />
<input type="text" th:field="*{email}" />
<input type="text" th:field="*{password}" />
<input type="submit" />
</form>
</body>
</html>
also here is the controller:
#Controller
public class RegisterController {
#Autowired
private UserService userservice;
#Autowired
private RoleService roleService;
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String regUser(Model model) {
User u = new User();
u.setUsername("username");
u.setPassword("password");
u.setEmail("email");
Set<Role> userRoles = new HashSet<>();
userRoles.add(roleService.findRoleByName("ROLE_USER"));
u.setRoles(userRoles);
System.out.println("test");
model.addAttribute("user", u);
return "register";
// return new ModelAndView("register", "command", new User());
}
#RequestMapping(value = "/registeruser", method = RequestMethod.POST)
public String addUser(#ModelAttribute(value = "user")User user,
ModelMap model) {
model.addAttribute("username", user.getUsername());
model.addAttribute("password", user.getPassword());
model.addAttribute("email", user.getEmail());
System.out.println("user " + user.getUsername() + "got registered, here a list of all users: " );
return "login";
}
}
The console print test works in the regUser() method but somehow the console print in the addUser() method does not work, so I guess it does not get triggered?
Also the View works perfect and I get redirected after submitting to the login page, but this is also the defaultSuccesFulUrl so it probably means nothing.
Kinda frustrated on this one, so it would be really nice if you could help.
Thanks in advance.
Try removing action="#" in your form. This may be stepping on the one that's generated through Thymeleaf.
Aside:
You can use #GetMapping and #PostMapping as shorthand for your
mappings.
You'll want to change it to input type="password"
You can use Model instead of ModelMap
Use #Slf4j and a logging system of your choice
Change your POST method to
#RequestMapping(value = "/registeruser", method = RequestMethod.POST)
public String addUser(User user) {
...
Also is better if in your submit, says is a button
<button type="submit">Submit</button>
And as said bphlilipnyc remove the action="#"

Thymeleaf with SpringBoot - how to loop model and delete?

I am using SpringBoot with Thymeleaf to build a trivial example to help me learn the two technologies.
I am basing my example on THIS GUIDE
The entity is a Greeting which has an Id and a Content.
I create the Greeting just fine, and I can list all the Greetings I've created.
I then wanted to add a delete option against each Greeting in the list page. When clicking delete, I want the object to be deleted and the list page served up again.
Alas, when I load the list page I get this error:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'greeting' available as request attribute
Controller and respository objects
#Controller
public class GreetingController {
#Autowired
GreetingRepo gr;
#RequestMapping(value="/greeting/list", method=RequestMethod.GET)
public String greetingsForm(Model model) {
model.addAttribute("greetings", gr.findAll());
return "greeting/list";
}
#RequestMapping(value="/greeting/delete", method=RequestMethod.POST)
public String deleteGreeting(#ModelAttribute("greeting") Greeting greeting) {
gr.delete(greeting);
return "redirect:/greeting/list";
}
}
#RepositoryRestResource
interface GreetingRepo extends JpaRepository<Greeting, Long> {
}
List.html page:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Result</h1>
<div th:each="greeting : ${greetings}">
<p th:text="'id: ' + ${greeting.id}" />
<p th:text="'content: ' + ${greeting.content}" />
<form action="#" th:action="#{/greeting/delete}" th:object="${greeting}" method="post">
<input type="hidden" th:field="*{id}"/>
<input type="hidden" th:field="*{content}"/>
<input type="Submit" value="Delete"/>
</form>
</div>
Add another
Show All
</body>
</html>
Would appreciate a push in the right direction here :-)
I think you miss this line .
model.addAttribute("greeting", new Greeting());
#RequestMapping(value="/greeting/list", method=RequestMethod.GET)
public String greetingsForm(Model model) {
model.addAttribute("greeting", new Greeting());
model.addAttribute("greetings", gr.findAll());
return "greeting/list";
}
you dont have to use a form to delete the greeting you can do it very easily with this approach. hide the id of the greeting within the url. so you dont need to use a form and hidden tags. and annotate the controller method with following approach, to accept incoming id of the greeting.
replace the current form with given html code and replace the delete method in the controller as well.
<a th:href="#{/greeting/{id}/delete(id=${greeting.id})}" th:text="delete"></a>
#RequestMapping(value="/greeting/{id}/delete",method=RequestMethod.GET)
public String deleteGreeting(#PathVariable int id) {
gr.delete(id);
return "redirect:/greeting/list";
}
edit:- since you need the object to be present within the controller
you can use findOne method to fetch the object from the given id.check out the following example.
<a th:href="#{/greeting/{id}/edit(id=${greeting.id})}" th:text="edit"></a>
#RequestMapping(value="/greeting/{id}/edit",method=RequestMethod.GET)
public String Edit(#PathVariable int id){
greeting greetingob = gr.findOne(id);
return "edit";
}

Categories