I was having some problem when trying to access session attribute in Controller. I declared my session attributes as such:
#Controller
#SessionAttributes({ WebKeys.OBJECT_SIX, WebKeys.DSP_LOGIC, WebKeys.NEW_CARD_FORM })
In each of my API, I am calling the function:
#RequestMapping(value = "/apiA.do", method = RequestMethod.POST)
public String doAPIa(Model model) {
setInfo(model);
}
#RequestMapping(value = "/apiB.do", method = RequestMethod.POST)
public String doAPIb(Model model) {
setInfo(model);
}
In my setInfo(), I am trying to access the session attribute and add value back to the model:
private void setInfo(Model model) throws Exception{
String populationId = // need to get from WebKeys.OBJECT_SIX session attribute
if(populationId!=null && (populationId.equals(Constants.POP_TYPE_ID))){
DisplayHelperTO helper = (DisplayHelperTO) // need to get from WebKeys.DSP_LOGIC;
NewCardNewBasicForm newCardForm = (NewCardNewBasicForm ) // need to get from WebKeys.NEW_CARD_FORM);
model.addAttribute("newCardForm", newCardForm);
model.addAttribute("dspLogic", helper);
}
}
I tried to declare in such way:
private void setInfo(Model model,
#SessionAttribute(WebKeys.OBJECT_SIX) String populationId) throws Exception{
}
However, if I am declaring the function in this way, the part to call the setInfo() in both doAPIa and doAPIb will be highlighted in syntax error. Any ideas on how to access the session attributes in function? Thanks!
Related
in the below example, i am using POST and GET methods. post is to initialize a varibale and GET is to get this varibale.
I use Postman to make the requests.
i am receiving an error
#RequestBody(value = "val") //cant resolve method value
please let me know how to fix the belwo error so i can use post method for initialization and get methdo to retrieve the value
Controller1
#Controller
#RequestMapping("/call1")
public class Call1 {
public String str = "inti";
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody(value = "val") String val) {
this.str = val;
}
#RequestMapping(value = "/getparam1", method = RequestMethod.GET)
public String getParam1() {
return this.str;
}
}
Create a class Variable and use other code in controller.
class Variable {
String data= 'val';
}
#RequestMapping(value = "/intiparam1", method = RequestMethod.POST)
public void intiParam1(#RequestBody Variable val) {
this.str = val.data;
}
When making a request pass json as {"data":"12345"}
and then use #RequestBody Variable v in code instead of String as it will serve your purpose of default value and will make the code extensible as you can add different properties to the existing variable in future if needed.
When to use #RequestBody?
You can not use value with it. You can use this when you have multiple field entity which you want to perform the operation. Let's say you want to save the user then you may need to create User Model first and use in a controller #RequestBody.
Model:
public class User
{
#Id
private int id;
private String firstname;
private String lastname;
//Getters-Setters, AllArgConstructor-constructor
}
#RequestMapping(value = "/requestBodyExample", method = RequestMethod.POST)
public String intiParam1(#RequestBody User user) {
return user.getFirstname();
}
Quick Start with Spring Boot
I am trying to get a object sent to a Spring-boot controller in one Class to be available in the model of another controller.
It seems like #SessionAttributes is for objects that are global (like the logged on user).
I have tried this on controller 1
#Component
#Controller
#SessionAttributes(value = { "user"})
public class FormController {
#GetMapping("/occurence/{occno}")
public String findOcc(#PathVariable String occno, OccViewModel occViewModel, Model model) {
Occ occ = occRepository.findByOccno(occno);
occViewModel.setOcc(occ);
occViewModel.setPersons(occPersonRepository.findOccPersonByOcc(occ.getId()));
List<OccPerson.OccRole> occRoles = Arrays.asList(OccPerson.OccRole.values());
model.addAttribute("occRoles", occRoles);
model.addAttribute("occViewModel", occViewModel);
model.addAttribute("countries", countries);
return "occ";
}
I have a button on this form which sends the user to this endpoint - I would like the same occViewModel to available to this endpoint on controller 2
#Component
#Controller
#SessionAttributes(value = { "user" })
public class PlanController {
#GetMapping("/newplan")
public String newPlan(Model model, OccViewModel occViewModel, HttpSession session) {
// create PlanViewModel DTO
Occ occ = new occVieModel.getOcc();
PlanViewModel planViewModel = new PlanViewModel;
planViewModel.setOcc(occ);
model.addAttribute(planViewModel);
//etc
}
I see there is #SessionAttributes but i do not understand in my first controller how I would even load it into the session if I dont know what Occ to get from the repo as it appears you need to #ModelAttribute prior to the handler - but the URI gives the occno?
I looked here also but it appeared do deal with the same class only and it wasn't clear how you would apply this to a id passed in on the URI.
I think I have this working correctly to retrieve a object from the database, put it in session and send via GET to the view. The view then later POST the data back to the handler and the object coming back from view is hydrated against the object in session (before being passed to Hibernate).
There is a POST and GET controller for OccViewModel. The #SessionAttributes means that between a Get and a Post the object is held in session and I do not need to pass the object id in hidden tags.
#Component
#Controller
#SessionAttributes(value = { "user", "occViewModel" })
public class FormController {
#PostMapping("newOcc")
public String occSubmit(#Valid #ModelAttribute("occViewModel") OccViewModel occViewModel, BindingResult result, Model model
HttpServletRequest request, SessionStatus status) {
// NEW OCC
if( occViewModel.getOcc().getId() == null ) {
occService.saveNewOcc(occViewModel.getOcc(), occViewModel.getPersons());
}
//UPDATE OCC
if( occViewModel.getOcc().getId() != null ) {
occService.updateOcc(occViewModel.getOcc(), occViewModel.getPersons());
}
}
status.setComplete();
return "redirect:/dashboard";
}
#GetMapping("/occ/{occno}")
public String findOcc(#PathVariable String occno, OccViewModel occViewModel, Model model) {
// POPULATE OCC VIEW MODEL
Occ occ = occRepository.findByOccno(occno);
occViewModel.setOcc(occ);
model.addAttribute("occViewModel", occViewModel);
return "occ";
}
I believe that OccViewModel must be passed as a parameter into POST and GET handlers.
In terms of then passing this object to another handler in another controller which was done for the sake of keeping the project tidy:
#Component
#Controller
#SessionAttributes(value = { "user", "occPlanWork" })
public class PlanController {
#GetMapping("/occ/{occno}/plan")
public String findPlan(#PathVariable String occno, OccPlanWork occPlanWork, Model model) {
// GET OCC FROM OCCNO
Occ occ = new Occ();
occ = occRepository.findByOccno(occno);
// SET EPT DATA
occPlanWork.setOccno(occ.getOccno());
occPlanWork.setStart_date(occ.getStart_date());
occPlanWork.setOccId(occ.getId());
// CREATE NEW PLAN IF BLANK
if (occ.getPlan()== null) {
Plan plan = new Plan();
occPlanWork.setPlan(plan);
}
if (occ.getPlan()!=null) {
Plan plan = new Plan();
plan = occ.getPlan();
occPlanWork.setPlan(plan);
}
// SET THE EXISTING WORKS (AND CONVERT SET<WORK> TO LIST<LIST> FOR TH COMPATABILITY)
if (occPlanWork.getPlan().getId()!=null) {
List<Work> works = new ArrayList<>(occPlanWork.getPlan().getWorks());
Collections.sort(works);
occPlanWork.setWorks(works);
} // CREATE NEW WORK LIST IF PLAN IS NEW
if (occPlanWork.getPlan().getId()==null) {
List works = new ArrayList();
occPlanWork.setWorks(works);
}
// RETURN EPT
model.addAttribute("occPlanWork", occPlanWork);
return "newplan";
}
That was achieved by passing the occurrence number in the URI to the other controller. Again the object backing the view (occPlanWork) is in Session Attributes on the controller level.
I have some external url for payment. After payment is done it redirects to me back.
#RequestMapping(value = "/first", method = RequestMethod.GET)
public String first(#RequestParam("id") String id) {
doSomething(id);
return "redirect:/externalurl"
}
// This method is called from external url
#RequestMapping(value = "/second", method = RequestMethod.GET)
public String second() {
// I want to get here id from first call
}
Is it possible somehow to do it with RedirectAttributes or other similar approach like to add it in first() method and to get it in second() method ?
I am using Spring 3.2.0 MVC. In that I have to store one object to session.
Currently I am using HttpSession set and get attribute to store and retrieve the value.
It returns only the String not Object. I want to use #SessionAttribute when I tried it sets the object in session but I could not retrieve the session object
#RequestMapping(value = "/sample-login", method = RequestMethod.POST)
public String getLoginClient(HttpServletRequest request,ModelMap modelMap) {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
User user = sample.createClient(userName, password);
modelMap.addAttribute("userObject", user);
return "user";
}
#RequestMapping(value = "/user-byName", method = RequestMethod.GET)
public
#ResponseBody
String getUserByName(HttpServletRequest request,#ModelAttribute User user) {
String fas= user.toString();
return fas;
}
Both methods are in same controller. How would I use this to retrieve the object?
#SessionAttributes annotation are used on the class level to :
Mark a model attribute should be persisted to HttpSession after handler methods are executed
Populate your model with previously saved object from HttpSession before handler methods are executed -- if one do exists
So you can use it alongside your #ModelAttribute annotation like in this example:
#Controller
#RequestMapping("/counter")
#SessionAttributes("mycounter")
public class CounterController {
// Checks if there's a model attribute 'mycounter', if not create a new one.
// Since 'mycounter' is labelled as session attribute it will be persisted to
// HttpSession
#RequestMapping(method = GET)
public String get(Model model) {
if(!model.containsAttribute("mycounter")) {
model.addAttribute("mycounter", new MyCounter(0));
}
return "counter";
}
// Obtain 'mycounter' object for this user's session and increment it
#RequestMapping(method = POST)
public String post(#ModelAttribute("mycounter") MyCounter myCounter) {
myCounter.increment();
return "redirect:/counter";
}
}
Also don't forget common noobie pitfall: make sure you make your session objects Serializable.
I would like to know how to read a flash attributes after redirection in Spring MVC 3.1.
I have the following code:
#Controller
#RequestMapping("/foo")
public class FooController {
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(...) {
// I want to see my flash attributes here!
}
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public ModelAndView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new ModelAndView().setViewName("redirect:/foo/bar");
}
}
What I am missing?
Use Model, it should have flash attributes prepopulated:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(Model model) {
String some = (String) model.asMap().get("some");
// do the job
}
or, alternatively, you can use RequestContextUtils#getInputFlashMap:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(HttpServletRequest request) {
Map<String, ?> inputFlashMap = RequestContextUtils.getInputFlashMap(request);
if (inputFlashMap != null) {
String some = (String) inputFlashMap.get("some");
// do the job
}
}
P.S. You can do return return new ModelAndView("redirect:/foo/bar"); in handlePost.
EDIT:
JavaDoc says:
A RedirectAttributes model is empty when the method is called and is
never used unless the method returns a redirect view name or a
RedirectView.
It doesn't mention ModelAndView, so maybe change handlePost to return "redirect:/foo/bar" string or RedirectView:
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public RedirectView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new RedirectView("/foo/bar", true);
}
I use RedirectAttributes in my code with RedirectView and model.asMap() method and it works OK.
Try this:
#Controller
public class FooController
{
#RequestMapping(value = "/foo")
public String handleFoo(RedirectAttributes redirectAttrs)
{
redirectAttrs.addFlashAttribute("some", "thing");
return "redirect:/bar";
}
#RequestMapping(value = "/bar")
public void handleBar(#ModelAttribute("some") String some)
{
System.out.println("some=" + some);
}
}
works in Spring MVC 3.2.2
For all those like me who were having problems with seeing the POST url in the browser when a validation would fail.
The POST url is a private url that should not be exposed to users but it was automatically rendered when a validation failed. i.e. if a field was below a minimum length. I was using #Valid. I wanted the original GET url of the form to show at all times even when validation bounced back to the form, so I did the following:
if (validation.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.story", validation);
redirectAttributes.addFlashAttribute("story", story);
return new ModelAndView("redirect:/january/2015");
where story is the form object representation, redirectAttributes are RedirectAttributes you put in the method signature and validation is the BindingResult. /january/2015 is the mapping to the GET controller where the form lives.
After this implementation, in the mapping for /january/2015, story comes in intact as follows:
Story story= (Story) model.asMap().get("story");
//story from the POST method
I had to augment my GET method and check if this was not null. If not null, then send this to the form else I would send a newly initialized Story type to the form as default behaviour before.
In this manner, I am able to return to the form with the bindingresults intact (errors show on form) but have my GET url in place of the post url.