AJAX Hello World with JPSpan

In my AJAX introduction post I talked about SAJAX and JPspan this posts walks you through installing JPSpan and writing the same simple Hello World app as we did in the SAJAX post.

Setting up JPSpan

  1. Download JPSpan: http://prdownloads.sourceforge.net/jpspan/
  2. Extract and copy the extracted folder to somewhere in your include path
  3. Your good to go

Create the JPSpan server component

JPSpan provides a lot more functionality then SAJAX, the biggest difference you notice on the javascript side of thing is that you have mapped objects, on the php side the biggest difference is that you have a server page and a client page.

The default JPSpan server is called JPSpan_Server_PostOffice, it can be used to map entire classes to javascript, or you can pick and choose. If you were using the server on a large site you might want to add a get flag called class to limit which classes get included and registered to limit the overhead, but I haven’t had any performance problems just letting 4 or 5 integration specific classes be registered all the time.

Note: the JPSpan examples set a constant called JPSPAN_INCLUDE_COMPRESS, that strips javascript whitespace, the code that does this performs horribly, so make sure not to turn it on

// Hello World class goes here will show that next

// Including this sets up the JPSPAN constant
require_once 'JPSpan/JPSpan.php';

// Load the PostOffice server
require_once JPSPAN . 'Server/PostOffice.php';

// Create the PostOffice server
$S = & new JPSpan_Server_PostOffice();

// Register your class with it...
$S->addHandler(new HelloWorld());

// This allows the JavaScript to be seen by
// just adding ?client to the end of the
// server's URL

