Announcement Announcement Module
Collapse
No announcement yet.
Controller design issue - Keeping Oject in memory for different requests Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Controller design issue - Keeping Oject in memory for different requests

    Hi all,

    I am trying to implement a wizard like form controller using Spring annotations. I have one problem of lazy initialization while going from one page to another.

    I guess that I have a problem in desgin and I would like to ask suggestion. In the controller below I define 2 methods the Step1Submit one is getting the param cityID from the page and assign the City object to the RegisterEstate estate class. When I am trying to recover the City.getAdministrativeCode().getName() from the method Step2Get got a lazy exception because the metod Step1Submit did not stored the complete object graph.
    Code:
    @RequestMapping(value = "/registerestate.htm", method = RequestMethod.POST)
       public ModelAndView step1Submit(@ModelAttribute("registerEstate") RegisterEstate registerEstate,
                                       ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception {
          
          //set the city from the ID stored on the web page
          City city = citiesService.getCity(request.getParameterValues("cityID")[0])
          registerEstate.getEstate().setCity(city);
          //store data in the session
          HttpSession session = request.getSession(true);
          session.setAttribute("registerEstate", registerEstate);
          ModelAndView mav = new ModelAndView("redirect:contract.htm");
          return mav;
       }
    
       @RequestMapping(value = "/contract.htm", method = RequestMethod.GET)
       public ModelAndView step2Get(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
          ModelAndView mav = new ModelAndView(viewStep2);
          HttpSession session = request.getSession(true);
          RegisterEstate registerEstate = (RegisterEstate) session.getAttribute("registerEstate");
          //lazy error on the next line
          registerEstate.getEstate().getCity().getAdministrativeCode().getName();
          mav.addObject("registerEstate", registerEstate);
          return mav;
       }
    Is there another way to accomplish this ? I am trying to create a sequence of pages which basically create piece by piece a big object that at the final page is submitted to the DB (I am trying to mimic the Wizard Form Controller). I guess that the way I am passing the register estate across the Get/Submit method is incorrect. I understood that now I do not keep the requests in the same HTTP session, which cause this problem.

    Any suggestion will be highly appreciated

  • #2
    Hi Davide,

    I'm going to take a guess here: you are using Hibernate, aren't you?

    Your problem is that the session is closed after the first method is invoked; any access to an uninitialized proxy thereafter will cause a LazyInitializationException error because your City instance will be detached from the Session. OpenSessionInViewFilter will not be of any help since your concern is what happens in the second request handled by the controller, and OSIV closes the session after rendering the view returned by the first request handled by the controller.

    I see three possibilities for you here:
    1. If you're doing only reads in the second method (and third, fourth, ... methods as well if any) - and it seems to be the case in your exemple - then you could get away with it by forcing the initialization of all the proxies in the first method, i.e. invoke somewhere in step1Submit before returning the ModelAndView:
      Code:
      city.getAdministrativeCode().getName();
      You will just need to be careful not to forget any proxy initialization in step1Submit.

    2. If you're doing writes, either:
      • Reattach objects in the second method (step2get) prior to doing anything with them (see Hibernate template's refresh() method, although I think you can also do it with Hibernate template's lock() method - someone please correct me here if I'm wrong). This essentially means that you're going to have two separate sessions (and transactions of course): one in step1submit, one in step2Get.

        Note that this will result in calls to the DB unless you have some second-level cache; I would also recommend using versioning for these beans (or face the possibility of overwriting data written between the two sessions).

      • Use a long transaction (c.f. http://forum.springframework.org/sho...lerInterceptor and http://www.cs.bham.ac.uk/~aps/syllab...ml#transaction).
        In this case you won't need versioning, but I don't recommend this solution as it is not a good idea to tie the duration of a transaction to the responsiveness of the UI / the user. Depending on the context, you risk having a lot of conflicts and wasting database resources.

    Hope this helps!

    Comment


    • #3
      HI Tama,

      yes I am using Hibernate. At the end following your advice I went for initializing the proxies (the 1st solution).

      So far it is working perfectly and maybe I should just add more JUnit testing to check that all the proxies are initialized before the other method, in case of code changes.

      Thank you again for the solution !

      Comment

      Working...
      X