Call a method only one time per user session - session

I would like to call a method of my Spring Controller only one time per user session.
#RequestMapping(value = "/user.html")
public String getUser(Model model) {
doSomethingAtEachCall();
doSomethingOnlyOneTimePerSession(); // call only first time user access to this page
return "user";
}
How can I do that (properly) ?

Related

Spring Security - How to get authenticated object in non-secure and secure pages?

I have a Spring-boot/Thymeleaf application with two ends point:
1: /int/: requires sso/authorization;
2. /ext/: public pages, everyone can access;
Using a PreAuthenticationFilter, I was able to secure /int/* pages. When an user tries to access the /ext/* pages, I'd like to be able to tell in the controller if the user has previously been authenticated (by accessing a secured page). Currently I save the authenticated Principal object in the HTTP session in UserDetailsService's loadUserDetails(). Just curious if this is the right way (or a better way) to do it.
You can get your authenticated object via #AuthenticationPrincipal annotation instead of getting the object from httpsession and casting it back to your object for every controller method.
Let me give you an example, given login page is a public page and User object as below:
User Class:
public class User implement UserDetails {
String contact;
Integer age;
}
Controller:
#GetMapping(value = "/login")
ModelAndView login(#AuthenticationPrincipal User user) {
if (user == null) {
return new ModelAndView("/login");
} else {
return new ModelAndView(new RedirectView("/home"));
}
}

how to pass object between two controllers in spring mvc?

Actually I've googled to see how we can pass data from one controller to another in Spring MVC and I found that using flash attributes do the job.
It consists on declaring one controller with RequestMapping=GET and an other with RequestMapping=POST. I have tested this code in my controller and it worked.
#RequestMapping(value ="/ajouter", method = RequestMethod.POST)
public String add(#ModelAttribute User user,final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("user", user);
return "redirect:/account";
}
and the other:
#RequestMapping(value ="/account", method = RequestMethod.GET)
public String addAccount(#ModelAttribute("user") User user,#ModelAttribute Account account) {
System.out.println(user.getId());
return "account";
}
But I have another case: I have two JSPpages:
The first will add a user into the database. I want to recuperate the id of the user just inserted to set it as a foreign key for the account (after submitting the page for adding a user, a second page for adding an account appears).
I've tested this code:
This controller will insert a user into the database and recuperate the user which has been just inserted.
#RequestMapping(value ="/addUser", method = RequestMethod.POST)
public String add(#ModelAttribute User user,final RedirectAttributes redirectAttributes) {
this.userService.insertData(user);
redirectAttributes.addFlashAttribute("user", user);
return "redirect:/account";
}
and this controller will insert an account into the database, but can not recuperate the user id of the user just inserted.
#RequestMapping(value= "/ajouterCompte", method = RequestMethod.POST)
public String addCompte(#ModelAttribute("account") Account compte,#ModelAttribute("user") User user){
System.out.println(user.getId()); //this code shows 0
System.out.println(compte.getPwd());
String hashPassword = passwordEncoder.encode(compte.getPwd());
System.out.println(hashPassword);
compte.setPwd(hashPassword);
compte.setId(user.getId());
this.compteService.insertCompte(compte);
return "redirect:/users";
}
I guess that the problem is that the 2 controllers are declared with a method method = RequestMethod.POST when it should be one GET and an other POST. But in this case how can I recuperate the id of the user so that it could be inserted into the database?
When I declare the second controller with GET, the insertion of the database fails!
Need your help please :(
The object which are set as flash attributes are only available for the first request after those have been set. (As also explained in the reference guide).
Assuming that in your account controller you have a GET based method for /account pre-populate the Account with the information at that point.
public String account(#ModelAttribute("user") User user, Model model) {
Account account = new Account();
account.setId(user.getId());
model.addAttribute("account", account);
return "account";
}
Now you can either annotate your controller with #SessionAttribute("account") to have the Account stored in the session in between requests. If so then you have to modify your POST handling method to include a SessionStatus object and after storing call setComplete() on it.
public String addCompte(#ModelAttribute("account") Account compete, SessionStatus sessionStatus){
...
sessionStatus.setComplete();
return "redirect:/users";
}
Or store the pre-filled information in hidden form fields so that it gets passed along with the following request and the Account can be reconstructed.
<form:hidden path="id" />

How to Update All Fields Submitted in a Form - Spring MVC

I have a form that has 10+ field inputs that will get updated by a user. On submit I need to update the object (by id) and any/all fields that were modified in the form (utilizing Spring Data JPA & Repositories). I believe I can do this by passing the #ModelAttribute as a method argument tied to my object, but I don't quite fully understand this yet. Here's my Controller
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("User") User user, #PathVariable Long id, Model model) {
user = userRepo.findOne(id); //Spring Repository method to find user by ID
// Here is where you'd set all fields of the User object including those modified in the form
model.addAttribute("user", user);
userRepo.save(user); //Updates user in database
return "success";
}
I'm looking for a method that would do the exact same thing as:
user.setName(user.getName());
user.setAddress(user.getAddress));
//etc.
Without explicitly calling each set method (the number of field inputs will grow).
Thanks mates
If you have a form and you´re using ModelAndAttribute you just need to set the id attribute to be send to the Controller
<form:input id="id" path="id"/>
<form:input id="name" path="name"/>
<form:input id="address" path="address"/>
Then in your controller you just need to do what you´re just doing
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("User") User user, #PathVariable Long id, Model model) {
user = userRepo.findOne(id); //Spring Repository method to find user by ID
// Here is where you'd set all fields of the User object including those modified in the form
model.addAttribute("user", user);
userRepo.save(user); //Updates user in database
return "success";
}
BUT, if you´re doing this request by Ajax you will need to load the again the entity User to set the new entity in your form with the new Id.
You can take a look to JQuery load to load the form element again.
Or if the save is done by HTTP Request you must refresh the page after save so you need to return again the ModelAndView with the entity user already update with an id
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("User") User user, #PathVariable Long id, Model model) {
user = userRepo.findOne(id); //Spring Repository method to find user by ID
userRepo.save(user); //Updates user in database
ModelAndView mav = new ModelAndView(yourview);
mav.setObject("user", user);
return mav;
}

How to call one controller to another controller URL in Spring MVC?

Hi I am new to Spring MVC ,I want to call method from one controller to another controller ,how can I do that .please check my code below
#Controller
#RequestMapping(value="/getUser")
#ResponseBody
public User getUser()
{
User u = new User();
//Here my dao method is activated and I wil get some userobject
return u;
}
#Controller
#RequestMapping(value="/updatePSWD")
#ResponseBody
public String updatePswd()
{
here I want to call above controller method and
I want to update that user password here.
how can I do that
return "";
}
any one help me .
Can do like this:
#Autowired
private MyOtherController otherController;
#RequestMapping(value = "/...", method = ...)
#ResponseBody
public String post(#PathVariable String userId, HttpServletRequest request) {
return otherController.post(userId, request);
}
You never have to put business logic into the controller, and less business logic related with database, the transactionals class/methods should be in the service layer. But if you need to redirect to another controller method use redirect
#RequestMapping(value="/updatePSWD")
#ResponseBody
public String updatePswd()
{
return "redirect:/getUser.do";
}
A controller class is a Java class like any other. Although Spring does clever magic for you, using reflection to examine the annotations, your code can call methods just as normal Java code:
public String updatePasswd()
{
User u = getUser();
// manipulate u here
return u;
}
You should place method getUser in a service (example UserService class) .
In the getUser controller, you call method getUser in the Service to get the User
Similarly, in the updatePswd controller, you call method getUser in the Service ,too
Here no need to add #reponseBody annotation as your redirecting to another controller
Your code will look like
#Controller
class ControlloerClass{
#RequestMapping(value="/getUser",method = RequestMethod.GET)
#ResponseBody
public User getUser(){
User u = new User();
//Here my dao method is activated and I wil get some userobject
return u;
}
#RequestMapping(value="/updatePSWD",method = RequestMethod.GET)
public String updatePswd(){
//update your user password
return "redirect:/getUser";
}
}

Session Handling in Spring MVC 3.0

I am using session.setAttribute to store user object after login. In next controller, I have #SessionAttribute for the same user and #ModelAttribute for same object to be used in the method mapped to a RequestMapping. After login if I click any link in the user home page it give
HttpSessionRequiredException: Session attribute '' required - not found in session
I am not sure what I am doing wrong. I went through many article and question in this site as well but could find any solution. The user object which I am storing in session stores user's account details which are required in all the controller to get different information from DB. I using SessionAttribute is wrong should I use HttpSession instead in all the controller and get the object from session manually or there is a proper way to handle in spring 3.0. Please note that this user object is not backing any form just login, but contains many other details.
As help would be good.
Have a look at my (non-perfect) use of session data:
#Controller
#SessionAttributes("sharedData")
public class RegistrationFormController {
#Autowired
private SharedData sharedData; // bean with scope="session"
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.GET)
public ModelAndView newForm() {
final ModelAndView modelAndView = new ModelAndView("registrationForm");
modelAndView.addObject("registrationForm", new RegistrationForm());
// I want to render some data from this object in JSP:
modelAndView.addObject("sharedData", sharedData);
return modelAndView;
}
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.POST)
public String onRegistrationFormSubmitted(HttpServletRequest request,
#ModelAttribute("registrationForm") RegistrationForm registrationForm, BindingResult result) {
if (result.hasErrors()) {
return "registrationForm";
}
// Perform business logic, e.g. persist registration data
return "formSubmitted";
}
}

Resources