if (isset($_SERVER['QUERY_STRING']) &&
        strcasecmp($_SERVER['QUERY_STRING'], 'client')==0) {

    // Compress the output Javascript (e.g. strip whitespace)
    // turn this off it has performance problems

    // Display the Javascript client

} else {

    // This is where the real serving happens...
    // Include error handler
    // PHP errors, warnings and notices serialized to JS
    require_once JPSPAN . 'ErrorHandler.php';

    // Start serving requests...


App code

The app code is really quite simple, just like in the SAJAX case, here I just copied and pasted it into a class and put the session setup code in the constructor. You can do anything you would with a normal class here, but remember, this class is being recreated for each call from the javascript side, so if you want to keep class members between calls you’ll need to put the class instance in the session.

class HelloWorld {

        function HelloWorld() {
                if (!isset($_SESSION['strings'])) {
                        $_SESSION['strings'] = array('Hello','World','Hello World');

        function addString($string) {
                $_SESSION['strings'][] = $string;
                return $this->stringCount();

        function randomString() {
                $index = rand(0,count($_SESSION['strings'])-1);
                return $_SESSION['strings'][$index];

        function stringCount() {
                return count($_SESSION['strings']);

HTML code to display it

There is greater seperation between html and php when using jpspan, you include auto generated tieing code, this should allow for easier client side caching with a little header work, which is useful if your just using the code to add an autocomplete widget to a current site.

JPSpan can be used asynchronously (using callbacks) or synchronously (directly returning), generally you want to use things asynchronously since sync calls can cause the ui to freeze while your waiting for feedback. Sometimes this is actually what you want, but you’ll want to post some sort of please wait message if your transfering much of anything. More detail are given in a JPSpan tutorial on the projects wiki. In this example were using all async calls to match the SAJAX HelloWorld app.

        JPSpan Hello World

Number of Random Strings:
Add new String:

If you were paying attention to the app code you might have noticed one minor difference between this JPSpan version and the SAJAX version. Addstring returns the count in this version, SAJAX automatically handles multiple async calls at once JPSpan doesn’t seem to so all that extra remote call gives JPSpan a problem.

This project is the first time i’ve used SAJAX and I think its ability to handle multiple outstanding calls is a big benifit. There is nothing to stop JPSpan from adding this ability but it has had a release lately so im guessing it will need someone to step up to the plate and write some actual code to get it done.

View Hello world app
, server.php source, index.php source

In my next post i’ll investigate how well SAJAX and JPSpan handle passing complex data types.

35 thoughts on “AJAX Hello World with JPSpan”

  1. Is it just me or is the JPSpan example a lot slow ? 🙁
    Always found JPSpan to be a very interesting package and had hoped it would outscore SAJAX …

    Dunno why but I’m not liking that SAJAX is bundling gazillion things in, like ruby, asp, .net and things like that but I guess I’m just a odd little hobbit 😉

  2. I think its a bit slower too, im not sure if its just the fact that its not doing multiple async requests at once or its just slower cause its more code. I don’t really like the x_ prefix or the polluting of the javascript namespace that SAJAX does.

    I’m going to investigate how well SAJAX serializes complex data types at some point and if it does a good job i’m guessing i’ll fork it add in OO support and some sort of server and use it to replace JPSpan on my work projects. If its no good with complex types I guess i’ll try to replace fix JPSpan but certain parts of it seem overly complex to me.

  3. Well if Harry isn’t inactive or to busy then you should be able to poke him about this issues, it’s open source after all 😉

    Plus I like JPSpan more because I know who Harry F. is and that it’s focusing on PHP 😛

    I’ll wait interested on your results since I’ll also have to pick either one of those to implement into some Jaws features.

  4. “..SAJAX automatically handles multiple async calls at once JPSpan doesn’t seem to so all that extra remote call gives JPSpan a problem.”

    Could you elaborate on the above point? A possible reason why it might be slower is beacuse in JPSPan, the javascript are generated for each call and it is not cached (it send no-cache http headers).

    Note that in JPSpan, the results can be return as JS from the same server file.

    This is an example that used JPSpan




  5. Helgi:
    SAJAX support no complex types, no arrays, no objects, nothing.

    That example does seem to act a lot faster. Its not the seperate client file that is the issue, thats actually a plus since you can add a cache. It seems like im blocking trying to make an async call while one is currently outstanding. I think jpspan just needs to create multiple xmlHttprequests objects if that is possible. Anyhow im going to take a look, overall I think JPSpan is too complex, and uses way to many small classes, but I don’t really want to do the work to make SAJAX use basic OO so i’ll give speeding up JPSPan a try.

  6. OK – finally I will get active on JPSpan again very soon – just need to make some time.

    “If you were using the server on a large site you might want to add a get flag called class to limit which classes get included and registered to limit the overhead”

    I did provide examples of how it works but I “stole” some code from WACT to take care of this – it’s that JPSpan_Handle class and JPSpan_HandleDescription in the ‘Handle.php’ script.

    What it means is where you’re currently doing this;

    $S->addHandler(new HelloWorld());

    You could instead do this;

    // Description needed so JPSpan can skip introspection…
    $HWDesc = new JPSpan_HandleDescription();
    $HWDesc->class = ‘HelloWorld’;
    $HWDesc->methods = array(‘addString’,’randomString’,’stringCount’);

    $S->addHandler(‘path/to/helloworld.php|HelloWorld’, $HWDesc);

    The HelloWorld class will now only be included when one of it’s methods is actually called. You do need to be more careful about how you use class constructors with this approach though. It may be best to focus on making the methods “statically callable” and have then “initialize” a class when called.

    The basic approach being used was discussed a little here: http://www.sitepoint.com/blog-post-view.php?id=167792. Jeff’s actually improved the WACT support for this to the notion of “Delegates” – will probably steal some more later 😉

    Regarding the JPSPAN_INCLUDE_COMPRESS constant, had envisaged people caching the generated code server side (or at least client side with some HTTP headers). Perhaps I need to bundle that functionality? The code that does it also needs replacing, but that means writing some level of Javascript parser, which I don’t really want to do right now. If anyone knows of a better “Javascript compressor” in PHP, would love to hear about it.

    “Addstring returns the count in this version, SAJAX automatically handles multiple async calls at once JPSpan doesn’t seem to so all that extra remote call gives JPSpan a problem.”

    I guess what you’ve probably had there is a “call in progress” error message. I can’t remember now what the problem was but I found you can get “wierdness” happening when a single XMLHttpRequest is asked to handle multiple async requests. Saw this also in the Mozblog XML-RPC client (http://mozblog.mozdev.org/nsXmlRpcClient.js) which also uses XMLHttpRequest. JPSpan currently expects you to create multiple objects if you need this. I see that SAJAX creates a new XMLHttpRequest object on every call, which should also work fine.

    One simple way would be to move this to a function in Javascript e.g.;

    function createHW() {
    var remoteHW = new helloworld(hwCallback);
    return remoteHW;

    To avoid object setup costs though, might be worth having a “pool” of objects ready for use when you need them. This is also something JPSpan should probably handle and perhaps I should consider creating multiple XMLHttpRequest object rather that pushing this problem onto the user.

  7. Harry:
    Sounds good It looks like the full blown example app im creating will only have one class so I don’t think i’ll have the chance to show it in that, but when add that to the code I use for our work apps i’ll post the final code.

    On Javascript compression I was thinking the same thing, the only problem currently is it will bite you without it since it performs quite badly (can add a second or 2 of processing time), again I should be writing a cache at some point and i’ll post it when its done.

    Finally that seems to be the “call in progress” problem, though it I did think you got an alert with that error and I was just getting silent failure (hence weirdness). I think the best solution is to add a pool of just the httpclient objects if possible. I’ll be showing off using multiple objects in the example app im working on the AZphp Presentation on tuesday the 26th.

    That library looks interesting, I don’t think i’ll use its ajax code but its event and effects code look like they are useful for any Rich web app.

  8. hi

    thx for thos tutorial.
    fyi I encountered a problem with JPSpan 0.4.1 : JPSpan/JPSpan.php don’t exist in this release. You have to call JPSpan/Server.php instead.

  9. Its in the root directory.

    When you extract JPSPAN you get jpspan-0.4.1 directly in that direction is a JPSpan.php file it just sets a contant with the location of the JPSpan subdir inside of JPSPan so if you just copy out the JPSpan subdir from the tarball you’ll need to use server.php, but if you just rename jpspan-0.4.1 (what i dir) or put it in your include path, you can include that.

  10. Pingback: There and Back Again » Blog Archive » Improving JPSpan Performance with an Object Pool

  11. Pingback: http://www.webxl.net/wordpress/?p=15

  12. JSPAN cant use turkish characters like: şğüiçö

    Are there any Turkish support avalible? How can Is use turkish characters with this. Please help me.

  13. Debdebe, there is nothing inherant aboutt JPSpan that should break Turkish support, but I don’t really know whats involved in getting it working.

    Generally the easiest solution is to get everything working as UTF-8 which might mean setting up mbstring on the php side. I’m not sure how encodings work in JavaScript at the moment, it might be enough to just serve that code as utf-8 it might take something else. Sorry I’m not more help, eventually i’ll look into what supporting multi-byte characters takes but its not high on my list of priorities.

  14. Pingback: There and Back Again » Blog Archive » AJAX Hello World with HTML_AJAX

  15. Jspan site seems to be down. Some error about reading a cache. Even google’s cache has the same thing. I don’t have the lead developers email to drop him a line. Any1? Btw Jspan is the funkiest ajax php lib IMHO.

  16. Hi,

    I have been getting this weird server error “[Server][2000] Only variables should be assigned by reference. method called: …”. Jpspan has been working fine on my server which is running PHP 4.3.11, now I’m trying to implement it on the server which runs PHP 4.4.0.

    Could this a be coding error? server error? I’m kinda lost.

  17. Welcome to the wonderful world of PHP 4.4.0
    They broke backwards compatability and said we don’t care to the rest of us.

    I would recommend never using PHP 4.4.0
    If you need to use it hack up the included Error Handler to stop passing warnings to the JavaScript side. The file is jpspan\JPSpan\ErrorHandler.php shoudl be simple enough to multilate it, just return from the notice case in the switch.

  18. I think its the first case of the switch that handles notices, if you modified the default case you won’t get any errors passed over at all.

    Which might be what you want but i think there is a different way to disable all the error passing.

  19. Commenting out ” //require_once JPSPAN . ‘ErrorHandler.php’; ” from server.php did the trick. Why would PHP 4.4.0 not be backwards compatible, thats really dumb. Anyway, Thanks Joshua.

  20. There are bugs around how references are handled, any case that triggers those bugs now creates a warning. The PHP devs said its only a warning so it shouldn’t matter. But many people display or log warnings in order to get better bug reports so that logic fails. But anyway you look at it, its what were stuck with.

  21. can i update a row in my table using jpspan..means..
    i have a table that will update when i get data from database..
    hw to do this using JPspan..
    is then same way like update id in span or div..
    id so, how can i use the JPSpan…

  22. rohing: thats a possibility, you just have to be more careful about it, IE doesn’t like to dynamically update table rows unless you have a tbody.

  23. Pingback: Saahil Chopra » Blog Archive » Ajax For Beginners

  24. If JPSPan is used by https(sharing SSL)
    , client_error1997 is generated.

    How should I deal?

  25. If JPSPan is used by https(sharing SSL)
    , client_error1997 is generated.

    How should I deal?

    >>Sorry ! error code is 1007
    on http url address
    http is ok

  26. I have problem with asynchonize comunicate of JPSpan. Because in some cases, remote object havenot aready finished but we need the result of it to do another thing, that effects bad the system. In default, JPSpan communicated asynchronously. How can i set it synchronously?

  27. Thuy: I believe there is a Sync() method on the proxy. I would watch chaining AJAX requests though it adds tons of latency to your system. Your much better off making both calls on the server and just getting the final result back.

Comments are closed.