John Topley's Weblog
December 2003 Article ArchiveBack Button BluesSaturday, 20 December 2003“You should never go back” they said, and they were right. They probably weren't thinking about the problems of web application development when they said it though. I've been struggling with the issue of handling the browser Back button correctly in a Struts application that I'm working on. The user is presented with a series of pages that make up a workflow process. I'm using an ActionForm with HTTP session scope because this is ideal for building wizard-style page flows, as the HTML form retains its values across multiple pages. The problem comes if the user doesn't enter a value for one of the fields. Using the Struts validation features I can raise an ActionError that prompts the user to enter a value for that field. If the user then submits to the next page but then clicks the Back button, the error message is still there, only this time the field still has the valid value that was just entered! In other words, the application is now in a logically inconsistent state. I've tried everything I can think of to solve this problem. The error message appears because the browser is returning a cached version of the page. I can turn off caching but then when the Back button is clicked the user gets that nasty IE page about the page being expired and needing to be refreshed. So they click the Refresh button and then they get a message dialogue that says that the page contains a form which requires that they click the Retry button to re-submit it. This returns them to the form and the errors are gone, only the values they entered are too. Hardly a slick user experience. The Struts mailing list is full of messages from developers having similar problems, but I've not been able to find a definitive solution. Some misguided souls even ask if it's possible to disable the browser's Back button to avoid the problem entirely. Hint: people use web browsers all the time and are used to being able to go back—don't break their expectations of how the application is going to behave by attempting to cripple their browser. Sites such as Amazon let users jump to any point within the payment workflow as they please and everything is as you expect it to be, but then again, they use their own custom CGI solution. Are there any Struts meisters reading this who have the answer? All of these problems stem from the fact that we're now using the stateless HTTP protocol for trying to deliver stateful applications. The technology behind the Web was designed to deliver static content. The browser-based application has been heralded as the solution to the problem of having to roll out traditional monolithic desktop applications to a large number of users within an organisation, and indeed it does solve this problem. It's also a great way to turn that shiny new 3 GHz computer on your desk into a dumb terminal. Is offering an impoverished user experience by virtue of using this technology for something it was never designed for, really the best we can come up with? Java Default ConstructorsFriday, 05 December 2003There seems to be a lot of confusion amongst Java programmers as to what consitutes a default constructor, a no-argument constructor and what the difference is between them. For example, I keep coming across Java code similar to this: public class OmniCognateNeutronWrangler —The Javadoc for this class is incorrect. The source code for the class contains a no-argument constructor, not a default constructor. The default constructor is the constructor that is generated automatically for you behind the scenes by the Java compiler if you create a class that has no constructors. It's possible to see this in action. Write a class that has no constructors and compile it: /** Next, use the javap command-line tool that comes with the JDK to decompile the compiled .class file using the -c switch, as shown below:
I've used the type command to show the contents of the source file to prove that there's no trickery going on. If you think I've doctored the screen shot then do try this at home kids. The decompiler lists the Java source code for the class and notice that the compiler has silently inserted a default constructor. The -c switch makes the decompiler list the corresponding JVM bytecodes. The line we're interested in is the invokespecial #1 call to the constructor in java.lang.Object: in other words, a default constructor has been generated for us and all it does is invoke the superclass constructor. |
![]() |



