Sunday, August 29, 2010

Handling Session timeout & other server http errors in AJAX

 

AJAX has really changed the way we build web applications.When I surf internet today, I find almost all the websites Ajaxified in some way. Writing an AJAX application is as simple as writing simple JavaScript methods and some server side code.

I have been writing AJAX codes since a long time now and believe me tge most difficult part is to handle errors and exceptions. Session timeout is one of the most trivial error that one needs to consider while creating an AJAX enabled application.

Normally, we use AJAX to deliever HTML content that we put in a DIV or SPAN tag and display it on screen. But suppose the request that we sent using AJAX was generated an error due to session timeout then the session timeout screen will be shown in DIV tag. Any error generated by server let say http 404 error or http 505 can lead to display such error in our display DIV.

Handle Session timeout errors

One solution that you can use to handle the session timeout errors is using JSON or XML format as output for your AJAX requests. You have to check for session in your script, say for example if you are using JSP then probably you can do something like this:

 

if(null == session || session.getAttribute("SOME_ATTR_THAT_I_PLACED_IN_SESSION")) {
isSessionNull = true;
}
...
{
<%
if(isSessionNull) {
out.println("status: error");
}
else {
out.println("status: success");
}
%>
}

In short, create a status field in your JSON script or a status tag in your XML which will describe the status of the request.

I am looking for some more ways of checking session timeouts in AJAX. Kindly let me know if you have a good solution.

Handle Server HTTP errors in AJAX


HTTP errors like 404, 503 are sometimes tedious to handle using AJAX. There is a simple trick to solve this problem. First let us see simple AJAX handler function that we use to get response XML/text through AJAX.

 

xhr.open("GET", "http://someurl", true);
xhr.onreadystatechange = handleHttpResponse;
xhr.send(null);
...
...
function handleHttpResponse() {
if (xhr.readyState == 4) {
//handle response your way
spanBodyContent.innerHTML = xhr.responseText;
}
}

Normal AJAX handlers has a if to check readyState and if it is 4 (response arrived state) then we get the response from xhr.responseText or xhr.responseXML.

AJAX’s XMLHttpRequest object has attributes to check the status of your http request. You can use two attributes: status and statusText for knowing this.

xhr.status
..
xhr.statusText


Thus by checking status attribute from your AJAX xhr object can solve your problem.

