In my Spring boot project, Passed a DTO object to my view which is then posted after submission. eg. How do I access the "randomKey" after the form is posted?
#GetMapping("/{userId}/edit/feature/")
public String showEditFeature(#PathVariable("userId") Long userId, UserDto userDto,
Model model)
{
User user = userService.get(userId);
model.addAttribute("user", user);
model.addAttribute("randomKEy", "AnyObject");
return "user/edit/profile";
}
Then My post function.
#PostMapping("profile_update")
public String watchFeatureUpdate(#Valid UserProfileDto UserProfileDto,
BindingResult result,
RedirectAttributes redirectAttributes, Model model)
{
Long userId = userService.updateUserProfile(userProfileDto);
redirectAttributes.addFlashAttribute("message", "Profile features updated
successfully!");
redirectAttributes.addFlashAttribute("alertClass", "alert-success");
return "redirect:/user/view/" + userId + "/profile";
}
You need to include in your HTML page "user/edit/profile" as a hidden input every object property value so they are sent back when the form is submitted.
<input type="hidden" name="randomKEy" value="${randomKEy}">
Note that HTML content is still manipulable by the user even not being visible in the rendered web page.
Related
I'm using Thymeleaf with Springboot2.1.2 and I have problem accessing session attributes in the templates.
Here's the code:
This is one of the controllers:
#GetMapping("/profile")
public String getProfile(HttpServletRequest request) {
HttpSession session = request.getSession(false);
String email = (String) session.getAttribute("userId");
User user = userService.getProfile(email);
session.setAttribute("user", user);
return "user/profile";
}
And the corresponding view(html):
<body th:object="${session.user}">
//some code using the user object here...
</body>
When I run the application, I got the exception:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'session' available as request attribute
I've also tried for #session and something else, they didn't work. However, in another controller, I can access the object by using Model:
#GetMapping("/register/user")
public String registerUser(Model model) {
model.addAttribute("user", new User());
return "user/register";
}
And the view is like:
<form th:object="${user}" method="post" action="#" th:action="#{/register/user}">
//some code using the user object...
</form>
It's driving me crazy since all the tutorials I can find tell me I can access session attributes by ${session.something}, in reality, it doesn't work.
Could you help me?
You are saving the information in the session, this is not visible by thymeleaf. you need to create a model for your thymeleaf template and add the attribute (or the session) to the model and then return that.
#GetMapping("/profile")
public ModelAndView getProfile(HttpServletRequest request) {
User user = userService.getProfile(email);
ModelAndView model = new ModelAndView(NAME_OF_THYMELEAF_PROFILE_FILE);
model.addObject("user",user);
return model;
}
Beware that for the thymeleaf to see the template it needs to be in a default path (resources/templates) or you need to define where your templates are stored.
If you want to use session again the solution is similar.
#GetMapping("/profile")
public ModelAndView getProfile(HttpServletRequest request) {
HttpSession session = request.getSession(false);
User user = userService.getProfile(email);
session.setAttribute("user", user);
ModelAndView model = new
ModelAndView(NAME_OF_THYMELEAF_PROFILE_FILE);
model.addObject("session",session);
return model;
}
UPDATE use model and return String:
#GetMapping("/profile")
public String getProfile(HttpServletRequest request, Model model) {
HttpSession session = request.getSession(false);
String email = (String) session.getAttribute("userId");
User user = userService.getProfile(email);
session.setAttribute("user", user);
model.addAttribute("session", session);
return "user/profile";
}
I used ModelAndView, you can do the same with Model, just instead of addObject() you must use addAttribute().
You should be using Spring-Security with thymeleaf extensions to accomplish what you want. Here is an example of what you want to do. If you follow the example you can access user information as follows:
<div sec:authentication="name"><!-- Display UserName Here --></div>
Please note that for spring-boot 2.1.X you should use the following dependency:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
In one page I have an DataTable.
when clicked upon a user, the user Id gets passed as url value
usersInfo?getid=1
I have a controller like this :
#RequestMapping(value = "users/userInfo", method = RequestMethod.GET, params = {"getId"})
#ResponseBody
public ModelAndView getClientStat(#RequestParam(value="getId", required = true) String getId) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
long clientId=0;
clientId=Long.parseLong(getId);
Client client=clientService.getClientById(clientId);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("userName", user.getName() + " " + user.getLastName());
modelAndView.addObject("userId", user.getId());
modelAndView.addObject("id", client.getName()+ " " + client.getLastName());
modelAndView.setViewName("users/userInfo");
return modelAndView;
}
And then I use the passed object id which has the name and last name to show the user name.
Then on the opened users/userInfo page I have a button which sends to another page to fill out a form.
The question is : How do I save the fields of these form to the database, but for the client whose id I have in the controller.
How do I pass this value on ?
Or is there a better more logical way to do this ?
I am fairly new at using Spring , so I apologize in advance if something is unclear but I would really appreciate some guidance.
Thank you
You can use #PathVariable with addAttribute
#RequestMapping(value = "users/edit/{userId}", method = RequestMethod.GET)
public ModelAndView getClientStat(#PathVariable(value="userId", required = true) String userId) {
//Use the userId to find user information and pass
modelAndView.addAttribute("id", userId)
modelAndView.setViewName("users/edit");
return modelAndView;
}
In your view, you can add the userId as hidden field
<input type="hidden" name="userId" value={userId} />, depend on the view you're using thymeleaf OR jsp
My objective is to pass model attributes from controller to JSP page during a redirect and avoid the attribute being displayed in URL. The source code below is validating login from datastore using java data objects.
Controller:
#Controller
public class LoginController {
int count;
PersistenceManager pm = PMF.get().getPersistenceManager();
//Instance of data class
User user;
ModelAndView modelAndView=new ModelAndView();
#RequestMapping(value="/Login",method = RequestMethod.POST)
public ModelAndView loginValidate(HttpServletRequest req){
//Getting login values
String uname=req.getParameter("nameLogin");
String pswd1=req.getParameter("pswdLogin");
count=0;
user=new User();
//Generating Query
Query q = pm.newQuery(User.class);
q.setFilter("userName == userNameParam");
q.declareParameters("String userNameParam");
try{
List<User> results = (List<User>) q.execute(uname);
for (User u: results) {
String userName=u.getUserName();
if(userName.equals(uname)){
System.out.println(u.getPassword());
if(u.getPassword().equals(pswd1)){
count=count+1;
modelAndView.setViewName("redirect:welcome");
modelAndView.addObject("USERNAME",uname);
return modelAndView;
}
//rest of the logic
}
JSP:
<h1>Welcome ${USERNAME} </h1>
My current URL is /welcome?USERNAME=robin
My goal is to display it as /welcome
Also, my page is supposed to display "Welcome robin" whereas it displays only Welcome.
RedirectAttributes only work with RedirectView, please follow the same
#RequestMapping(value="/Login",method = RequestMethod.POST)
public RedirectView loginValidate(HttpServletRequest req, RedirectAttributes redir){
...
redirectView= new RedirectView("/foo",true);
redir.addFlashAttribute("USERNAME",uname);
return redirectView;
}
Those flash attributes are passed via the session (and are destroyed immediately after being used - see Spring Reference Manual for details). This has two interests :
they are not visible in URL
you are not restricted to String, but may pass arbitrary objects.
You need to be careful here because I think what are you trying to do is not supported for a good reason. The "redirect" directive will issue a GET request to your controller. The GET request should only retrieve existing state using request parameters, this is the method contract. That GET request should not rely on a previous interaction or on any object stored some where in the session as a result of it. GET request is designed to retrieve existing (persisted) state. Your original (POST) request should have persisted everything you need for you GET request to retrieve a state.
RedirectAttributes are not designed to support you in this case, and even if you managed to correctly use it it will only work once and then they will be destroyed. If you then refresh the browser you will get an application error because it cannot find your attributes anymore.
I have this piece of code:
#RequestMapping(value="login/authUser", method=RequestMethod.POST)
public String authUser(#RequestParam("login") String login,
#RequestParam("password") String password, ModelMap model){
(...)
if (password.equals(user.getPassword())){
ModelMap modelMap = new ModelMap();
modelMap.put("loggedUser", user.getName() + " " + user.getSurname());
return "home";
}
else{
model.put("info", "Bad data!");
return "index";
}
For bad password, everything is correct - it returns a with information "bad data", but if password is correct I can't get an info about logged user (but it redirects correctly). Because ModelMap model is ,,bind" to index.jsp it works when it redirects to index jsp, but is there a way to "bind" new ModelMap to view called home.jsp with simply way or I have to use ModelAndView?
Thank you in advance.
#SOLVED: It was my stupidity, I simple do not initialize name and surname in variable user, and because of it there were a "" instead name and surname which I want to see in home.jsp. Now, with user with name and surname set it works great :)
An item is displayed at this URL:
/item/10101
using this Controller method:
#RequestMapping(value = "/item/{itemId}", method = RequestMethod.GET)
public final String item(HttpServletRequest request, ModelMap model,
#PathVariable long itemId)
{
model = this.fillModel(itemId);
return "item";
}
The page contains a form that submits to the following method in the same controller:
#RequestMapping(value = "/process_form", method = RequestMethod.POST)
public final String processForm(HttpServletRequest request,
#ModelAttribute("foo") FooModel fooModel,
BindingResult bindResult,
ModelMap model)
{
FooModelValidator validator = new FooModelValidator();
validator.validate(FooModel, bindResult);
if (bindResult.hasErrors())
{
model = this.fillModel(fooModel.getItemId());
return "item";
}
return "account";
}
If the validator finds errors in the form, it redisplays the item but instead of displaying it at the original url:
/item/10101
it displays it at its own url:
/process_form
Is it possible to redisplay the form at the original URL?
/item/10101
(I've tried getting the referrer and redirecting to it in processForm but then all of the model contents end up displayed as URL name/value pairs:)
#RequestMapping(value = "/process_form", method = RequestMethod.POST)
public final String processForm(HttpServletRequest request,
#ModelAttribute("foo") FooModel fooModel,
BindingResult bindResult,
ModelMap model)
{
String referrer = request.getHeader("referer");
FooModelValidator validator = new FooModelValidator();
validator.validate(FooModel, bindResult);
if (bindResult.hasErrors())
{
model = this.fillModel(fooModel.getItemId());
return "redirect:" + referrer;
}
return "account";
}
Short answer: No.
What happens is a server-side redirect (forward), which is within the same request, and so the submitted values are preserved (and displayed in the form)
The url will change if you use a client-side redirect (return "redirect:item";), but in that case a new request will come and the submitted values will be lost.
But here are two options that you have:
use the same URL in the mappings for both methods and distinguish them based on request method - GET for the former, POST for the latter. This might be confusing, so document it.
find / implement flash scope for spring-mvc. There's nothing built-in. The flash scope means that values are preserved (in the session usually) for a submit and the subsequent redirect. This option includes the manual handling, by putting the submitted object in the session, and later retrieving & removing it