|
|
|
There is a ferocious battles for mind-share for what developers use to build RIA (Rich Internet Applications).
Adobe Flash
vs. Microsoft SilverLight which both say is superior to
AJAX (a term coined by Jesse James for
Asychronous Javascript
and XML).
AJAX is a design pattern that uses the XMLHttpRequest function built into Javascript.
Flash programming is appealing to Javascript coders struggling to achieve common behavior among browsers.
However, brave souls have come forward to put complex cross-browser coding into AJAX libraries (toolkis) of functions used to write nifty web browser apps with the look and feel of a desktop app that are portable.
Rather than downloading Dojo, jQuery, Prototype, Script.aculo.us, or MooTools, have clients download from
code.google.com/apis/ajaxlibs via a loader API
so that users only download the library once to their client for all sites.
This also enables Google to correctly set cache headers and staying up-to-date with the most recent bug fixes.
These are members of the
Open AJAX Alliance
which TIBCO implements with its publish/subscribe PageBus.
There is also:
.r.a.d.ajax $999 from Telerik claims a
no code approach because their Visual Stuido plug-in inserts the necessary code.
SlickSpeed compares the speed of Mootools vs. Dojo, Prototype, JQuery, and YUI.
BackBase claims to be the "most widely used Ajax Framework with the richest library of Ajax components."
If you get certificate errors, save the SSL certificate. Otherwise, you end up having VuGen record/generate this:
web_text_link("Continue to this website (not recomm",
"Snapshot=t1.inf",
DESCRIPTION,
"Text=Continue to this website (not recommended).",
ACTION,
"UserAction=Click",
LAST);
If you end up with this, comment it out in your script.
web_reg_find("Text=Untitled",
LAST);
To avoid a playback error, comment it out (with //).
Zip up the script folder immediately after a recording.
This preserves the Generation Log.
Unlike static HTML web pages, one cannot "View Source" at the client browser to look for text to correlate.
With AJAX sites, one must look at the dynamic exchange of data
VuGen captures in its Generation Log and
in VuGen's new Tree view.
VuGen captures the traffic between client and server much like HTTP Proxy client utilities such as Fiddler.
In the Generation Log, the first GET request is for the URL specified to obtain the response.
"HTTP/1.1 200 OK" is the normal expected valid response, as agreed in the HTTP 1.1 spec.
In the Response Header, notice the
Set-Cookie: JSESSIONID=89B629853850438A28F07F366FD57F4A; Path=/a4j-simpleRepeator
<HTML>
<HEAD>
</HTML>
<TITLE>ajax4jsf. Simple Repeator Demo</TITLE>
</HEAD>
<script type="text/javascript" src="/a4j-simpleRepeator/org.ajax4jsf.resource/org.ajax4jsf.framework.ajax.AjaxScript">
<BODY>
<form id="_id0" method="post" action="/a4j-simpleRepeator/demo.jsf" enctype="application/x-www-form-urlencoded">
</BODY>
<table><tbody>
</form>
<tr>
</tbody></table>
<td> Type the Text:</td><td><input type="text" name="_id0:_id3" value="" onkeyup="A4J.AJAX.Submit('_viewRoot','/a4j-simpleRepeator/demo.jsf',this,{'parameters':{'_id0:_id4':'_id0:_id4'}})" size="50"></td>
</tr><tr>
<td>Text in the AJAX Response:</td>
</tr>
<td><span id="_id0:repeater"></span></td>
<input type="hidden" name="_id0" value="_id0">
The remaining HTML is not shown here.
If the script was recorded with "Recording Options" set to "HTML", then the script would not have a separate request for the AjaxScript
because the "mode=HTML" in the VuGen script tells LoadRunner to automatically retrieve resources (such as script, css, img, and other files) mentioned in the HTML.
The "jsessionid=" appended to the end of the URL to retrieve the AjaxScript
means that the file will be downloaded again at the start of every session, which
developers want if the file changes dynamically.
If the script file is not expected to change, users would not need to wait for the file to be downloaded
if there was not a "jsessionid=" in the URL, since
the browser will automatically reuse what remains in the cache.
That is unless the browser has been set by the user to "refresh with every page" or the expiration date on the file has passed.
When normally static file changes, developers rename the file name to ensure that all active clients
get the new file rather than reusing the old file in their cache.
The AjaxScript file can be examined at the location where browsers download resources (cookies, CSS files, etc.).
On IE browsers, pull down "Tools", "Internet Options", click "Settings" within the "Temporary Internet files" section, then "View Files...".
This opens up a Windows Explorer.
Scroll right or expand the width of the window to click "Last Accessed" once or twice to sort the list.
Save the file by right clicking on it, select "Copy", then paste it into another Windows Explorer window.
At that new location, right click on it, select "Properties" to note its size (e.g., 50,798 bytes).
Use Wordpad to edit the file because it contains UNIX style line breaks which Notepad ignores.
For faster download, "production" websites would have the content of static compressed (stripped of whitespace such as blank spaces and tabs).
If that is the case, for human readability we would need to
reverse the compression by saving the code in a file and sending it through a code formatter utility to indent the statements.
The SlickEdit editor can reformat code.
BTW, at the top of the file, notice the comment "Sarissa
is an ECMAScript library acting as a cross-browser wrapper for native XML APIs."
Scroll down to see that this particular library uses logging functions extensively.
Notice that "RecContentType=text/javascript" appears even when the file name is suffixed with ".AjaxScript" rather than ".js". "AjaxScript" is really JavaScript.
Other websites code the onKeyPress= event instead because it represents the entire keystroke and can be canceled.
The event specified to fire is the A4J.AJAX.Submit function defined in a JavaScript/AjaxScript library on the client. Other libraries may use another function name.
Unlike other attributes, "onkeyup=" does not require the user to click on another area of the screen before it gets to work.
Search for this in the ActionScript file. We see that it accepts 3 parameters (separated by commas within the parentheses):
A4J.AJAX.Submit = function( containerId, form, obj , options ) {
This function in turn calls A4J.AJAX.SubmitRequest (which has the same parameters)
at last invokes form.onsubmit that sends a request out to the server
"/a4j-simpleRepeator/demo.jsf",
Java Server Faces file. specified "<form action=" HTML.
The request body shown in the Generation Log, such as:
are formatted in the "Add Event" script presented under "ITEMDATA" in VuGen scripts, presented in this table with a correspondence to the source of parameters in HTML code through AjaxScript functions:
| HTML | onkeyup= A4J.AJAX.Submit parameter | parameter in Javascript function | VuGen script generated within web_submit_data |
|---|---|---|---|
| <form action=... | '/a4j-simpleRepeator/demo.jsf' | form | "Action=http://livedemo.exadel.com/a4j-simpleRepeator/demo.jsf;jsessionid={JSESSIONID2}", |
| - | '_viewRoot' | containerId | "Name=AJAXREQUEST", "Value=_viewRoot", |
| <input type="text" name="_id0:_id3" | this | obj | "Name=_id0:_id3", "Value=x", |
| - | {'parameters':{'_id0:_id4':'_id0:_id4'}} | options | "Name=_id0:_id4", "Value=_id0:_id4", |
| <input type="hidden" name="_id0" value="_id0"> | - | - | "Name=_id0", "Value=_id0", |
| <form ... enctype="application/x-www-form-urlencoded" | - | - | "RecContentType=text/xml" |
Within the Javascript, note that "this" refers to the text object itself, which contains a text value "x".
The enctype="application/x-www-form-urlencoded" in the HTML form requests the browser to send (asynchronously) what the HTTP spec calls an XMLHttpRequest by specifying Content-Type: application/x-www-form-urlencoded;charset=UTF-8 in the Request Header.
"RecContentType=text/xml" appears with the web_submit_data instead of
"RecContentType=text/html" for regular HTML requests.
Internally, this results in VuGen sending out a "HTTPXMLrequest".
The second and subsequent Response Header do not contain a "Cookie: JSESSIONID=" that browers and LoadRunner automatically resend back to the server to help maintain the same session.
Note that the response body begins with <?xml version="1.0" encoding="iso-8859-1"?>, which IE does not display.
During playback, the Run-Time Viewer would display an error for pages beginning with this
(if in "Tools", "General Options", "Display" tab, "Show browser during replay" is checked).
A JavaScript listener function in the AjaxScript reads the rest of the response body. For example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>ajax4jsf. Simple Repeator Demo</title>
</head>
<body><hr />
<span id="_id0:repeater">x</span>
<span id="ajax-update-ids" style="display: none" title="_id0:repeater">
<input type="hidden" name="jsf_sequence" value="1" />
</span>
<div style="font-size:9px;height:150px;width:800px;
border: 1px solid darkblue;padding: 5px 5px 5px 5px; overflow: auto;"
id="logConsole">
</div>
</body></html>
Notice that this response does not contain some of the HTML of the first Response Body (why AJAX is preferred over traditional whole-page exchangees).
<span id="ajax-update-ids" style="display: none" title="_id0:repeater">
id="ajax-update-ids" triggers an update of the innerHTML text in the object named in title="_id0:repeater", which is defined in the first HTML above by <span id="_id0:repeater">.
An AjaxScript "callback" function update displays the text "x" between <span id="_id0:repeater"> and </span>.
So to verify the response, add to the VuGenscript a LoadRunner web_reg_save_param()
call to capture the text between those two markers.
web_reg_save_param("pRetText","Search=Body", "ORD=ALL",
"LB=<span id=\"_id0:repeater\">",
"RB=</span>", "Notfound=warning",
LAST);
Note that back slashes are added to quote characters being searched.
Add logic to perform the VuGen script command to capture the JSESSIONID value AGAIN if cookies are cleared or if the application user logs off.
Add logic to NOT perform the VuGen script command to capture the JSESSIONID value during the same continuous session.
This can be done by declaring an integer (binary) flag in the vuser_init section:
int intHaveJSessionID = 0; // 0 = NO.
The Action section would have:
if( intHaveJSessionID == 0 ){
web_reg_save_param("JSESSIONID2",
"LB/IC=jsessionid=",
"RB/IC=\"",
"Ord=1",
"Search=header",
"RelFrameId=1",
LAST);
intHaveJSessionID = 1; // 1 = YES
}
...
web_cleanup_cookies();
intHaveJSessionID = 0;
Simply adding "Notfound=warning", to the generated web_reg_save_param command does not work because that would cause the JESSIONID2 parameter to be unusable when the value is not there to find.
Because the Response Header is usually smaller than the Response Body, you can save a little script execution time by changing
"Search=body" to
"Search=header"
Instead of a traditional web_submit_data command, VuGen may records this out-going XML requests as web_custom_request() commands containing a Body such as:
"Body=AJAXREQUEST=_viewRoot&_id1%3AtextArea=This%20text%20area%20should%20not%20be%20updated&_id1%3A_id18=any&_id1%3A_id21=yellow&_id1%3A_id24=any&_id1=_id1&_id1%3A_id22=_id1%3A_id22&",
Other examples from Exadel, the sponsor of AJAX4JSP, require hidden type fields such as com.sun.faces.VIEW to be captured within VuGen scripts.
The Get Author webapp described here
| Requested by/as | File Downloadload | Bytes | Notes |
|---|---|---|---|
| user | solution.html | 2,067 | |
| - | .../fonts.css | 634 | |
| .../reset.css | 441 | ||
| .../yahoo.js | 4,548 | global object used by YUI Library. | |
| .../event.js | 60,717 | ||
| .../dom.js | 34,659 | ||
| .../calendar.js | 132,161 | ||
| .../calendar.css | 1,928 | ||
| EXTRARES | ...bc_1.7.3.js | 3,211 | |
| EXTRARES calendar.css | ...callt.gif | 94 | |
| ...calrt.gif | 94 | ||
| Total: | ?.? | ||
YAHOO.namespace("example.calendar"); invokes a function in the yahoo.js library which invokes the function YAHOO.widget.Calendar.
function init()" in the calendar.js library knows to replace
<div id="cal1Container"></div> with HTML code that it generates based on the current date.
Such generated HTML can only be seen if "Full Source" or a special Microsoft DLL is installed.
In that generated HTML, each clickable field is defined with a class and an id that are also generated internally by JavaScript.
YAHOO.util.Event.addListener(window, "load", init); establishes a listener for responses from the server.
The following response from the server is a JSON (JavaScript Object Notation) data payload format. Its use of braces and indentation instead of tags in XML makes it more "lightweight" and easier to read.
{"addressbook": {"name": "Mary Lebow",
"address": {
"street": "5 Main Street"
"city": "San Diego, CA",
"zip": 91912,
},
"phoneNumbers": [
"619 332-3452",
"664 223-4667"
]
}
}
Within browser Javascirpt, this is read by code such as:
var myObj = eval( '(' + JSON_response + ')' );
JSON is also favored because its use of server callback functions gets around browsers preventing files being loaded across domains
Json.org lists links, such as
BEA's Intro to JSON
Resources:
Related Topics:
Performance Testing
NT Perfmon / UNIX rstatd Counters
Mercury LoadRunner
Mercury Virtual Table Server (VTS)
Mercury WinRunner
Rational Robot
Free Training!
Tech Support
| Your first name: Your family name: Your location (city, country): Your Email address: |
Top of Page Thank you! | |||