Posts Tagged Ajax

Accessing Ajax Response Headers

One way to handle error responses with Ajax requests is to add an HTTP Response Header to the response, denoting the resulting command status, while still returning content or data related to the error in the response. Generally when using Ajax calls you don’t want a raw exception or server error to bubble up to your JavaScript handlers.

Let’s say we have a simple quote service at “blurb.jsp”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@page import="java.util.Random"%>
<%!
    private static final Random rng = new Random();
    private static final String[] quotes = {
        "I regret that I have but one life to live for my country.",
        "To be or not to be, that is the question...",
        "I drank what?",
        "I am what I am and that's all I am"
    };
%>
<%
    try {
       // WARNING: intentional random error below
        final String quote = quotes[rng.nextInt(quotes.length+1)];
       
        response.setContentType("text/plain");
        response.setHeader("X-Status","OK");
        out.write(quote);
       
    } catch(Exception e){
        response.setHeader("X-Status","ERR");
        out.write("Something bad has happened: " + e.getMessage());
    } finally {
        out.close();
    }
%>

All this does is setup some simple quote strings and randomly provide one of them as a text response. I have added an error condition by allowing the random number generated to exceed the maximum index of the array so that we can get a random error response. In both cases, success or failure, the response header “X-Status” is given a value of “OK” or “ERR” respectively to denote the type of response being sent.

Handling this response with Prototype is pretty simple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<html>
    <head>
        <script type="text/javascript"
           src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"></script>
        <script type="text/javascript">
            Event.observe(window,'load',function(){
                $('quote').observe('click',handleClick);
            });
           
            function handleClick(evt){
                new Ajax.Request('blurb.jsp', {
                    onSuccess: function(response) {
                        var quoteElt = $('quote');
                        if( 'ERR' == response.getHeader('X-G-Status') ){
                            quoteElt.setStyle({color:'red'});
                        } else {
                            quoteElt.setStyle({color:'black'});
                        }
                        quoteElt.update(response.responseText);
                    }
                });
            }
        </script>
    </head>
    <body>
   
        <blockquote id="quote" style="border:1px dashed green;padding:4px;">Click me for a quote...</blockquote>
   
    </body>
</html>

Basically, in your “onSuccess” handler function you just pull the header value out of the response object. You could conceivably do any kind of response handling you wanted for an “error” response. In the little demo, you will get a quote from the server each time you click on the quote box; successful quotes will be black, while errors will be in red text.

For the heck of it, I decided to try the same thing in JQuery (without making a whole separate post about it). I am just including the script sections, since they are the only difference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type="text/javascript"
   src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
    jQuery(function(){
        $('#quote').bind('click',handleClick);
    });
   
    function handleClick(evt){
        var jqr = jQuery.get(
            'blurb.jsp',
            function(text){
                var quoteElt = $('#quote');
                if( 'ERR' == jqr.getResponseHeader('X-Status') ){
                    quoteElt.css('color','red');
                } else {
                    quoteElt.css('color','black');
                }
                quoteElt.html(text);
            },
            'text'
        );
    }
</script>

Surprisingly enough, this was a bit more difficult (or convoluted) to do with JQuery since JQuery does not seem to provide any wrapper access to the response itself. You have to use the XMLHTTPRequest object, which works fine but as you can see in the Ajax callback it leads to some interesting code; the jqr varible contains the request object and is used inside the callback function. It just feels a lot less clean.

Maybe I am not clear on how to use the JQuery Ajax support yet and I am missing something simple… or the developers of JQuery decided that since the times you actually need the response object itself are pretty limited, they could get away without providing direct access. Ultimately though, the support is there and that’s what’s really important.

Popularity: 2% [?]

  • Share/Bookmark

Tags: , , , ,

Google Ajax APIs

I came across the Google Hosted Ajax Libraries recently and have since found them to be quite useful, especially in quick testing situations where you really don’t want to have to setup a project. You can do everything in one nice text file.

To use the library you want, simply link to it using the external script source link:

1
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

Google has them hosted, minimized and cached so they are nice and fast. Pretty handy.

I mentioned this quickly in my post about Highlighting Text With JavaScript, but I felt that it needed its own little post so that it doesn’t get lost.

Popularity: 1% [?]

  • Share/Bookmark

Tags: , , ,

When Ajax Was Still Just a Cleanser

A few years ago the company I was working for did the SimCityScape web interface, which was the online component to the SimCity 2 game (EA Games/Maxis). I was the developer assigned to do the high-end JavaScript and any other programming for the site, while the CSS and design work was done by one of our graphic designers. One of the requirements was that the game interface should not have to reload when an action is performed… it was a very heavy interface with a pile of images that all had to be placed with some complex JavaScript — to reload this page with each action would have made the game unplayable.

These days I am sure the first thing that pops into your head is “AJAX, baby!”… well maybe without the “baby” part; however, back a couple years ago Ajax was still just a cleanser and there was no well-supported means of accomplishing “behind the scenes” data transfer without a page reload.

So what did I do? Well, I’ll tell you but you have to promise you won’t run away screaming… I am going to say a word that has a lot of undue negativity associated with it… applet.