xhr.open("GET", "http://someurl", true);
xhr.onreadystatechange = handleHttpResponse;
xhr.send(null);
...
...
function handleHttpResponse() {
if (xhr.readyState == 4) {
try {
if(xhr.status == 200) {
//handle response your way
spanBodyContent.innerHTML = xhr.responseText;
}
}catch(e) {//error}
}
}
Thus, if status is not 200, you may not want to update your DOM with the ajax result and display some error message on your web page.

Amazon Online Shopping with Web Service Framework for PHP

Introduction

phpIf you have done any on-line shopping, then you probably don't need an introduction to Amazon.com. But have you ever thought of writing your own application to make purchases on Amazon? In fact, you can do just that with the Amazon Web Services API. This tutorial guides you through writing a simple PHP application to access Amazon E-commerce Web services to do on-line shopping, using the Web Services Framework for PHP.

Table of Contents

 

Designing the PHP Class Library for Amazon

When writing a Web service application, it is a good practice to keep all of the Web service invocation logic in a separate layer and build the dependent logic on top of that. So, in this case we will create a class named 'AmazonClient' and contain all the Web services requests to the Amazon Web service in it.

First of all, create the skeleton of the class which would be filled by the operations as we go on through the tutorial.

<?php
class AmazonClient extends WSClient
{
const AMAZON_ENDPOINT = "http://webservices.amazon.com/onca/xml";

private $amazon_key;
private $amazon_service;


public function __construct($amazon_key)
{
parent::__construct(array(

"to"=>self::AMAZON_ENDPOINT ));
$this->amazon_key = $amazon_key;
$this->amazon_service = "AWSECommerceService";
}


/* the service operations to be implemented */

}
?>

So whoever uses this PHP class will only need to write the following bit of code. For example, to do an ItemSearch:

$amzon_client = new AmazonClient("your amazon key");
$amazon_client->ItemSearch();

Next, we will look at how to fill the class body with service operation invocations..


 


Using The SOAP API


As always, we will start our on-line shopping task by searching. For that, you can use Amazon's ItemSearch service operation.


ItemSearch operation requires a keyword and a Search Index as input parameters. In fact, the keyword will be your search query. Search Index is the item category you want to search, and hence needs be one of the values defined by Amazon. Some of the possible values are Books, Music, DVD, Software, Software Video Games and etc..


Here is our version of ItemSearch which just wraps the Amazon request for ItemSearch:

/**
* Search Web
* @param $query query string
* @param $catagory catagory to search
* @param $catagory page to search
* @return associate array consist of the response parameters
*/

public function ItemSearch($query, $catagory, $page = 1)

{
$req_payload = <<<XML
<ItemSearch xmlns="http://webservices.amazon.com/AWSECommerceService/2007-10-29">
<AWSAccessKeyId>19VBVF8C8HQQ0HTH7PR2</AWSAccessKeyId>
<Request>
<ResponseGroup>Medium</ResponseGroup>
<ItemPage>{$page}</ItemPage>
<Keywords>{$query}</Keywords>
<SearchIndex>{$catagory}</SearchIndex>
</Request>
</ItemSearch>
XML;
/* call the request method with the request payload */
$ret_message = $this->request($req_payload);
$simplexml = new SimpleXMLElement($ret_message->str);


$res = $simplexml->Items;

return $res;
}

You can test your code very easily with the following bit of code:

<?php
require_once("AmazonClient.php");
$amazon_client = new AmazonClient("your amazon key");


$items = $amazon_client->ItemSearch("Web Services", "Books");
foreach($items->Item as $item)

{
echo $item->ASIN.". ";
echo $item->ItemAttributes->Title. " - ";
echo $item->ItemAttributes->Author. "\n";

}
?>

You will find the detailed result se, that contains the information of the Books you searched for, like Book Title, Authors etc. Amazon returns many other fields that you may be interested in like the DetailPageURL ($item->DetailPageURL) of the item.


You may have noticed in the above code I have been echoing the "ASIN" of the item ($item->ASIN). ASIN is the unique identifier of the item used by Amazon. This is required to be remembered, since you will need it when you are adding items to the shopping cart.


After you've found the item you've been looking for, you may do a simple lookup on that particular item. For that, Amazon provides the ItemLookup operation. Here, by setting the request parameter 'ResponseGroup' to 'Large'. you will be able to access more information about the book, like people's reviews, impressions and so on.

/**
* ItemLookup
* @param $ASIN Amaxon Item Id
* @return associate array consist of the response parameters
*/

public function ItemLookup($ASIN)
{


$req_payload = <<<XML
<ItemLookup xmlns="http://webservices.amazon.com/AWSECommerceService/2007-10-29">
<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>
<Request>
<ResponseGroup>Large</ResponseGroup>
<ItemId>{$ASIN}</ItemId>
<ReviewPage>1</ReviewPage>
</Request>
</ItemLookup>
XML;

$ret_message = $this->request($req_payload);
$simplexml = new SimpleXMLElement($ret_message->str);


$res = $simplexml->Items;

return $res;
}

You will be able to access this operation using the following lines of code:

/* we can use the same $amazon_client we created for the ItemSearch */
$lookups = $amazon_client->ItemLookup("0131488740");

echo $lookups->Item->ASIN.". ";

echo $lookups->Item->ItemAttributes->Title. " - ";
echo $lookups->Item->ItemAttributes->Author. "\n";

 


This way you will be able to retrieve a lot of interesting details of the item you want to buy, from your applicaiton. But if you feel that you may have missed something, you can simply put a link to the Item web page in Amazon.com by setting a hyperlink to the $lookups->Item-> DetailPageURL value inside the above code. After these operations, you will probably have enough information about the Item and may decide that you really want to buy this Item. In fact, you can put that Item to the virtual shopping cart through the Amazon 'CartCreate' operation. With this operation you can give one or more items you wish to add to the cart.

/**
* CartCreate
* @param $items array of items you wish to add to the new cart
* sould be a hash of "Product ASIN"=> "Quantity"
* @return associate array consist of the response parameters
*/

public function CartCreate(Array $items)

{

$items_xml = "";
foreach ($items as $asin => $quantity)

{
$items_xml .= <<<XML
<Item>
<ASIN>{$asin}</ASIN>
<Quantity>{$quantity}</Quantity>
</Item>

XML;
}
/* Create the request payload */
$req_payload = <<<XML
<CartCreate xmlns="http://webservices.amazon.com/AWSECommerceService/2007-10-29">

<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>
<Request>
<Items>
$items_xml
</Items>
</Request>
</CartCreate>
XML;
/* call the request method with the request payload */
  $ret_message = $this->request($req_payload);
$simplexml = new SimpleXMLElement($ret_message->str);


$res = $simplexml-> Cart;

return $res;
}

Note that you are giving the items you want to buy in a hashmap with the mapping "Product ASIN"=> "Quantity". So the following code shows how you can create a cart and check the total price.

$cart = $amazon_client->CartCreate(array("0131488740" => 5));

echo $cart-> CartId." - ";
echo $cart->CartItems->SubTotal->FormattedPrice."\n";

echo $cart->PurchaseURL."\n";

From this you can retrieve the following information:




















Cart Id$cart-> CartIdThe Id of the cart you just created
HMAC$cart-> HMACSecurity Token which would be required in order to change the cart later
Purchase URL$cart->PurchaseURLYou can navigate to PurchaseURL to continue the rest of the transaction through the Amazon website..
CartItemId$cart->CartItems->CartItem[x]->CartItemIdThis exists for each cart item and is different from ASIN


Here you will need to keep the Cart Id, HMAC and CartItemId for each Item in order to modify or clear items in the cart. I will show you how you can implement it in your application with Amazon's CartModify and CartClear operations.

/**
* CartModify
* @param $cart_id id of the cart to modify..
* @param $HMAC security token for authentication..
* @param $items array of items you wish to change
* sould be a hash of "Cart Item Id"=> "Quantity"
* @return associate array consist of the response parameters
*/

public function CartModify($cart_id, $HMAC, Array $items)

{

$items_xml = "";
foreach ($items as $cart_item_id => $quantity)

{
$items_xml .= <<<XML
<Item>
<CartItemId>{$cart_item_id}</CartItemId>
<Quantity>{$quantity}</Quantity>
</Item>

XML;
}

/* create the request payload */
$req_payload = <<<XML
<CartModify xmlns="http://webservices.amazon.com/AWSECommerceService/2007-10-29">
<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>
<Request>
<CartId>$cart_id</CartId>
<HMAC>$HMAC</HMAC>
<Items>
$items_xml
</Items>
</Request>
</CartModify>
XML;
/* call the request method with the request payload */
$ret_message = $this->request($req_payload);
$simplexml = new SimpleXMLElement($ret_message->str);


$res = $simplexml-> Cart;

return $res;
}
/**
* CartClear
* @param $cart_id id of the cart to modify..
* @param $HMAC security token for authentication..
* @return associate array consists of the response parameters
*/

public function CartClear($cart_id, $HMAC)
{


$req_payload = <<<XML
<CartClear xmlns="http://webservices.amazon.com/AWSECommerceService/2007-10-29">
<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>
<Request>
<CartId>$cart_id</CartId>
<HMAC>$HMAC</HMAC>
</Request>
</CartClear>

XML;
/* call the request method with the request payload */   
$ret_message = $this->request($req_payload);
$simplexml = new SimpleXMLElement($ret_message->str);


$res = $simplexml;

return $res;
}

You will be able to modify or clear the cart you created earlier, using above operations in few lines of codes like the following:

$modified_cart_info = $amazon_client->CartModify("102-0208736-3675339", "lXOKkAyAVl6+/+D+KA3GvJRF4P0=", array("U181IPR3ATNL7R" => 3));


$cleared_cart_info = $amazon_client->CartClear("102-0208736-3675339", "lXOKkAyAVl6+/+D+KA3GvJRF4P0=");

Here I have put some fake values for HMACs, Card Ids and CartItemIds. Please use your own values here. (That is, you will be using the values retrieved from the CartCreate operation)


So that is all you need to write your own online shopping application. The next part of the tutorial is going to explain how to do the same thing in another way.


 


Using The REST API


The amazing thing about Amazon.com is that it provides Web services for both SOAP and REST consumers. And if you are using Web Service Framework for PHP you will be able to convert the SOAP consumer to a REST consumer with a very little change of code. But unfortunately with Amazon you may need to change all the request messages too, since their API for REST and SOAP are different. Now I will walk you through the same set of steps demonstrated above, but this time it will be using "REST" and not "SOAP".


The first and most important thing is to change the options of the WSClient constructor[4] which would be called inside the AmazonClient.

const AMAZON_ENDPOINT = "http://webservices.amazon.com/onca/xml";
parent::__construct(array(
"to"=>self::AMAZON_ENDPOINT,
"HTTPMethod"=>GET,
"useSOAP"=>FALSE));

Here, note the options given to the WSClient.












"to"This is the REST service endpoint of the Amazon ECommerce web service. This is different to the soap endpoint
"useSOAP" =>FALSEThis is where we tell the WSClient we are not interested in going with SOAP.
"HTTPMethod"=> "GET"We will use 'Get' method to do the queries

So that is the basic configuration you need to change to convert your SOAP consumer to a REST consumer. In addition to that you will need to change your request xml. For example, for the Item Search Operation your new (for REST) request will be like this.

<ItemSearch>
<Service>AWSECommerceService</Service>
<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>

<Operation>ItemSearch</Operation>
<Keywords>{$query}</Keywords>
<SearchIndex>{$catagory}</SearchIndex>

<ItemPage>{$page}</ItemPage>
</ItemSearch>

As you can see in the 'REST' request all the XML elements can go only one level deeper. So the elements like Keywords, SearchIndex and ItemPage are taken away from "Request" element (which is where they were in the SOAP request) and put as immediate child of the ItemSearch. So the WSF/PHP engine will convert this in to the following HTTP request..

GET /onca/xml?Service=AWSECommerceService&AWSAccessKeyId='Your_amazon_key'&Operation=ItemSearch&Keywords='Your-Query'&SearchIndex=Books&ItemPage=1 HTTP/1.1

You will probably be thinking how can you give an array of elements to the 'REST' request. This kind of request messages are present in the Amazon E-Commerce service as well. (e.g. CartCreate, CartModify)


So next we will see how to invoke the 'CartCreate' operation with REST.

$i = 0;
$items_xml = "";
foreach ($items as $asin => $quantity)

{
$i ++;
$items_xml .= <<<XML
<Item.$i.ASIN>$asin</Item.$i.ASIN>
<Item.$i.Quantity>$quantity</Item.$i.Quantity>

XML;
}
/* call the request method with the request payload */       
$req_payload = <<<XML

<CartCreate>
<Service>AWSECommerceService</Service>
<AWSAccessKeyId>{$this->amazon_key}</AWSAccessKeyId>
<Operation>CartCreate</Operation>
$items_xml
</CartCreate>

XML;

So for a call like the following,

$cart = $amazon_client->CartCreate(array("0131488740" => 5, "0234323234" => 3));
the generated request message will be like,
         <CartCreate>
<Service>AWSECommerceService</Service>
<AWSAccessKeyId>your_amazon_key</AWSAccessKeyId>
<Operation>CartCreate</Operation>

<Item.1.ASIN>0131488740</Item.1.ASIN>
<Item.1.Quantity>5</Item.1.Quantity>

<Item.2.ASIN>0234323234</Item.2.ASIN>
<Item.2.Quantity>3</Item.2.Quantity>

</CartCreate>

which would be ultimately converted to a HTTP GET request with the following format.

GET /onca/xml?Service=AWSECommerceService&AWSAccessKeyId=your_amazon_key&Operation=CartCreate&Item.1.ASIN=0131488740&Item.1.Quantity=5&Item.2.ASIN=0234323234&Item.2.Quantity=3 HTTP/1.1

You may be wondering now how you should handle the 'REST' Reponse, and if that would be different from the way you handle the 'SOAP' Response? Fortunately, it is not. Both the payload of the SOAP response and that of the REST response have the same format. That means, you can use the same piece of code to handle the response in both 'SOAP' and 'REST' forms when you are using WSClient.


If you followed the tutorial fully, you will now have a PHP class which helps you to access Amazon Web services either in REST or SOAP form. If you want to improve the flexibility of your class by giving the class user an option to set which request format (from 'REST' and 'SOAP') they prefer, what you need to do is to simply add another parameter to your class constructor that specifies whether to use 'REST' or 'SOAP. Based on this constructor parameter, you can select the logic to be used when sending the request. So users of the class do not need to worry about the underlying message format after they initially construct the class.


 


Conclusion


This tutorial guided you to write a simple web service consumer for amazon.com services using WSO2 Web Service Framework for PHP (WSF/PHP). By writing a consumer for a popular public Web service, the simplicity of the use of WSF/PHP consumer API and it s ability to call both 'REST' and 'SOAP' services with a minimum amount of work is highlighted.


Resources



Author


Dimuthu Gamage is a Software Engineer at WSO2. He is a commiter of the Apache Web Service project and a developer of the WSF/PHP and WSF/Ruby projects.


dimuthu at wso2 dot com.


I wrote an article on "Amazon Online Shopping with Web Service Framework for PHP" for Oxygen Tank.
There I'm demonstrating how to write a simple client library to access Amazon Web Services and how to use that library to write your own application to do online shopping with Amazon.com
There I attached the Client library code and two sample applications, one very simple php command line application and the other much improved web application. Hope this will be useful to people who are interested in working with WSF/PHP.

Sample jQuery AJAX Tutorial, Example: Simplify Ajax development with jQuery

jQuery, the JavaScript library provides some powerful set of jQuery AJAX API’s to handle AJAX requests. The normal way of making AJAX calls using JavaScript is a bit odd as you have to first create an XMLHttpRequest object that depends on the browser and then make an AJAX call. Also sending a form data using AJAX is also bit difficult if we use normal JavaScript approach of calling AJAX.

jQuery provides simple yet powerfull functions which have extended the JavaScript AJAX methods and provide more flexible way. Let us see different ways of doing AJAX things in jQuery.
GET Request method using jQuery

Load a remote page using HTTP GET request method. This is an easy way to send a simple GET request to a server. It allows a single callback function to be specified that will be executed when the request is complete (and only if the response has a successful response code).
jQuery.get( url, [data], [callback], [type] )

url: (String) The URL of the page to load.
data (Optional): (Map) Key/value pairs that will be sent to the server.
callback (Optional): (Function) A function to be executed whenever the data is loaded successfully.
type (Optional): (String) Type of data to be returned to callback function: “xml”, “html”, “script”, “json”, “jsonp”, or “text”.
e.g.

$.get(
 "http://some-remote-site",
 "{key:value}",
 function(data) { alert(data); },
 "html"
);

$.get(
 "http://some-remote-site",
 function(data) { alert(data); },
);


POST Request method using jQuery

Sending post method is also very easy with jQuery. All you have to do is just to call jQuery.post () method instead of jQuery.get (). Following is the syntax of post method.
jQuery.post( url, [data], [callback], [type] )

url: (String) The URL of the page to load.
data (Optional): (Map) Key/value pairs that will be sent to the server.
callback (Optional): (Function) A function to be executed whenever the data is loaded successfully.
type (Optional): (String) Type of data to be returned to callback function: “xml”, “html”, “script”, “json”, “jsonp”, or “text”.

$.post("test.php", { func: "getNameAndTime" },
  function(data){
    alert("Hello");
  }, "json");

Get JSON using jQuery

JavaScript Object Notation (JSON) is a popular light weight format that can be used to get data from server. JSON has became very popular since that web pages have became interactive using AJAX. JSON format is easy to create from the server and easy to parse at client as it is the basic object representation in JavaScript.

JQuery provides a function that can be used to make an AJAX call and get the data in JSON format. Normally the data that we get from AJAX is converted in JSON by calling eval () method of JavaScript. But the function provided by JQuery handles this internally and provides direct JSON object as output.
jQuery.getJSON( url, [data], [callback] )
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
        function(data){
          $.each(data.items, function(i,item){
            $("").attr("src", item.media.m).appendTo("#images");
            if ( i == 3 ) return false;
          });
        });

