by Steven J. Owens (unless otherwise attributed)
Doug writes:
>Well, one of the advantages of using Servlets/JSP/Beans, supposedly, is the
>separation of business/data logic from presentation. I guess you are
>finding one of the downsides.
>
>I think the subject of effective gui in a browser is pretty big and pretty
>distinct from server-side techniques, whether done in servlets or something
>else. I think you may have to concentrate on the gui area without
>consideration of the server-side, and then work out the links to the
>back-end (via JSP, etc.). A good book on JSP should give some hints, but I
>have none to recommend.
I haven't done much work with Javascript, but what I have done is far more than I ever wanted to do :-). It's a slippery slope - once you get your hands a little bit dirty with it, you become the resident expert, and of course that makes you the best candidate to work on it further...
My best advice on this topic is, don't do it. Javascript is a painful language, and it's incompatible. Incompatible with what? incompatible with itself; there is no version of Javascript that is fully compatible with any other version of javascript. Different versions numbers, different browser flavors, different platforms, change any variable and you can pretty much guarantee you're going to have to chase down compatibility issues, and if you're trying to do anything in the slightest bit tricky, you'll find yourself running into unresolvable contradictions.
Note: And yes, for the pedantics, there is theoretically a difference between javascript, the language, and the browser DOM that client-side javascript has to work with. A lot of the incompatibilities are between different DOMs. Claiming that these aren't relevant to javascript is stupid; what else are you going to code client-side DOM manipulations in?
All of this advice, of course, goes out the window if you can select a single browser and version and just support that. And when I say single, I mean exactly that. Not "IE 4.0 and later", not "IE 4.x", but just exactly "IE 4.0". Not that I'd choose 4.0 to support, it had the buggiest behavior when I was suffering through Javascript purgatory. But Javascript is still a painful language, and the "only support a limited number of browsers" approach is an extremely slippery slope - expect to find yourself burning a lot of time arguing with your business users about why it's not a good idea to expand support to include other browser versions and/or flavors.
My second-best advice is, if you have to do it, get PeachPit Press's Visual Quickstart Guide To Javascript as a cookbook for the various trivial bells & whistles you may need. Most of the common whizbang features of Javascript are covered there, with code to work around browser compatibility issues. If it's not in there, tell your client it probably can't be done, and it would be prohibitively expensive to find out for sure (because the only way to do it is to try to do it, and then test on seven different browsers, then try to do it again...). Get O'Reilly's javascript reference book to use when altering the PeachPit Press examples.
A couple of things some folks specifically asked for:
To insert a value into a javascript from a servlet, the easiest way is to just have the servlet generate the page with the javascript on it, inserting the string containing the value directly into the javascript statement before the javascript gets interpreted by the browser.
If you need to have a dynamically generated HREF in a static page, one half-assed workaround would be to have a static HREF that points to the servlet, which would in turn generate the dynamic URL and redirect the request to the URL. This is of limited usefulness in high-security settings, of course, because you have to use GET-style variable passing to the servlet. There's no way to redirect a POST-style form submission, trust me, I know, I spent a good chunk of a year looking for a way.
The reason it's impossible has to do with the MIME types used in HTTP interactions. Basically, browsers and servers talk to each other by passing MIME-encoded chunks of information back and forth. There are two MIME types, single-line and multi-line. I suppose in theory both types could be sent back and forth, but HTTP servers and clients (browsers) are almost universally coded to only use multi-line MIME types when going from the browser to the server.
In a redirect, the browser sends the server a request for a page, and the server responds with a code saying "That's not here, but you'll find it over there." A POST is a multi-line MIME type, a GET is a single-line MIME type. In order to redirect a POST, the server would need to receive the multi-line MIME and then send it (or something similar) back to the browser.
Somebody talked about using separate javascript source files. This is where you have a javascript tag something like (offhand, look it up to make sure the syntax is right):
<SCRIPT SRC="http:///www.blah.com/myscript.js">
One trick I haven't tested, but which should be possible in theory, would be to have http:///www.blah.com/myscript.js point to a servlet that generates and returns appropriate javascript for whatever your purposes are.
Another possiblity people have asked about is using separate frames and/or windows to finesse various situations where you want to post to a servlet, take the response and do something with the data. This is certainly feasible. However, it is not simple to implement, and it gets even hairier if you're trying to make it work on more than one flavor of browser. I burned up a lot of brain cells and more seconds of my life than I'd care to remember proving this :-(. The various browsers have extremely different DOMs (document object models), even from browser to browser. Make it work on one, it breaks on another.
It is damn near impossible to make the above approach secure; various browsers have unreliable behavior with respect to caching and respecting pragmas, and will helpfully offer to rePOST the information when you back up to the page. You can mimize its impact by coding checks on the server side, but there's no way to nail down the browser side. I found this extremely frustrating when dealing with IE particularly, especially 4.0. There is, in fact, no way to make IE 4.0 forget the contents of a POST. I did find a way to fake it, through clever use of multiple frames and forcing a reload of the page containing the original form, but it was truly a kludge and not something I recommend.
Oh yeah, another thing about IE, 4.0, is the SSL non-Versign CA POST bug. If you're dealing with SSL servers and you're using a non-Verisign Certificate Authority, IE 3.x doesn't give you any option to accept the certificate, though you can manually install your CA for use in intranets. However, with IE 4.0 the user can click through a couple of dialogs to accept the non-standard CA... whereupon IE 4.0 continues with the POST, having forgotten the actual arguments somewhere in the process!
This was extremely annoying and difficult to track down, particularly because it was taking place in an SSL session where I couldn't monitor what was actually going on. Speaking of which, I highly recommend that anybody doing servlet programming, and especially anybody doing tricky HTML or JavaScript programming to boot, should set up a simple proxy server between their browser and server, to monitor what's the browser and server are saying to each other. This is extremely instructive in general, and is incredibly helpful when troubleshooting. Now, if only somebody would write a server or browser add-on to let me troubleshoot the SSL sessions... :-).