Howto send vars and receive model in same time from same controller? - java

In Spring boot who receive post model and in same time send vars to thymeleaf template?
#Controller
public class ProfilingController {
#GetMapping("/")
public String main(Model model){
FormModel form_model = new FormModel();
model.addAttribute("form_model", form_model);
model.addAttribute("demo", "abc");
return "main_template";
}
#PostMapping("/")
public String receive(#ModelAttribute ModelForm form_model){
FormModel form_model = new FormModel();
// How to set model to send the var to thymeleaf template?
model.addAttribute("form_model", form_model);
model.addAttribute("demo", "abc");
return "main_template";
}
}
If in post method receibe the model, how set the model to send vars to template?, if send two params does not works:
#PostMapping("/")
public String receive(Model model, #ModelAttribute ModelForm form_model){
The model_form is empty.
The template:
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
</head>
<body>
<form class="form-signin" action="#" method="post" th:action="#{/}" th:object="${form_model}">
<input th:field="*{email}" required="required" type="email" />
<input th:field="*{password}" type="password" />
<p th:text="${demo}"></p>
<button type="submit">Submit</button>
</form>
</body>
</html>

You can do this with ModelMap as below:
I have commented new form_model object creation assuming that you need to keep the received data to send back to the user.
#PostMapping("/")
public String receive(#ModelAttribute ModelForm form_model, ModelMap modelMap){
//other code to call service layer & save the data
//Commented new object creation for FormModel
//FormModel form_model = new FormModel();
modelMap.addAttribute("form_model", form_model);
modelMap.addAttribute("demo", "abc");
return "main_template";
}

Related

Spring RestController POST accepting a basic HTML form

I'm attempting to post a simple HTML form to Spring RestController using #ModelAttribute and MediaType.APPLICATION_FORM_URLENCODED_VALUE as consumed data type. I've double checked all of my forms fields which match my request bean.
When the request enters the mapped method, all of the request beans fields are null.
#RestController
#EnableWebMvc
public class WebServiceController {
#RequestMapping(
value = "/test",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<?> post(#ModelAttribute FormBean request){
// request.getParam() == null
return ResponseEntity.ok().build();
}
}
public class FormBean {
private String param1;
public String getParam1() {
return param1;
}
public void setParam1(String param1) {
this.param1 = param1;
}
}
<html>
<head>
<title>Test Form</title>
</head>
<body>
<form action="/test" method="POST">
<input type="text" id="param1">
<button type="submit">Submit</button>
</form>
</body>
</html>
You are missing the name attribute in your HTML inputs, id attribute is meaningless when posting an HTML form
<input type="text" name="param1">

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}";
}

Error:Neither BindingResult nor plain target object for bean name 'id' available as request attribute

i am using the thymeleaf and spring. i want to implement the post request.
my controller class is
public class URLController {
#RequestMapping(value = "index")
public String index1(Model model){
model.addAttribute("employee",new Employee());
return "index";
}
#RequestMapping(value = "/")
public String index(Model model){
model.addAttribute("employee",new Employee());
return "index";
}
#PostMapping("/result")
public String result(#ModelAttribute Employee employee){
System.out.print(employee.getName());
return "result";
}
}
and the html page is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index page</title>
</head>
<body>
<form action="#" th:action="#{/result}" modelAttribute="employee" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p>name: <input type="text" th:field="*{name}" /></p>
<p>phone: <input type="text" th:field="*{phone}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
there is no binding with the id field.
In your HTML, you need to use the proper syntax for your model attribute. Spring is complaining that it can't find the property id because you are providing the string employee, not the object.
modelAttribute="employee" --> th:object="${employee}"
Additionally, you can consolidate to:
#Controller //please add this
public class URLController {
#GetMapping({"/", "/index"})
public String index1(Model model){
model.addAttribute("employee",new Employee());
return "index";
}
#PostMapping("/result")
public String result(#ModelAttribute Employee employee){
System.out.print(employee.getName()); //use a logger instead
return "result"; //may want to return a different page name for clarity
}
}
Your IDE will not complain if you change your HTML tag to:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
Lastly, you may want to use the tel input type for the phone field. Doing so will allow for a custom keyboard to show for mobile users.

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