I have a Spring MVC project setup where I define several model attributes & session attributes when a user accesses the home page home.html.
HomeController.java
#RequestMapping(value = "/getHomepage", produces = "text/html", method = RequestMethod.GET)
protected ModelAndView getHomepage(HttpSession session) {
ModelAndView mav = new ModelAndView("home");
// do some stuff
session.setAttribute("attr1", "cool");
session.setAttribute("attr2", "attributes");
return mav;
}
I grab these session attributes on a separate orderForm.html (I'm using Thymeleaf as my template engine)
Session Attribute 1: <div th:text="${session.attr1}"></div>
Session Attribute 2: <div th:text="${session.attr2}"></div>
This works fine until my session is timed out/invalidated and the user is still on orderForm.html - they lose scope of the session attributes as they're defined only on the Home #Controller
Can I retrieve my session attributes without first hitting the homepage and without setting them on every view #Controller in my project?
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 WEB-INF having a Jsp File pls see image I am using Spring mvc with Hibernate Database connection,in my controller having data from database in variable val now how can i redirect to another jsp page with data's
Controller Part:
#RequestMapping(value = "/EditShop" , method = RequestMethod.POST)
public String editShop(HttpServletRequest request,HttpServletResponse response) throws IOException
{
String id=request.getParameter("Id");
try
{
String val=shopService1.editShopinfo(id);
System.out.println("Edit Shop : "+val);
}
catch(Exception e)
{
System.out.println("Edit Shop : "+e );
}
return "redirect:/EditShop.jsp";
}
You can pass data from controller to UI(another JSP page) with the help of ModelAndView in Spring.
new ModelAndView("newJSPPage","aliasNameToBean",originalBean);
newJSPPage - replace with the new JSP file which you need to redirect from the controller.
aliasNameToBean - replace with the alias name which you can access bean data at redirected JSP page.
originalBean - replace with the original bean object name which you have the data.
return "redirect:/EditShop.jsp";
Insted of this you have return View Name like
return "EditShop";
In Spring Execution Flow InternalResourceViewResolver will Take Care to Call Jsp.
you have to set val to HttpSession Object like session.setAttribut("val",valueofField);
Then you get that value In your jsp
session.getAttribute("val");
I Hope it helps.
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.
Im facing a an issue while Im adding a method to the controller class with #RequestMapping(method = RequestMethod.POST) annotation. The issue is when I add this method and start application. Application unable to load resources (css,JS etc). On the browser I get:
Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
and on the Run logs I get this message:
org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
WARNING: Request method 'GET' not supported
When I remove this method from the controller class, all works fine. Dont know why is this happening. Im sure its nothing to do with Configuration or resources in Dispatcher Servlet mapping because without this method every thing works perfectly fine.
I need to use this method because of some business requirement, which otherwise is not possible.
Can any body help me in Identifying where the issue is.
#Controller
public class InvoiceController
{
#RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView adminPage() {
String username;
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
username = auth.getName(); //get logged in username
username.toUpperCase();
// Logic to build menue based on the Role of the user.
HashMap hm = new HashMap();
OrderItems od = new OrderItems();
ModelAndView model = new ModelAndView();
model.addObject("usr", username);
//Set the object for Menue Links on the Page
model.addObject("mnue", hm);
model.setViewName("index");
model.addObject("odi",od);
return model;
}
#RequestMapping(method = RequestMethod.POST)
public String save(HttpServletRequest request,
HttpServletResponse response,
Model model)
{
System.out.println("Im here in Genaric Post Method");
return null;
}
}
Please also note that Im using Spring Security configurations. Is there anything to do with Security? Or there is some issue with Controller Class configuration.
Thanks in advance for your anticipation.
Regards,
D Kamran
Add endpoint url value to request mapping
#RequestMapping(value="/index", method = RequestMethod.POST)
This happens because Post method declared mapped to all paths as both Method and Controller class don't have that value
I'm developing a simple web application using spring MVC and thymeleaf. I have a form correctly handled by this method in my controller
#RequestMapping(value = "/list", method = RequestMethod.POST)
public ModelAndView searchJob(
#ModelAttribute(SEARCH_PARAMS) #Valid SearchParams params,
BindingResult bindingResult) {
ModelAndView output = null;
if (!bindingResult.hasErrors()) {
JobsAPIImplService service = new JobsAPIImplService();
JobsAPI api = service.getJobsAPIImplPort();
ArrayList<NoaJob> jobs = (ArrayList<NoaJob>) (api.search(JobUtils.toSearchParams(params))).getItem();
output = new ModelAndView("scheduler/list");
output.addObject("jobs", jobs);
} else {
// errors handling
}
return output;
}
So in my result page I can access to the ArrayList "jobs" in this way:
<tr th:each="job : ${jobs}">
...
</tr>
In the same page, I have a simple link which calls another GET method on the same controller. The goal here is to have the same ArrayList in another page in order to implement a "back" button without re-executing the search logic (a call to a web service).
Here is the method called
#RequestMapping(value="/list/{id}", method = RequestMethod.GET)
public ModelAndView details(#PathVariable("id") String jobUuid,
#ModelAttribute("jobs") ArrayList<NoaJob> jobs) {
ModelAndView output = new ModelAndView("scheduler/details");
LOGGER.info("Size jobs list: " + jobs.size());
NoaJob job = new NoaJob();
job.setJobUuid(jobUuid);
output.addObject("job", job);
output.addObject("jobs", jobs);
return output;
}
the problem is that the arraylist here is always null! I read that in GET requests Spring allocates a new ModelAttribute, so how can I pass this object throug pages?
Define a session attribute like this in the head of your controller:
#SessionAttributes({ "myFancyList"})
#Controller
public class HomeController {
// your code here
}
Now.. when you have to insert the "list" to be viewable via thymeleaf:
output.addObject("myFancyList", jobs);
and modify thymleaf pseudocode accordingly.
in the "post" of the search "override" the session attribute with the current search result..
i think this should do the trick for you