Thursday, May 31, 2007

Bitwise AND operator

To alternate the table background color:


rows [i].className = ((rows [i].index & 1) == 1) ? "alt" : "";

Friday, May 18, 2007

Javascript RegExp

- Example 1


var regex = /<title[^>]*>([\s\S]*?)<\/title>/i;
while(match = regex.exec(httpResp)){
if ('Login Page' == match[1]) {
...

"?" is important in the above regexp. By default it is greedy mode, with ?, it means the group will stop at the first encountered '<';

exec return ["<title>Login Page</title>", "Login Page"] since group () is used in regex which is useful to extract interested content.

-Example 2

html += ' <a href="javascript:showManyToMany (groupsForUser, \'' +
rowData.name.replace(/\'/g, "\\'").replace(/\"/g, "&.quot;") + '\');">Edit</a>';

In this case, single quote has to be escaped by javascript \\'; however Double quotes has to be escaped by html as &.quot; rather than \\", otherwise, "unterminated string literal" error occur. It looks like browser can understand \', but it doesn't
understand \".

- Example 3
cartName.replace(" ", "_"); will only replace first occurrence of space character. It should be cartName.replace(/\s/g, "_"). 1st parameter is regExp, rather than string, and /g means global search for all occurrences of a pattern. Note that the regular expression doesn't need to be quoted.

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) { ... }
});

Javascript undefined vs. null

In JavaScript, undefined means a variable has been declared but has not yet been assigned a value, such as:


var TestVar;
alert(TestVar); //shows undefined
alert(typeof TestVar); //shows undefined

null is an assignment value. It can be assigned to a variable as a representation of no value:

var TestVar = null;
alert(TestVar); //shows null
alert(typeof TestVar); //shows object

From the preceding examples, it is clear that undefined and null are two distinct types: undefined is a type itself (undefined) while null is an object.

Unassigned variables are initialized by JavaScript with a default value of undefined.

JavaScript never sets a value to null. That must be done programmatically. As such, null can be a useful debugging tool. If a variable is null, it was set in the program, not by JavaScript.

null values are evaluated as follows when used in these contexts:

Boolean: false
Numeric: 0
String: “null”

undefined values are evaluated as follows when used in these contexts:

Boolean: false
Numeric: NaN
String: “undefined”

.........................................................................................................................................................

null is an object. It's type is null. undefined is not an object, it's type is undefined.

Use if (SomeObject) to check value existence is not robust. It will also catch the cases of SomeObject having numeric value of 0, or string value of empty string. Because their boolean coercion is also false. See, in JavaScript, null and undefined are actually equal according to the == and != operator! (ECMA-262 standard, section 11.9.3 tells us so.) So we have null == undefined. In vast majority of cases, you don't care about the difference at all, so using someExpr != null is good enough.

If we really need to differentiate null and undefined, use

typeof(SomeObject) == 'undefined'

Session timeout handing in AJAX call

DWR has a textHtmlHandler that allows you to manage what happens when a DWR request receives a response that isn't Javascript. This generally means that a server session has timed out, so it is usual in a textHtmlHandler to redirect to a login screen.


dwr.engine.setTextHtmlHandler(function() {
//automatically take user to logon page due to timeout
document.location.reload();
});

You set a global error handler like this:

dwr.engine.setErrorHandler(handler);

You can also specify call or batch level error or warning handlers. For example, in the call meta-data:

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

or, in batch meta-data:


dwr.engine.beginBatch();

Remote.method(params, function(data) { ... });
// Other remote calls

dwr.engine.endBatch({
errorHandler:function(errorString, exception) { ... }
});

Unfortunately, Dojo doesn't provide such global error handler and has to be handled individually on each onLoad().

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

Tuesday, May 15, 2007

JSF study notes

- a Java component-oriented web framework (RAD)
- allows developers to think in terms of components, events, backing beans and their interactions, instead of requests, responses, and markup.
- higher level abstraction, Servlets and JSP were developed to make it easier to build applications on top of HTTP protocol. JSF was introduced so that developers can forget that they're using the protocol at all.

def: a software component is a unit of composition with contractually specified interfaces and explicit context dependencies only (container). A software component can be deployed independently and is subject to composition by third parties.

Events:
1. value change event
2. data model event - data row selected
3. action event - command from button or link
4. phase event - request processing life cycle event

Phases: (translate http request to events and update server side components value)
1. restore view
- find/create components tree, including event listeners, validators,converters associates with components; if initial request, skip to phase 6