AJAX Start/End using jQuery

While you make an AJAX call and get some data from server, it is good to show a progress bar or image to user so that (s)he knows that something is going on. Hence Loading… text is common in AJAX enabled application.

What if you web application is making many AJAX calls like gmail. You may want to display a Loading… text while any of AJAX call is proceeding. To achieve this ajaxStart() and ajaxComplete() methods of jQuery can be used.

ajaxStart() method registers a function handler that will be called by jQuery internally whenever an AJAX call is made. If already a request is active than the handler is not called. We can use this method to register a handler function that will display our progress bar.
$.ajaxStart(function() {
 $("div#loading").text("Loading...");
});
In above code snippet, we used ajaxStart() method to register a function that set the innerHTML of div to Loading…

Similarly ajaxComplete() method can be used to register a handler function which gets called by jQuery when an AJAX request get completed and any other active request are not in progress.
$.ajaxComplete(function() {
 $("div#loading").text("");
});
Serialize html form using jQuery

While submitting a form using AJAX, one has to create a input string that contains the value of all the input elements on the screen. It is very difficult to create this string if your form is very big. Hence we can use jQuery’s serialize() and serializeArray() method to do so.
serialize()

Serializes a set of input elements into a string of data. Serialize is typically used to prepare user input data to be posted to a server. The serialized data is in a standard format that is compatible with almost all server side programming languages and frameworks. In order to work properly serialize requires that form fields have a name attribute. Having only an id will not work.
var str = $("form").serialize();
$("#results").text(str);
In above code snippet, we created a serialize output of the form. This value can be sent to server by an AJAX call.
serializeArray()

