Announcement Announcement Module
Collapse
No announcement yet.
Problem with usage of SimpleFormController Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with usage of SimpleFormController

    Dear all,

    Below is a stripped down version of a SimpleFormController I'm using, and having a slight problem with.
    I tried to leave exactly the code that might be relevant there.

    The formBackingObject initialises an Employee command object. The retrieveEmployee method that does
    this correctly initializes an employee.getA().getB() member, which is correctly displayed in the page the first time.

    If the form is then submitted, it usually works well, because I redirect with almost all of the pageAction actions.
    However, if I do not return a modelAndView with a viewName starting with "redirect:" here, the problem occurs.

    I get a LazyInitializationException on the employee.getA().getB().
    I don't understand what is exactly happening here, but my guess is it has something to do with the "Invalid submit detected".
    I do not understand why it is not finding the Form object in session.
    Below is a fragment of the log output.

    Just before the LazyInitializationException a line says "Removing form session attribute". Who is doing this?
    The logger says "MedewerkerController [449]" but that line of code has nothing to do with it.

    I would be grateful if anybody could help me clear this up.
    (In the mean-time, I will simply make sure I'll always redirect at the end of the onSubmit method )

    Code:
    DEBUG 2009-07-23 09:00:22  nl.bmc.gis.administratie.medewerker.controller.MedewerkerController [89] - In handleRequestInternal (setting pageMode/formAction/mdeCode/viewName)
    DEBUG 2009-07-23 09:00:22 MedewerkerController [270] - Invalid submit detected: Form object not found in session (in session-form mode)
    DEBUG 2009-07-23 09:00:22 MedewerkerController [655] - formBackingObject returns [320, Pieter Wever]
    DEBUG 2009-07-23 09:00:23 MedewerkerController [266] - No errors -> processing submit
    DEBUG 2009-07-23 09:00:23 MedewerkerController [233] - onSubmit with pageAction: deleteContract
    DEBUG 2009-07-23 09:00:23 MedewerkerController [325] - TODO: Remove contract with ECT_ID 320 and startdate 15-01-2003
    DEBUG 2009-07-23 09:00:23 MedewerkerController [564] - Setting form session attribute [nl.bmc.gis.administratie.medewerker.controller.MedewerkerController.FORM.medewerkerInput] to: nl.bmc.gis.domain.generated.Employee@ed0b79
    DEBUG 2009-07-23 09:00:23 MedewerkerController [449] - Removing form session attribute [nl.bmc.gis.administratie.medewerker.controller.MedewerkerController.FORM.medewerkerInput]
    23-jul-2009 9:00:23 org.apache.catalina.core.ApplicationDispatcher invoke
    SEVERE: Servlet.service() for servlet jsp threw exception
    org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    Thanks in advance,
    Jonne.


    Code:
    The configuration:
    ===============
    
    	<bean id="medewerkerController"
    		class="nl.bmc.gis.administratie.medewerker.controller.MedewerkerController">
    		<property name="validator" ref="medewerkerInputValidator" />
    		<property name="sessionForm" value="true" /> <!-- store command object in session? -->
            <property name="commandName" value="medewerkerInput" />
            <property name="commandClass" value="nl.bmc.gis.domain.generated.Employee" />
    	</bean>
    	<bean id="urlMapping"
    		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    	  <property name="mappings">
    		<props>
    			<prop key="/medewerkerView.htm">medewerkerController</prop>
    			<prop key="/medewerkerEdit.htm">medewerkerController</prop>
    		</props>
    	  </property>
    	</bean>
    
    The controller:
    ===============
    
    public class MedewerkerController extends SimpleFormController {
    
    	enum Mode {EDIT, VIEW};
    	
    	/**
    	 * Test whether we are in View or Edit mode according to the request.
    	 * @param request
    	 * @return
    	 */
    	private Mode getPageMode(HttpServletRequest request) {
    		String requestURL = request.getRequestURL().toString();
    		if(requestURL.contains("/medewerkerEdit.htm")) {
    			return Mode.EDIT;
    		} else {
    			return Mode.VIEW;
    		}
    	}
    	
    	/**
    	 * Overriding handleRequestInternal to go to the right view.
    	 */
    	@Override
    	protected ModelAndView handleRequestInternal(HttpServletRequest request,
    			HttpServletResponse response) throws Exception {
    
    		log.debug("In handleRequestInternal (setting pageMode/formAction)");
    		ModelAndView modelAndView = super.handleRequestInternal(request, response);
    		if(modelAndView == null) {
    			log.debug("super returned null, creating a fresh ModelAndView.");
    			modelAndView = new ModelAndView();
    		}
    		
    		if(getPageMode(request).equals(Mode.EDIT)) {
    			// Page in edit mode
    			modelAndView.addObject("pageMode", "edit");
    			modelAndView.addObject("formAction", "medewerkerEdit.htm");
    		} else {
    			// Page in read-only mode
    			modelAndView.addObject("pageMode", "view");
    			modelAndView.addObject("formAction", "medewerkerView.htm");
    		}
    		
    		if(modelAndView.getViewName() == null || !modelAndView.getViewName().startsWith("redirect:")) {
    			modelAndView.setViewName("medewerker");
    		}
    		return modelAndView;
    	}
    	
    	/**
    	 * Registering several custom property editors
    	 */
    	@Override
    	protected void initBinder(HttpServletRequest request,
    			ServletRequestDataBinder binder) throws Exception {
    		
    		super.initBinder(request, binder);
    
    		DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
    		CustomDateEditor editor = new CustomDateEditor(df, true);
    		binder.registerCustomEditor(Date.class, editor);
    	}
    
    	/**
    	 * Fill in some fields automatically before validation starts. These are the
    	 * employee that is modifying or creating this record and some timestamps.
    	 */
    	@Override
    	protected void onBind(HttpServletRequest request, Object command) throws Exception {
    		HttpSession session = request.getSession();
    		Employee sessionEmployee = (Employee) session.getAttribute(
    				SessionAndSecurityInterceptor.SESSION_EMPLOYEE_ATTRIB_NAME);
    		String pageAction = request.getParameter("pageAction");
    		
    		Employee employee = (Employee) command;
    		Date now = new Date();
    
    		if(employee.getEpeId() <= 0) {
    			// Inserting
    			employee.setEmployeeByEpeCreateEpeId(sessionEmployee);
    			employee.setEpeCreatedate(now);
    		}
    
    		// Always set these fields
    		employee.setEmployeeByEpeChangeEpeId(sessionEmployee);
    		employee.setEpeChangedate(now);
    
    		super.onBind(request, command);
    	}
    	
    	/**
    	 * De onSubmit methode wordt aangeroepen als het formulier gesubmit wordt en
    	 * zorgt ervoor dat de ingevoerde benchmark goed wordt opgeslagen.
    	 */
    	@Override
    	protected ModelAndView onSubmit(HttpServletRequest request,
    			HttpServletResponse response, Object command, BindException errors)
    			throws Exception {
    		log.debug("onSubmit with pageAction: " + request.getParameter("pageAction"));
    		
    		HttpSession session = request.getSession();
    		Employee sessionEmployee = (Employee) session.getAttribute(
    				SessionAndSecurityInterceptor.SESSION_EMPLOYEE_ATTRIB_NAME);
    
    		Employee epe = (Employee) command;
    		String pageAction = request.getParameter("pageAction");
    		Mode pageMode = getPageMode(request);
    
    		if ("save".equals(pageAction)) {
    			...
    			ModelAndView modelAndView = new ModelAndView();
    			modelAndView.setViewName("redirect:/administratie/medewerker/medewerkerEdit.htm");
    			modelAndView.addObject("epeId", epe.getEpeId());
    			GisUtil.addMessage(request, "Medewerker is opgeslagen.");
    			return modelAndView;
    		} else if("remove".equals(pageAction)) {
    			...
    		} else if("deleteContract".equals(pageAction)) {
    			String startDate = request.getParameter("subId");
    			Date date = DateUtil.convertToDate(startDate);
    			log.debug("TODO: Remove contract with ECT_ID " + epe.getEpeId() + " and startdate " + startDate);
    			//GisUtil.addErrorMessage(request, "Removal of employeecontracts not yet implemented.");
    			
    		} else if (pageAction != null && !"".equals(pageAction)) {
    			// Onbekende actie
    			log.error("Onbekende actie gevraagd: " + pageAction);
    		}
    
    		ModelAndView modelAndView = showForm(request, response, errors);
    		return modelAndView;
    	}
    
    	@Override
    	protected Map referenceData(HttpServletRequest request) throws Exception {
    		Map map = new HashMap();
    		Employee epe = (Employee) getCommand(request);
    
    		// Companies
    		map.put("companies", companyStructureService.findCompanies());
    		map.put("columns", companyStructureService.findColumnsForCompany(epe.getCompanieByEpeCpyId() == null ? null : 
    			String.valueOf(epe.getCompanieByEpeCpyId().getCpyCode())));
    		map.put("divisions", companyStructureService.findDivisionsForColumn(epe.getDivision() == null ? null : 
    			epe.getDivision().getColumn().getClnId()));
    
    		...
    		
    		return map;
    	}
    
    	/**
    	 * Deze methode initialiseert het form backing object. Meestal wordt in deze
    	 * methode het form backing object geladen uit de database, of
    	 * geinitialiseerd met default waarden.
    	 */
    	@Override
    	protected Object formBackingObject(HttpServletRequest request)
    			throws Exception {
    
    		String idParam = request.getParameter("epeId");
    		Long epeId = idParam == null ? null : Long.valueOf(idParam);
    		Employee epe = epeId == null ? null : employeeService
    				.retrieveEmployee(epeId);
    
    		// Initialize contactperson
    		if (epe == null)
    			epe = new Employee();
    		
    		log.debug("formBackingObject returns [" + epe.getEpeId() + ", "
    				+ Formatter.formatEmployeeNameFirstMiddleLast(epe) + "]");
    		return epe;
    	}
    
    }

  • #2
    I suggest a readup on hibernate and how it works.

    If you don't use a redirect the SAME object is reused (you store it in the http session), however the hibernate session that was used to retrieve the object isn't there anymore. If you use a redirect this isn't an issue.

    Comment


    • #3
      Hi Marten,

      Thanks for the explanation. I see now that I'm a bit off-topic as well in the forum.

      I think I understood what was going on.
      Redirecting was also not satisfying, because the errors also showed up
      in case of binding errors.

      I fixed the issue now by adding the following to web.xml:

      Code:
      <filter>
      	  <filter-name>hibernateFilter</filter-name>
      	  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      	</filter>
       	<filter-mapping>
       		<filter-name>hibernateFilter</filter-name>
       		<url-pattern>/*</url-pattern>
       	</filter-mapping>
      This keeps an Hibernate session open during the lifetime of the HTTP request and is used by the property I used in my form which caused the problem.

      Kind regards,
      Jonne.

      Comment

      Working...
      X