2. apply request values
- update value of components to values in request, converter may get involved
-'immediate' property may trigger action event, handy for 'Cancel' button

3. process validation
- component validate itself
- value change events fired

4. update model values
- update value of backing beans or model objects associated with components

5. invoke application
- action events fired

6. render response
- render response, and save view in user session (?) to be restored later

Question: why may date model events be fired in phase2 - phase 4?

- 且就洞庭赊月色, 将船买酒白云边。

Webwork ScopeInterceptor

ScopeInterceptor is used to pull attributes out of session/applicaton and set action properties, i.e., dependency injection.


<action name="handleGeneralError" class="...">
<interceptor-ref name="scope">
<param name="key">FoglightError_</param>
<param name="session">exception,statusCode,originalRequestUri</param>
<param name="type">end</param>
</interceptor-ref>
<result .../>
</action>

key - key prefix
session - a list of action properties to be bound to session scope
type - 'end' means remove from session after action run; 'start' means it's a start action of the wizard-like action sequence and all session scoped properties are reset to their defaults; any other value or no value means that it's in-the-middle action that is set with session properties before it's executed, and it's properties are put back to session after execution.

Monday, May 14, 2007

HTTP Status Code & Error Handling

1xx Informational
2xx Successful (200 OK)
3xx Redirection (302 Found)
4xx Client Error (403 Forbidden 404 Not Found)
5xx Internal Server Error

We can define how a web application handles errors using the error-page element in the WEB-INF/web.xml file. The error-page element defines exceptions by exception type or by error code, as the following sections describe. The order of these elements in the web.xml file determines the error handler.


<error-page>
<error-code>500</error-code>
<location>/common/error/handleGeneralError.jsp</location>
</error-page>

<error-page>
<exception-type>java.io.FileNotFoundException </exception-type>
<location>/error-pages/404.jsp </location>
</error-page>

The HttpServletRequest and HttpServletResponse objects provide access to error information
...

Object status_code = req.getAttribute("javax.servlet.error.status_code");
Object message = req.getAttribute("javax.servlet.error.message");
Object error_type = req.getAttribute("javax.servlet.error.exception_type");
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
Object request_uri = req.getAttribute("javax.servlet.error.request_uri");

With such error information, we can delegate the error handling to one Action class which provides fine grained control, e.g, printStackTrace on screen on dev mode.

Tuesday, May 8, 2007

[Reading on Go] HEALTHY BUT BROKE

A British man who went on a wild spending spree after doctors said he only had a short time to live, wants compensation because the diagnosis was wrong and he is now healthy - but broke. John Brandrick, 62, was diagnosed with pancreatic cancer two years ago and told that he would probably die within a year. He quit his job, sold or gave away nearly all his possessions, stopped paying his mortgage and spent his savings dining out and going on holiday. It emerged a year later that Brandrick's suspected "tumour" was actually an inflamed pancreas.

- spree: a time of free and wild fun, spending, drinking, etc.
- inflamed: (of a part of body) read and swollen because hurt or diseased

Thursday, May 3, 2007

WebWork Result Types

Besides the default result type "dispatcher", there are some common result types:
1. redirect
Important for those create actions, reload confirmation page may result in re-create sth if URL stick to the previous create action. Parameter can be passed in by value in stack. e.g,
.. type="redirect">listBundles.action?archiveFilename=${archiveFilename}

2. chain
Action chaining is different from dispatching to another action in that:
- In same ActionInvocation
- Copy common properties from most recent action
In both cases, every action executed is pushed onto stack since they run in same thread/request.

3. StreamResult
For download file. BTW, use setTimeout() on init() to both refresh a page and download a file sounds a better solution than using refresh metatag which causes 'back' button problem.

We may even create customized ResultType such as JSON for AJAX call.

Wednesday, May 2, 2007

Some FreeMarker operators

- Number
value?c converts a number to string for ``computer audience'' as opposed to human audience.e.g., number 3600 will be parsed as 3600 instead of 3,600

- Handle missing values
exp1!exp2 deprecates exp1?default(exp2)
exp1! deprecates exp1?if_exists (replace with empty string "", empty set etc if not exists)
exp1?? deprecates exp1?exists

Note:
product.color?default("red")

This examines if the product hash contains a subvariable called color or not, and returns "red" if not. The important point is that product hash itself must exist, otherwise the template processing will die with error.

(product.color)?default("red")
This examines if product.color exists or not. That is, if product does not exist, or product exists but it does not contain color, the result will be "red", and no error will occur.