Sunday, January 01, 2006

Struts re-submits form posts? Am I missing something?

I just finished my first bona fide Struts application, and I'm a bit perplexed. I find an inherent problem with the design, and I'm trying to figure out if I missed something.

The problem is that the framework doesn't protect against form re-submission. The Struts framework seems to use a forward instead of a redirect after a form is successfully submitted and validated. If you do this and hit the refresh button on your browser, you'll see the problem. The form re-submits. This is a basic web development problem, and the ramifications are severe. If a form is resubmitted, a user can add as many records to a database as they hit the refresh button, make numerous purchases of the identical set of products, add the exact product to a shopping cart numerous times, etc. I'm surprised that this problem exists in such a widely used framework!

This problem is an obvious one, and I'm SURE that someone else has figured out an elegant solution to it. So I'm not about to give up on the framework altogether. However, I'm beginning to be skeptical of it. And I'm not the only one.

In my opinion, the solution involves a different workflow. Struts uses a Post -> Forward workflow. For successful form submissions, a Post -> Redirect -> Get (PRG) workflow is much better. Struts does provide support for tokens to see if a form is submitted more than once, but in my opinion, tokens aren't the way to solve the problem. Not only does it leave the server open to tampering, it also poses usability problems for the user.

Now, I don't claim to be any sort of expert in Struts matters. I just know that forwarding and allowing a form to be resubmitted is dead wrong, even if tokens can help check to see of a form is being resubmitted. In my simple understanding of Struts and ActionForwards, I do have an idea for a solution. Seeing an ActionMapping in the struts-config.xml, where there's a form, there's a <forward>. When the form is successfully validated without any errors, the ActionServlet should send the HttpResponse.redirect() instead of the HttpResponse.forward(), which I am assuming is what happens.

So, first, I think I'll look a little deeper into what other people have done to solve this problem,. If I can't find anything that seems to work, I'm going to subclass the ActionServlet as PRGActionServlet, and make it redirect to an ActionForward instead of forward. And MAYBE I'll add support for a different XML element called <redirect>. I don't know, but I'll report back with what I decide to do.

1 comment:

Anonymous said...

Hi!
Did you solved this problem with forward/redirect? I have the same
Maxim