|
From: Ken K. <kk...@kk...> - 2003-05-21 22:05:52
|
Hi Juergen,
Thanks for your changes, but there is something I still have a question
about.
NOTE: In the following, I have removed my IsFormSubmission override and
set bindOnNewForm=true.
Consider the scenario in petclinic where a user submits some changes to
an owner's info. The owner page is then displayed with the changes and
the user notices that a change was forgotten. The user then uses the
Back button to go back to the "change owner info" page, makes another
change, and sumits the form. I expected that the change will be
validated and submitted and the owner page with the new info would then
be displayed. What happens is that
AbstractFormController.handleRequestInternal calls handleInvalidSubmit
as expected when it can't find the formObject but it then returns
without processing the validate/submit logic. The user must then submit
the new change a second time to actually get it submitted.
To make it work the way I intended, I must override handleInvalidSubmit
and in it call showNewForm to rebind the data to the formObject, ignore
it's returned ModelandView, and then process a duplicate of
AbstractFormController's validate/submit logic. The complete code is
shown below.
Is this the way you intended it to work and if so, why ?
Best Regards,
Ken
/*
* OwnerInfoForm.java
*
* Created on May 9, 2003, 9:53 AM
*/
package petclinic.web;
import petclinic.Clinic;
import petclinic.Owner;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import com.interface21.validation.BindException;
import com.interface21.web.servlet.ModelAndView;
import com.interface21.web.servlet.mvc.SimpleFormController;
import com.interface21.web.bind.ServletRequestDataBinder;
import com.interface21.context.ApplicationContextException;
/**
*
* @author Ken Krebs
*/
public class OwnerInfoForm extends SimpleFormController {
/** Holds value of property clinic. */
private Clinic clinic;
/** Creates a new instance of OwnerInfoForm */
public OwnerInfoForm() {
}
/** Setter for property clinic.
* @param clinic New value of property plinic.
*/
public void setClinic(Clinic clinic) {
this.clinic = clinic;
}
protected void init() throws ApplicationContextException {
if(clinic == null)
throw new ApplicationContextException("Must set clinic bean
property on " + getClass());
}
protected ModelAndView onSubmit(Object command) throws
ServletException {
Owner owner = (Owner) command;
// add stuff to test if adding new or updating existing owner
clinic.update(owner);
return new ModelAndView(getSuccessView(), "owner", owner);
}
protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
int ownerId = 0;
try {
ownerId = Integer.parseInt(request.getParameter("ownerId"));
} catch(NumberFormatException e) {/*OK to trap & ignore*/}
Owner owner = clinic.getOwner(ownerId);
return (owner != null) ? owner : new Owner();
}
protected ModelAndView handleInvalidSubmit(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException {
showNewForm(request, response);
// process submit
Object command = userObject(request);
ServletRequestDataBinder errors = bindAndValidate(request, command);
return processSubmit(request, response, command, errors);
}
}
jürgen höller [werk3AT] wrote:
>Ken,
>
>I've further refined invalid submission handling. An invalid submit request in session form mode (i.e. when no form object is in the session) triggers AbstractFormController's handleInvalidSubmit method. The latter's default implementation simply shows a new form, binding the submitted values to the new form in case of "bindOnNewForm=true". But handleInvalidSubmit can be overridden now, to show an "invalid resubmit" error message or redirect to some other view.
>
>Regarding transaction tokens: In session mode, form objects can serve as transaction tokens. If a user presses the browser's reload button, he either sees a new form or some custom error message (as determined by the handleInvalidSubmit implementation). Thus, if you need to forbid duplicate submissions for a certain form, switch its controller into session form mode in any case (even if you wouldn't need to keep the form object in the session otherwise).
>
>Thus, we don't really need dedicated transaction token support - just leverage AbstractFormController's invalid submission handling in session form mode. A dedicated token attribute in the session would only be necessary if there isn't any form object involved. Do you see a use case for forbidding duplicate submissions without a form?
>
>Struts has programmatic token support: You can manually add it to a session/request in an Action implementation when showing the form, and manually check its validity on submit. The html:form tag automatically adds a respective hidden field. I don't see actual value in this, though, beyond what proper session form handling already provides. BTW, transaction tokens aren't even mentioned in the Struts User Guide.
>
>Regards,
>Juergen
>
>
>-----Original Message-----
>From: Ken Krebs [mailto:kk...@kk...]
>Sent: Tuesday, May 20, 2003 7:21 PM
>To: jürgen höller [werk3AT]
>Cc: 'spring-dev-list'
>Subject: Re: [Springframework-developer] MVC Forms
>
>
>Juergen,
>
>I haven't had a chance to look at them but your changes for the Back
>button problems, including some way of forbidding duplicate submission
>(hopefully possible through configuration of the form bean), sound like
>they will help provide what's needed and are a real plus for developers.
>I will try to point this out in the accompanying tutorial text.
>
>As for AbstractFormController and SimpleFormController seeming
>restrictive, this was probably just a perception I got as I tried to
>solve the Back button issue. My own AbstractSearchFormController
>subclass of SimpleFormController shows that it is not restrictive on
>submission. I was concerned about how to handle things going wrong prior
>to submission (see next paragraph).
>
>There is another class of MVC problem not necessarily just with forms,
>and that is when the user directly enters a mapped url to a Controller,
>and the Controller expects to see parameters that aren't there. An
>example of my own handling of this in petclinic is in the method
>ClinicController.ownerHandler. In this case, it's makes sense to just
>redirect the user to the FindOwnerForm as I've done. I was planning on
>handling this situation for the OwnerInfoForm by making the form
>dynamically show a "Update Owner Info" button if the preconfigured
>object can be provided or a "Add Owner" button if there is no
>preconfigured object, but redirection may be desirable in some
>situations. What do you think ?
>
> From the viewpoint of an organization considering adopting Spring, the
>fact that Spring addresses these problems directly without individual
>developers having to craft their own adhoc solutions should be seen as a
>plus.
>
>Ken
>
>
>
>
|