serializeArray() does the similar job. Except it creates JSON output.
[
     {name: 'firstname', value: 'Hello'},
     {name: 'lastname', value: 'World'},
     {name: 'alias'}, // this one was empty
]

php ajax code Delete Row from HTML Table by clicking it using jQuery

jQuery has became one of the most used and most loved JavaScript framework of all time. It not only does reduce the overhead in coding simple techniques in JavaScript, but also make your code cross browser compatible. I have written many tutorials on jquery and this time also I came with this simple plain implementation. The task is to remove the rows from a HTML table using some funky effects just by clicking the row. Following is the jQuery code to achieve this.

$(document).ready(function() {
 $("#sample tr").click(function() {
  //change the background color to red before removing
  $(this).css("background-color","#FF3700");

  $(this).fadeOut(400, function(){
   $(this).remove();
  });
 });
});


In above code we have attached handler with all “tr” in “#sample” table. On click we are first changing the background of the row and then fade it out and remove it. This is such a simple task.

Tuesday, August 24, 2010

Necessary before the operation of the program.

Necessary for the operation of the javascript have to reload the page to work with before. Conditions are. Assigned to work with the program when a page has finished loading. With the code below.

$(document).ready(function(){
    // From your code in this section.
 });

Writing code with jquery as follows.

 
    

begin with jquery


Create files for testing your learning jquery simple html
<html>

<head>
<script type="text/javascript" src="path/to/jquery.js"></script>
<script type="text/javascript">
/ / Insert your code here
</script>
</head>
<body>
<a href="http://jquery.com/">jQuery</a>
</body>
</html>
Edit the line location of the file jquery.js. Correct.
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
Ready for writing jquery.
<html>

<head>
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript">
/ / Insert your code here
</script>
</head>
<body>
<a href="http://jquery.com/">jQuery</a>
</body>
</html>