Yes, I said it; I used an applet embedded in the page to allow the interaction on the front end to communicate with the backend, sans reload. It worked great, though I am not saying there weren’t some issues with it, especially since we had a “no plugin” requirement put on us, meaning that I only had the MS IE JVM (which is still lost somewhere around Java 1.1) available to me. I was able to use JavaScript to interface with the applet on the page which would fire off a request to the server. The server response was formatted text that was parsed into a data structure and returned to the JavaScript on the page (no JSON back then either). The nice thing about using an applet was that you could pass Java objects back to JavaScript and “just use them”. No fuss. No conversion.

Today I had the thought that even with all of this Ajax goodness, there still may be an interest in using an applet… so I will work a simple little example that does everything I mentioned above.

Let’s just make a simple data retrieval applet to demonstrate my point. You can take it from there if you are interested. The applet itself is quite simple. You just want to extend JApplet and override the init() method. All we are doing in our init() is getting the server url (there are other ways of getting this, but this is nice and easy). The applet code is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ControllerApplet extends JApplet {
    private String baseUrl;

    public void init() {
            this.baseUrl = getParameter("base.url");
            super.init();
    }

    public Map retrieveData(int id) throws Exception {
            Map map = new HashMap();
            URL url = new URL(baseUrl + "?pid=" + id);
            BufferedReader reader = null;
            try {
                    reader = new BufferedReader(
                            new InputStreamReader(url.openStream())
                    );
                    String line = reader.readLine();
                    if(line != null){
                            String[] nvps = line.split(";");
                            for(int n=0; n<nvps.length; n++){
                                    String[] parts = nvps[n].split(":");
                                    ap.put(parts[0],parts[1]);
                            }
                    }
            } catch(Exception ex){throw ex;}
            finally {
                    if(reader != null){
                            try {reader.close();} catch(Exception e){}
                    }
            }
            return(map);
    }
}

You will notice that the interesting method is the retrieveData(int) method. This is where the fun is. This method opens a stream to a local url (must be on the same server) and retrieves data from a JSP page (shown later) using a parameter. The data returned is read into a map which will then be used by the JavaScript that calls the applet.

Let’s embed this applet in a page and see something happen. I am only going to show the important fragments:

1
2
3
4
5
6
7
8
9
10
11
12
<APPLET name='controller' code='controller.ControllerApplet' width='0' height='0' mayscript='mayscript'>
    <PARAM name='base.url' value='http://localhost:8080/data.jsp' />
</APPLET>
   
<form name='theForm'>
    Person:
    <select name='pid'>
            <option value='1'>Abe Ableman</option>
            <option value='2'>Bob Baker</option>
    </select><br/>
    <button onClick='doSubmit(document.theForm.pid.value)'>Retrieve Info</button>
</form>

There is a lot to look at here. The first thing is the applet tag (you probably should use the Java Plugin object/embed tags, but this works for both IE and FireFox). The applet tag is given a name so that it can be easily referenced and mayscript is set so that we can call the applet using JavaScript. Also of note is the fact that this applet is 0 by 0; It’s a stealth applet.

The form is just a simple select list to pick a person that you want to retrieve information about. Now we need the JavaScript function that does the work:

1
2
3
4
5
6
7
8
9
10
11
12
function doSubmit(pid){
    try {
            var data = document.applets['controller'].retrieveData(pid);

            var info = 'Name: ' + data.get('Name') + '\n' +
                    'Department: ' + data.get('Department') + '\n' +
                    'Title: ' + data.get('Title');
            alert(info);
    } catch(ex){
            alert('Exception: ' + ex.toString());
    }
}

That wasn’t too bad. Basically all you have to do is call the retrieveData(int) method on the applet and the applet does the rest. One feature I have always liked about this is the ability to pass actual Java objects from the applet to the JavaScript. You will note that the data structure used here is a Map and JavaScript has no problems letting you handle it on the client side.

The JSP page I used for this is just a simple data switch:

1
2
3
4
5
6
7
<%@ page language="java" contentType="text/plain" pageEncoding="UTF-8"%><%
String pid = request.getParameter("pid");
if(pid != null && pid.equals("1")){
    out.println("Name:Abe Ableman;Department:Accounting;Title:Head Bean Counter;");
} else if(pid != null && pid.equals("2")){
    out.println("Name:Bob Baker;Department:Development;Title:Code Slave;");
} %>

Ultimately that’s all there is to it and this example works on IE 6 and FireFox 1.5. You can expand this to use XML, SOAP, formal HTTP clients, etc, but this is the meat of it all. The big problem you run into is security restraints that keep you in your own domain and the fact that the applet must be loaded before you can use it. The latter seems obvious, but I ran into cases where things were not loaded as you would expect.

In my opinion, Ajax is a more stable way of doing things, but you should always keep alternatives like this in mind. Applets got a bad reputation over the years that I don’t think they really deserve; they were an amazing addition to the web when they came out and they can still be pretty cool.

Popularity: 1% [?]

  • Share/Bookmark

Tags: ,

Switch to our mobile site