|
From: Ken K. <kk...@kk...> - 2003-05-23 13:55:54
|
Juergen,
I've changed my code to remove the override of handleInvalidSubmit and
it works well. I like the way this implemented now as it does make it
intuitive and easy for developers. This is exactly how it should be: the
framework takes care of the sticky but common Back button problem
without the developer having to do extra work while providing the
capability to explicitly forbid the duplicate submissions fairly easily.
Thanks,
Ken
jürgen höller [werk3AT] wrote:
>Ken,
>
>You're right about the back-and-resubmit-valid-form case. I've changed the default implementation of handleInvalidSubmit to fetch a new backing object and resubmit, instead of showing a new form. So you don't need to override handleInvalidSubmit in your case to get the desired behavior.
>
>Note that duplicate submissions are now possible with the default behavior. If you want to forbid them, you need to explicitly override handleInvalidSubmit and either show a "invalid submit" message or redirect to a new form. Only then will the form object in the session serve as transaction token.
>
>I hope this is now as intuitive as possible (it's also documented in JavaDoc). What do you think?
>
>BTW, I'm gonna check the change in this afternoon, together with some polishing, and full tests for ControllerServlet and co.
>
>Regards,
>Juergen
>
>
>-----Original Message-----
>From: Ken Krebs [mailto:kk...@kk...]
>Sent: Thursday, May 22, 2003 12:00 AM
>To: jürgen höller [werk3AT]
>Cc: spring-dev-list
>Subject: [Springframework-developer] MVC Forms
>
>
>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
>>
>>
>>
>>
>>
>>
>
>
>
>
>-------------------------------------------------------
>This SF.net email is sponsored by: ObjectStore.
>If flattening out C++ or Java code to make your application fit in a
>relational database is painful, don't do it! Check out ObjectStore.
>Now part of Progress Software. http://www.objectstore.net/sourceforge
>_______________________________________________
>Springframework-developer mailing list
>Spr...@li...
>https://lists.sourceforge.net/lists/listinfo/springframework-developer
>
>
>
>
|