Showing posts with label ajax. Show all posts
Showing posts with label ajax. Show all posts

Thursday, May 17, 2007

Session timeout handing in AJAX call

DWR has a global handler textHtmlHandler for this purpose. When a DWR request receives a response that isn't Javascript. It indicates a server session has timed out, and we can redirect user to logon screen in this handler. So any DWR call doesn't need to worry about session timeout.


dwr.engine.setTextHtmlHandler(function() {
document.location.reload();
});

Unfortunately, Dojo doesn't have such mechanism, so for each dojo.io.bind or FormBind, we have to deal with it individually as shown below.

load: function(type, data, evt) {
sessionTimeoutCheck(data, evt);
...
}

I have modified dojo source code (doLoad method in BrowserIO.js) to support a global/transparent session timeout for dojo. I don't think Dojo itself will support this feature in the future. This is because dojo's response could be 'text/html' mimeType, which is typically used in setURL of contentPane. And the server normally returns the logon page when session timeout occurs. So dojo cannot know whether it is a requested page or timeout page. DWR is simplier since it doesn't support text/html and we can treat a html response as timeout.


** More on DWR's error handling - It has global/batch/call three levels of fine-grained support.

global error handler:

dwr.engine.setErrorHandler(handler);

call level error handlers:

Remote.method(params, {
callback:function(data) { ... },
errorHandler:function(errorString, exception) { ... }
});

or, in batch level:

dwr.engine.beginBatch();
Remote.method(params, function(data) { ... });
// Other remote calls
dwr.engine.endBatch({
errorHandler:function(errorString, exception) { ... }
});

Wednesday, April 25, 2007

Avoid XMLHttpRequest caching


var url = "../index.html?randomKey=" + Math.random() * Date.parse(new Date());

The task is to poll server periodly for availability with a scheduled XMLHttpRequest (using JS's setInterval("heartbeat()", 15*1000); However, in IE the response is cached even though those meta tags such as 'cache-control', 'expired' have been set to no-cache. And I have tried to set these in request header and not helpful either. The ajax calls are still cached and always return status 200 even though server is down and 404 should be returned. The IE caching is based on url, therefore, append a random key will resolve this issue.

Friday, April 20, 2007

DWR's Method Signature

JS client side


SecPasswordChecker.preLoginCheck (name, password, callback);

Java server side

public String preLoginCheck (String userName, String password, ServletContext servletContext) {..}

The method signatures of DWR method on Javascript side and server side are not equivalent. JS side declare callback whereas server side allows us to add HTTP servlet object (i.e. HttpServletRequest, HttpServletResponse, HttpSession, ServletContext or ServletConfig) declared on your method. DWR will not include it on the generated stub and upon a call of the method it will fill it in automatically.

Thursday, April 19, 2007

DWR's async trick


function submitUserAction() {
sdgControlSelectedRows (userGrid, method);
sdgRequestRows (userGrid);
}

First line delete some rows, second line requests lasted rows after udpate. Both using DWR invocation.It is surprising to see that the rows on the table not changed althought the selected rows are deleted on server side unless we intentionly refresh/reload the page. It is due to the asynchronous nature of AJAX call. 2nd statement is executed before the 1st one finished -- i.e, before the row deletion. Both method invocations are queued in ajax engine, and invoke server side in order, however, server's response may come back in any order, thus, 1st request involved DB operation and take longer time and 2nd request always come back earlier and its callback invoked first. It results in the table not being refresh.

The solution is to add them to a batch and treated as an atomic request, similar to a transaction.

function sdgControlSelectedRows (gridObject, method) {
if (! dwr.engine._batch) {
DWREngine.beginBatch ();
gridObject.gridServer.controlSelectedRows (method, {
callback: function (response) {
if (response != 'success') {
dojo.event.topic.publish("actionMessageTopic", {message: response, type: "ERROR", delay: 4000});
}
},
errorHandler: function (message) {}
});
sdgGetRows (gridObject, "control");

DWREngine.endBatch();
}

Wednesday, April 18, 2007

Dojo's Formbind


dojo.require("dojo.io.*");

var x = new dojo.io.FormBind({
formNode: "configureDirectoryForm",
mimetype: 'text/json',
load: function(type, data, e) {
alert("type=" + type + "Data=" + data);
}
});

x.onSubmit = function(form) {
// validate form or dispaly loading msg
return true; // need this, otherwise form won't get sent!
}

Alternatively,

dojo.io.bind({
formNode: dojo.byId("agentCreationForm"),
method: 'post',
mimetype: 'text/json',
load: function(type, data, e) {
alert("type=" + type + "Data=" + data.state);
msgDialog.hide();
},
error: function(type, data, e) {
alert("An error occured!");
}
});

However, it has the limitation in form validation. It only allow client side JS validation. If we use webwork's validation framework, the response is html page with error msg rather than JSONObject string and cannot be interpreted.