Archive for the ‘web’ Category
IE, Memory Management, and You
In a recent blog, commenters took me to task for a perceived IE 6 memory leak. It wasn’t actually there (they were wrong), but in attempting to prove myself right, I found a couple of memory leaks under IE in JSF’s Ajax support. Since I just spent a week learning how all this functioned, I thought I’d set it down so that others could learn from my efforts.
Now, none of the information that I’ll present here is new – it’s been discussed among Ajax programmers for at least the last 4 years. If you’re a web guru, it’s likely that you’re not going to learn anything new here (thought I’d welcome any additional information and corrections). But at least a couple of the points I’ll illustrate below are either poorly communicated or misunderstood. I’ll include a number of links at the end of this article. There are also very significant differences between IE 8 (which mostly works), IE 7 (which is bad), and IE 6 (which is just awful). I’ll try to point out the differences as they matter for each.
Tools
First – use the right tool for the job: In order to spot leaks, you’ll need to download a tool that can detect them. By all accounts, sIEve is the way to go. It uses IE itself, and introspects to get it’s data. The UI is pretty primitive, but I can’t recommend it enough – it’s truely invaluable. Since it uses IE for it’s work, you’ll need to run it on a machine that has IE6 installed – presumably in a VM. You’ll also want to have it running on a machine that has IE 7 and IE 8 as well, just to be sure. XP fits nicely on a VM that runs on my Mac, and this is how I use it.
Cyclic Leak
Now that that’s out of the way, it’s time to talk about the very worst of the memory leaks in IE – the dreaded cyclic reference, which the commenters thought that I’d committed. Under certain conditions, IE 6 will “leak” DOM nodes, retaining them, and the javascript objects that point to them, until the browser is either shut down, or crashes entirely due to lack of memory. Ugh! To understand how this happens, you really only need to know two things:
- IE 6 (and 7!) reportedly has very primitive garbage collection using reference counting
- There are two memory spaces in IE, one for JavaScript, and the other for the DOM, and they don’t communicate well.
What could go wrong? Well, lots. The commenters thought that the rule was: A leak will occur if any reference is made in JavaScript to an element that isn’t eventually set to null. That’s close, but not quite correct. The real rule is: A leak will occur if the JavaScript code contains any reference to the DOM that isn’t released in some way, either by going out of scope or being explicitly unset.
When IE 6 sees a JavaScript variable that is pointing to something in the DOM (typically, an element or node), it will record that reference, and not collect it – even when you surf over to a new page. And the DOM won’t be collected, since there’s a reference to it from JavaScript. These two objects, and all the stuff that references them, will stick around until shutdown. In IE 7, the geniuses at Microsoft saw the bug, and said “Hey, I know how to fix that, let’s garbage collect everything when we leave the page.”. Nice improvement, but it still doesn’t fix the bug, since if you’re developing a page that is designed to be used for a long period of time (like many page-as-application apps are now), it’ll still crash the browser. Apparently, they saw the error of their ways eventually, since this behavior is no longer present in IE8. (All this is confirmed by my testing with sIEve.)
So, in the example that had in my previous blog, there was no memory leak, because the variable that pointed to the element eventually went out of scope. So – how to you create variables that don’t go out of scope? The easiest way is to put them in an object – this was the leak that I eventually found in JSF. The fix there was to null out the object manually. But there’s another, more insidious way to create an object – create a closure. That creates a function object implicitly under the window object, and that will never go out of scope. But the key thing to remember is that you need to be aware of when things go out of scope when coding in IE, and act accordingly.
But wait! There’s more
If that was the only problem, life would have been fairly easy for me the last week. But that’s not the only bug that the Web Wizards of Redmond chose to deliver to their unsuspecting consumers. There’s another bug in IE (again, only in IE 6 and 7 – IE 8 appears to have fixed it per my testing), which also leaks DOM nodes that aren’t cleaned up until you leave the page. Apparently, when the IE DOM receives a call from the removeChild or replaceChild functions, it doesn’t actually, err, remove the nodes. It just leaves them there, hanging around the DOM like party guests that don’t have the sense to leave after the host has started handing out coats. While these nodes will eventually be cleaned up when the user leaves the page, this still causes problems for page-as-app programs, as in the cyclic leak for IE 7, above. While the removeChild call is fairly notorious for this, I had to find out about replaceChild with my own testing (though I did find a few obscure references once I went looking for it).
That means that instead of saying node.parentNode.replaceChild(newNode, node), you instead should say something like: node.parentNode.insertBefore(newNode, node); deleteNode(node); (with an appropriate if statement for isIE(), and a deleteNode function that doesn’t use removeChild). And instead of saying node.parentNode.removeChild(node); you instead are reduced to coding something like: node.outerHTML = ”; (again, with browser check). Except that when you combine that with IE’s horrible problems with manipulating tables, it may fail. So instead, you’re probably better off with something like this:
var temp = document.createElement('div');
try {
temp.appendChild(node.parentNode.removeChild(node));
temp.innerHTML = ""; // Prevent leak in IE
} catch (e) {
// at least we tried
}
deleteNode(temp);
Again, possibly with an isIE() check.
Hopefully you found this description of IE’s Memory “Management” useful. Here’s a few of the links that I used for research, that I found the most helpful.
- sIEve – the tool you should already have.
- Quirks blog link roundup of memory leak info.
- Microsoft MSDN article on the topic. Useful, even if it insultingly implies that it’s your fault the browser is leaking.
As always, I look forward to any comments. Especially about this topic – I’m far from expert in this area.
UPDATE: John Resig just posted about a very interesting looking tool. Haven’t checked it out yet, but if it’s got him excited…
(This article originally published on my java.net blog on November 13, 2009.)
An (almost) comprehensive list of Web Components
In talking with Andy Schwartz before our recent talk together at Oracle Open World, Andy mentioned that he’d like to see some new components make it in to JSF 2.1.
I’d like to see that too – but what new components? To aid the discussion, I thought it might be handy to make up a list of components that I think would be handy for JSF – but please, don’t take this as an endorsement of any particular component for inclusion into the spec. At best, I can see us adding only a handful, perhaps 3 or so. Still, once started, this kind of project becomes it’s own end – so I decided it might be good to publish such a list. Many of these components already exist in some form or another for JSF, or as a JavaScript Widget that could be wrapped in a JSF component – so most of them are available today.
Basic Html
Most of the basic HTML components are already well covered, but there would seem to be a little room for a few very basic components
- File Upload
- Formatted i18n data
- Date entry/display
- Time entry/display
- Currency entry/display
- Flat Tree
- Static Progress Status
- SingleRowSelect
- HTML5
This is pretty basic – and Servlet 3.0 just added it.
These can currently be done with converters and validators, but is there a better way?
A very basic hierarchical data visualization component that has no JavaScript required.
A bar which indicates percent complete, a static version of the Ajax version below
A radio button that works with a table.
There’s new stuff coming up – should we start to care? IE is, as usual, the lone holdout.
Navigation
Components for navigating from one page to another.
- Breadcrumb Trail
- Navigation List
- Navigation Tree
Almost standard on many sites now, a horizontal list, often limited to three deep, that allows you to backtrack through your history without the back button.
A fairly straightforward list of links that navigate to different pages in the site. Often put in a Navbar on the left of the page.
Like a Navigation List, but with hierarchical categories
Security
Components that deal with identity and authorization.
- Java EE Login
- Logout
- Register
- Forgotten Password/Username
- Capcha
This one would seem to be a no brainer, but it’s actually a bit hard to get right.
If you log in, you should be able to log out.
Probably not possible in a fully reusable way, since Java EE doesn’t specify a standard registration API.
Same problem as Register
This would be very useful, but probably not amenable to standardization, since the robots keep getting smarter.
Simple Rich UI
- Framebuster
- Tabbed Pane
- Spinner
- Slider
- Calendar
- TimeSpinner
- ColorPicker
- ModalWindow
- ModalDialog
- Popup Menu
- FloatingWindow
- Tag Cloud
- TabularData
- Menubar
- CommandBar (icon button)
The war between the framers and the framebusters means that this will be obsolete almost immedately on release, but it might be worthwhile to try.
Basic Web component or rich component, depending on whether you use DHTML. Since DHTML is probably easier for the end user, it’s my preference to have it in this list.
Increment an integer value by a set amount at the press of a button, or manually enter a number. Implemented as a demo in Mojarra 2.0.
Analog slider to choose a numeric value, or manually enter a value.
Need to also include options to pick a date, or only a month, or even only pick a year. May be hard to do reusably, since styling matters so much. Wrapped a YUI Calendar widget as a component as a demo in Mojarra 2.0.
A special case of a spinner, for picking a time.
A very special case, but easy to implement.
Alert box.
Alert box, with two or more buttons.
A detached embedded window, that you can move around within the HTML frame or window that contains it. After a brief burst of popularity, I’ve seen usage drop off.
I’m frankly not convinced of the usefulness of this particular visualization, but many designers seem to love it.
A table that’s modeled on a database set, rather than being explicitly bound to the HTML table. Would include sorting, at a minimum, and also probably reorder of rows. Maybe even filtering?
Drop down menu bar. Many HI people hate them on the web.
Essentially, a horizontal strip of buttons.
Filthy Rich UI
Really elaborate graphical components. Harder to do as a standard, since styling becomes so important.
- Carosel
- Accordian
- EditText (in place edit)
- Shuttle (Switch List)
- ComboBox
- Collapsible Tree
- RichTextEdit
- RSSReader
- Slideshow
- Lightbox
- Charting
Like Apple’s cover flow, flip through a set of images to select one.
Just because I’ve never seen it implemented well doesn’t mean it’s useless.
Easy to do, but hard to get right, I’ve implemented it as a demo in Mojarra 2.0.
Fairly common, I’ve implemented it as a demo in Mojarra 2.0.
Essentially a static version of the AutoSuggest component, below.
Tomahawk has had a tree for years.
Several good JavaScript widgets exist for this functionality.
Update a page automaticially with the latest blog posts. Far more useful than you might first think, since many programs (like hudson, for instance) now export data as RSS.
A fairly complex JavaScript widget.
An incredibly complex JavaScript widget for organizing images.
Incredibly complex, and incredibly useful, this is probably best done as a completely separate software product. Some JavaScript widgets already exist, and some JSF components already support this…
Behaviors
Things that are probably best implemented as behaviors.
- Tooltip
- DragAndDrop
- Clientside Validation
Probably almost trival to implement.
The opposite of trivial to implement, it could still be incredibly useful. Some support in various JSF component sets already.
A customer request since year 2000.
Ajax
- AutoSuggest
- Poll
- Map
- Progress Indicator
- Busy Status Indicator
The “shopping cart” of the Ajax world. Note that Andy is working on a demo that implements this as a behavior. Supported as a component in some JSF component sets.
Besides periodic updates, also handy for keeping sessions alive, and avoiding many cases of view expiration. Less necessary if we implement Comet, but probably still useful as simpler solution.
Relying on an external service means that this is probably not suitable for standardization.
Progress of a server operation
Essentially a binary version of Progress Status
More?
I’m sure I’ve left some out – suggest more in the comments…
(This article originally published on my java.net blog on October 14, 2009.)
Eval JavaScript in a global context
Even though it’s considered bad practice, it’s often handy to eval code in JavaScript. And in my case, it was simply necessary, since the JSF specification requires eval of scripts. And it’s also necessary to execute those evaluated scripts in the global scope. It’s not as easy as it first looks.
For our first naive implementation, we’d simply used eval(src) in our first pass at the implementation.
This is utterly wrong, and to understand why, you’ll need to understand scopes. JavaScript has what you can think of as two different scopes – function scope, where you’re executing something in the context of a function, and global scope, where you’re executing something in a global context – for instance, if I say var j = 1; within a function’s scope, then the variable j is set to 1 within that function. If I say the same expression, var j = 1 within the global scope, then j is set to 1 everywhere in the program – in every function, provided that that function doesn’t define a j variable in its local scope. In browsers, the global context is window – this is the default object that everything gets hung off of if you don’t specify any other object.
So, when we said eval(src), we were executing the src scripts within the local scope of the function where eval was called – that meant that I would be getting different results when variables were declared and set than would be expected – in fact, for some cases, it just seemed like the scripts weren’t being executed at all.
So, what to do? Well, as is usual for the browser JavaScript, there’s Internet Explorer, then there’s everyone else. As is usual, IE, the crazy cousin Larry of the browser world, has a convenient, well intentioned, and utterly nonstandard way to do this: window.execScript(src) It works great – and the other ways I’ll detail here break rather infamously, so use this non-standard function on IE.
For more standards-respecting browsers, the way to do this should be to use the call function, which is a standard function attached to every Function object. So, eval.call(window, src) should work. But to understand why, it’s important to know about context, in addition to scope. Every function call has it’s own context: this is the object that’s represented by the special value this. When we use the call function, the first parameter is the context object we’ll use for this. This is handy for all kinds of purposes, but for us, it’s just nice to use to set the context to the window object – which, you’ll recall, is the global.
Sadly, eval.call(window,src) breaks on Chrome – it complains about contexts not matching. Odd – and I was unable to Google up why this might be so. But a couple lucky guesses later, and I discovered that window.eval.call(window,src) works on all non-IE browsers. Now, when I say “var j = 1″, the window[j] is the variable that’s set… So, that’s good. Why do we have to add the extra window. on Chrome? Not sure – I could guess, but it’s too likely to be wrong.
At this point, I thought we’d licked the problem. No such luck. Sure, global variables are getting set, but it turns out that if you say: alert(this) – then you would correctly receive the global object back on Chrome and Safari, but not Firefox – there, you’d get back the object that was the enclosing object before the call function got called. Very odd, and likely a bug in their implementation.
With a little help from Werner Punz, we figured out that they best way to get around this issue is to wrap the calling function in an anonymous globally scoped function. Like the Chrome bug, I can guess why this might work, but it would only be a guess. Better not to clutter up the internets with more guesses – I’ll just stick to what I know works.
Here’s the code that I now use to do a global eval:
var globalEval = function globalEval(src) {
if (window.execScript) {
window.execScript(src);
return;
}
var fn = function() {
window.eval.call(window,src);
};
fn();
};
Hope this list of tricks is helpful to someone else who’s looking to do something similar.
(This article originally published on my java.net blog on September 8, 2009.)
A simple Ajax JSF 2.0 example
In my previous blog post, I talked about the New Composite Component feature of JSF. I’ll come back to that shortly, but I’d like to talk about another new feature: integrated Ajax support. While this part of the specification is still being finalized, I thought it might be worthwhile to see what a simple example of the Ajax support in JSF 2.0 will look like. (Don’t worry, I’ll tie this together with Composite Components in a future posting.
Now, before I start, please keep in mind that the final version of JSF 2.0 will make this even easier, with a declarative (tag based) way to call out to Ajax in JSF. But for now, we’ll have to be content with the Javascript centric approach described below. Also, to use this example, you’ll have to use Glassfish v3 prelude, updated to build 5 of the JSF 2.0 EDR2 release via the updatetool – just released a couple hours ago. And if that doesn’t say “this is Alpha level code”, I don’t know what does.
A fairly common “hello world” type ajax example is a counter – so let’s build an app that counts upward. We’ll need a simple bean to store the count, as well as increment it and reset it:
import javax.faces.event.ActionEvent;
import javax.faces.model.ManagedBean;
import javax.faces.model.SessionScoped;
@ManagedBean(name = "count")
@SessionScoped
public class Count {
Integer count = 0;
public Integer getCount() {
return count++;
}
public void reset(ActionEvent ae) {
count = 0;
}
}
Note that unlike JSF 1.2, you can set up your managed bean without using the facesconfig.xml file – instead, you can just use annotations.
Now, we’ll look at the facelets file that we’ll be using, and then we’ll go through line by line. Here’s the facelets file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>Ajax</title>
</h:head>
<h:body>
<h:form id="form1" prependId="false">
<h:outputScript name="jsf.js" library="javax.faces" target="head"/>
<h:outputText id="out1" value="#{count.count}"/>
<br/>
<!-- Increment the counter on the server, and the client -->
<h:commandButton id="button1" value="Count"
onclick="jsf.ajax.request(this, event, {execute: this.id, render: 'out1'}); return false;"/>
<br/>
<!-- Resets the counter -->
<h:commandButton id="reset" value="reset"
onclick="jsf.ajax.request(this, event, {execute:'reset', render: 'out1'}); return false;"
actionListener="#{count.reset}"/>
</h:form>
</h:body>
</html>
This form paints three widgets: An outputText, and two commandButtons.
outputText “out1″ has the contents of the count value. “button1″, when pressed updates (and hence increments) the “out1″ field and only that field” – there’s no full page reload. Similarly, “reset” resets the counter value, and updates the “out1″ field, and only that field. Useful? Not really, unless you were to put a bunch of other things on the page, and didn’t want to refresh the entire page.
The h:outputScript tag says that we should include the JSF ajax library into our page. This is necessary for the call to jsf.ajax.request that we later make.
Note that even though the “out1″ output text is the target of our ajax, it doesn’t contain any unusual markup.
Then, we have “button1″ – it’s onclick method does two things – call jsf.ajax.request, and return false. The false return, for those not versed in JavaScript, means that it doesn’t actually call submit on the enclosing form.
The jsf.ajax.request call, on the other hand, takes three parameters. The first is the calling object, this. The second is the calling event, event. You’ll typically just use these values, so don’t worry too much about them.
The last parameter is a JavaScript object with two properties – an execute property, which takes list of the ids of all the JSF components that we would like to execute – since we’re executing this button, we’ll include it in the list as ‘this.id’. The second property is all the JSF components that we want to render – in this case, that’s just ‘out1′. That tells JSF to update the displayed value of the outputText component, above.
Lastly, we have ‘reset’ – it’s onclick is pretty much identical, but there’s an additional attribute, “actionListener”. Since we’re already executing ‘reset’, that means that JSF will call that method as part of the button push.
Hopefully this example was pretty clear – and fairly simple. Any questions? Ask below. (I’ll be doing more complex examples as the month progresses.)
Update: I’ve updated this example to be more clear, and to conform with the latest JSF 2.0 PR release.
(This article was originally published on my java.net blog on November 5, 2008.)
Writing a simple Composite Component with JSF 2.0
One of the pain points for JSF has always been the complexity that you face in creating components. In JSF 2.0, creating a new component that’s made up of existing components is a snap.
Here’s a quick example of how you can create a new component, and use it in your page.
For this example, I wanted to create a simple text box that has a yellow background. Useful? No. Simple? Yes
In fact, it only needs two files. (This may look like a bit of code for a blog entry, but bear with me – most of it is just xhtml fluff. There’s only about 4 or 5 lines that you’ll actually need to learn.)
The first file is the page itself. Since JSF 2.0 uses Facelets as the preferred way to create pages, we’ll use that. Here’s the page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ez="http://java.sun.com/jsf/composite/simpleout">
<h:head>
<title>Yellow Text Example</title>
</h:head>
<h:body>
<h1>Output Text Example</h1>
<h:form id="form1">
<ez:out value="Test Value"/>
<p><h:commandButton value="reload"/></p>
<h:messages/>
</h:form>
</h:body>
</html>
Two lines you need to care about here:
xmlns:ez="http://java.sun.com/jsf/composite/simpleout"
defines the composite component library, and
<ez:out value="Test Value"/>
then uses the composite component. But where is the “simpleout” component library? It’s in the directory WEB-INF/resources/simpleout, and the “out” component is defined in a file named out.xhtml in that directory. Here’s the contents of that file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">
<head>
<title>This will not be present in rendered output</title>
</head>
<body>
<composite:interface>
<composite:attribute name="value" required="false"/>
</composite:interface>
<composite:implementation>
<h:outputText value="#{cc.attrs.value}" style="background-color: yellow"/>
</composite:implementation>
</body>
</html>
Again, there’s really two bits to look at here. The first is
<composite:attribute name="value" required="false"/>
says that our out component can take one attribute, named “value”, and that it’s presence is optional. Then,
<h:outputText value="#{cc.attrs.value}" style="background-color: yellow"/>
is where we actually define the component, with the “value” attribute set to the value attribute that’s been passed in.
And that’s it. No Java code is required for this very simple example.
I’ll do other blogs about how to create more complex composite components, but I hope that I’ve made my point about how very simple this new way of component creation can be.
As always, if you have any questions, feel free to ask. And remember that you can try out this example by downloading GlassFish, and updating to JSF EDR2.
Update: I’ve updated this example to be more clear, and to conform with the latest JSF 2.0 PR release.
(This article was originally published on my java.net blog on November 1, 2008.)
Comet TicTacToe
Here’s the Comet TicTacToe that I went over in my BOF on Comet on Wednesday night. It’s pretty simple (though not as simple as my first example, or even the somewhat improved version) – just 200 lines of Java code (including the game logic), 50 lines of JavaScript (embedded in an HTML page), 50 lines of HTML, and a 75 line CSS file. Simple stuff, but if you’re looking to write your own Comet app, this might help get you started.
You can find the full Netbeans project here.
Essentially, the program logic is contained in only two files: ttt1.html, and CometServlet.java. Check ‘em out. After my initial example two posts ago, these should be pretty self explanatory. If you have any questions, by all means ask in the comments below.
(This article was originally published on my java.net blog on May 8, 2008.)
Solving the Comet timeout problem
In my previous blog, I mentioned that I didn’t like the hack of reloading the iframe via the post action – it’s hacky, and it’s not hard to imagine it messing things up in a more complex program.
Turns out the answer is both easy and blindingly obvious once you think of it: the iframe onload event. And while we’re add it, we’ll add a onerror event too.
In my previous program, I had had a hidden iframe, and on every update, I would reset the source for the iframe using the location property.
We’ll still do that, but add a new function:
<iframe name="hidden" src="CometCount" frameborder="0" height="0" width="100%"
onload="restartPoll()" onerror="restartPoll()" ></iframe>
Note the onload and onerror events – whenever the server closes the connection, these will be called. And here’s the function that’s called:
var retries = 0;
function restartPoll() {
if (retries++ > 10) {
alert("The connection has errored out too many times");
} else {
hidden.location = url;
}
}
Also, I’ve added a retry limit in there – it wouldn’t do to have the client go into a fatal spin just because the server is down.
Now when the server closes the connection (from a timeout, or an error), the client will continue to function, automatically calling back into the server. Not a solution you’ll want for every situation, but useful enough, especially for our small example.
Lastly, there was a bug in my previous version under IE – sorry about that. It turns out that if you send a POST via IE, you need to have a content body, or IE gets fussy. The fix is to change the line
xhReq.send(null);
to
xhReq.send("null");
I’ve uploaded new versions of the files index.html and CometCount.java, so you can see the complete code in context.
(This article was originally published on my java.net blog on May 5, 2008.)
Dead Simple Comet Example on Glassfish v3 / Grizzly
I was looking at a recent blog by Shing Wai Chan and going through the Comet example, when I noticed that the example wasn’t working correctly. Although he updated his example to get around that problem, I was still a bit unsatisfied, and decided to sit down, using his basic example, and see if I could make it even simpler.
I’ve whittled it down to about 100 lines, and only 2 files, and I thought I’d go over it here. The full example (both files) are
index.html and CometCount.java. So this will be a little long, but if you’re tired of reading my rambling, just look at the files, and the code should speak for itself.
First, about the app: It’s a simple counter, which is updated every time you hit a button on the page. Pretty basic, except – every other web browser viewing that page will have the counter updated as well, through the magic of Comet.
About setting it up: make sure that the url mapping points to /CometCount, the value is hardcoded in a few places. Also, to compile you’ll need access to the Grizzly Comet APIs – you can either get them from Grizzly, or Glassfish v3 tp2. You’ll need to also add the jar in the modules directory named grizzly-optionals to your classpath in order to build, along with the standard Servlet API. You’ll also need to update the domain.xml of the v3 instance to add the property cometSupport=true, as you see below:
Now on to the description of the program flow. On startup, the servet is initialized, and registers itself with with the Comet Engine (make sure the servlet is installed with a url CometCount, or it won’t work). We set a timeout of 2 minutes.
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletContext context = config.getServletContext();
contextPath = context.getContextPath() + "/MyComet";
CometEngine engine = CometEngine.getEngine();
CometContext cometContext = engine.register(contextPath);
cometContext.setExpirationDelay(120 * 1000);
}
Then on the first load of index.html in the browser, the hidden iframe makes a call to the doGet of the servlet – this call suspends, awaiting further action. It does this by attaching the response to a handler (of type CounterHandler), and attaching the handler to the servlet’s CometContext. This also gives rise to the first bug of the program – there’s no display of initial result.
So this:
<iframe name="hidden" src="CometCount" frameborder="0" height="0" width="100%"></iframe>
calls this:
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
CounterHandler handler = new CounterHandler();
handler.attach(res);
CometEngine engine = CometEngine.getEngine();
CometContext context = engine.getCometContext(contextPath);
context.addCometHandler(handler);
}
Next, someone, somewhere, who’s also using the program, hits the button marked “click”. This calls the onclick method, postMe(). postMe sends an empty POST to the servlet, triggering the doPost method.
So this:
<input type="button" onclick="postMe();" value="Click">
Calls this:
var url = "CometCount";
function postMe() {
function createXMLHttpRequest() {
try { return new XMLHttpRequest(); } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
alert("Sorry, you're not running a supported browser - XMLHttpRequest not supported");
return null;
};
var xhReq = new createXMLHttpRequest();
xhReq.open("POST", url, false);
xhReq.send(null);
hidden.location = url;
};
The doPost method increments the counter, and then sends a notify event to the servlet’s CometHandler.
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
counter.incrementAndGet();
CometEngine engine = CometEngine.getEngine();
CometContext context = engine.getCometContext(contextPath);
context.notify(null);
}
This event now wakes up that initial GET request, and sends a bit of javascript down the line. Lastly, we call resumeCometHandler, which marks the current event as completed, removing it from the active queue.
public void onEvent(CometEvent event) throws IOException {
if (CometEvent.NOTIFY == event.getType()) {
int count = counter.get();
PrintWriter writer = response.getWriter();
writer.write("<script type='text/javascript'>parent.updateCount('" + count + "')</script>\n");
writer.flush();
event.getCometContext().resumeCometHandler(this);
}
}
Back at the client, that javascript that got sent down gets put into the hidden iFrame, and then executed. This calls the updateCount function, which updates the counter with the new value. Then, we set the iframes’ location object, which reconnects with GET to the servlet, and we’re ready for our next request.
function updateCount(c) {
document.getElementById('count').innerHTML = c;
hidden.location = url;
}
That is, unless we time out. If we time out (remember, we set the timeout to 2 minutes, not “infinite”), the iframe goes dead, the GET polling loop is broken, and we never again update the counter on the webpage, though the user’s increasing frustrated button pushing on the client will happily update counter on the server. So, to get around this, we add a single line at the end of our postMe function, updating the hidden iframe’s location again. This is the one really hacky part of the program, and I’d love to know a better way to do it. Also, it gives rise to the second bug of our program, related to the first – if the connection dies, you need to click the button twice to see an update of the counter on the client.
So – ta da! We have a bare bones, long polling comet application in two files and about 100 lines.
Again, here’s the programs
Download file index.html
Download file CometCount.java
Jeanfrancois Arcand and I have a BOF on Wednesday night (May 7th, 2008) at JavaOne. If you’re at JavaOne and are just getting started with Comet, come on by.
(This article was originally published on my java.net blog on May 1, 2008.)
Servlet History
I’ve been doing servlets and JSPs longer than any other person on the planet (which in itself is a story for another time), so when I read a few things about the history of servlets in Beyond Java by Bruce Tate, I cringed. But I realize that such ancient history (10 years ago!) isn’t recorded anywhere, so I thought that I’d set the record straight.
In his book, Bruce says: “In the halls of Netscape, server-side Java emerged. Servlets (a term originally coined by O’Reilly) made server-driven Internet applications available to application developers. Sun capitalized on this movement quickly with a standard, and an open source implementation of a servlet engine called Tomcat.”
Whoosh, where to start. Prehaps at the beginning:
Servlets were originally conceived of by James Gosling in 1995, but put aside for other interests. After some time, the concept was picked up by Pavani Diwanji, who built on the concept to create servlets as part of a project then called Jeeves (from a fictional character). This project was eventually productized into the Java Web Server, which many of us in Java EE land remember fondly to this day. I still have a shirt showing Duke in a Tux holding a platter, the symbol for Java Web Server. And incidently, the first versions of the servlet package were called java.servlet.*, since the javax extension hadn’t been invented yet.
Incidently, JSP was invented over a weekend by Anselm Baird-Smith, then later elaborated on as a specification by Satish Dharmaraj (now of Zimbra). (Just in case anyone was curious.)
The server-side Java container conceived of by Netscape was done as a parallel effort, as was another similar thing done by Oracle. (I was part of the team that visited both companies to try to sell them on this technology.)
The Tomcat stuff came a few years later, as did the first version of the servlet spec, written by James Davidson.
As for O’Reilly coining the term servlets, I don’t know for sure about that, but given the history I do know, I’m skeptical.
There, I’ve gotten that off my chest.
Know something I don’t? Please comment below.
(Originally published on my java.net blog, on Dec 11, 2005.)