Introduction and Credits
There are a few crucial design decisions to be made when implementing an AJAX framework. We want to especially credit the authors of http://ajaxpatterns.org/ as their site helped us immensely in thinking systematically about our AJAX design.
Client vs. Server Framework
We decided to implement a server-side framework mainly:
- First of all we want to introduce AJAX gradually. We won't have an AJAX-only site any soon. Large parts of our applications will require full-page request/response cycles for a long time to come but will more and more be sprinkled with AJAX-driven components.
- Server-side frameworks keep most of the processing on the server while client-side frameworks offload some processing to the client thereby reducing server CPU load. Most typical PKP application installations are viewed by a moderate number of concurrent users and typically do not experience very strong access fluctuations. We therefore believe that in our case the advantages of a server-side design outweigh this disadvantage.
Semantic vs. HTML Data Payload
As we chose server-side processing as our general AJAX-approach, HTML payload is the logical consequence. We therefore decided to use HTML payload rather than passing semantic data (e.g. as XML) to the client.
We still may use semantic data payloads in specific use cases if we encounter requirements that force us to do so. This is especially the case where large data sets have to be transported to the client and manipulated there. Some performance relevant techniques (e.g. predictive fetch, XML data islands, etc.) work best with semantic data. Semantic data sets can improve usability and performance as data can be manipulated on the client without any need for network roundtrips.
XML vs. JSON vs. Plain Text Encoding
HTML can be transported over all three encodings. While plain text comes to mind first there are certain advantages in using XML or JSON even with an HTML payload. The advantage of a structured encoding is that you can send protocol data (e.g. status codes, etc.) together with the HTML payload.
We decided to wrap our data in JSON messages so we can send status messages along with the payload:
- JSON has a low memory and CPU footprint on the server side.
- There is less format interference between JSON and HTML than between XML and HTML. In other words: JSON messages with an HTML payload need less escaping and are therefore easier to read for the human eye.
We might use XML encoding for semantic data if we need it in the future (see the comment on semantic data in the previous section).
Browser XSLT vs. Templating
The reasons to use HTML payload, JSON encoding and server-side processing have already been laid out. This means that we cannot use client-side XSLT. We'll use server-side smarty templating instead.
REST-style vs. RPC-style Calls
Server-side AJAX calls go over HTTP. This means that server-side controller methods need to to be triggered over URLs requested over HTTP. REST-style calls are considered simpler and "cleaner" by some. They are modeled closely along features of the HTTP protocol. REST-style messages come to mind naturally when thinking of simple CRUD-style applications.
In our case, however, we believe that an RPC-style call schema is better suited:
- Our application is not a simple CRUD application. Our handler operations cannot be cleanly mapped to HTTP's PUT/DELETE/POST/GET methods. This impedance mismatch between the REST protocol and our internal API is the main reason why we prefer an RPC-style call scheme. It allows us to map URLs directly to our internal API in an easy and obvious way.
- We want to maintain maximum compatibility with a very large number of target installation environments. As some web servers do not support HTTP methods like PUT or DELETE we prefer to use an HTTP-to-handler-mapping that does not require "exotic" HTTP methods.
- We do not plan to expose our API directly to end-users which would be a certain argument in favor of a (simple) REST-style approach. In other words: we are providing full end-user applications and not web services. Where we explicitly provide web-services we still might think of using REST where appropriate.
SOAP vs. XMLRPC vs. Client Stub vs. Procedural API
RPC-style APIs can be exposed via a variety of different technologies. We chose a simple procedural approach that maps URLs to handler operations.
SOAP and XMLRPC calls are too complex for our simple requirements. We don't need to transport sophisticated data structures from the client to the server. The simple key-value approach of GET or POST requests can handle all we need. SOAP/XMLRPC would be over-engineered in our case.
The procedural API approach falls into place naturally. Please see our router architecture document for further details.
Performance-Relevant Design Patterns
We chose to employ multi-stage download where possible. This means downloading an HTML document to the client first that then triggers further network roundtrips to download components.
This has several advantages:
- The perceived loading time is reduced as the first response comes in quicker and the user already has the basic page structure on screen.
- The server-side framework we use supports multi-stage download well.
- Multi-stage download decouples the page controller from the component controllers. The only thing that the page controller needs to be aware of is the RPC service endpoint (=URL) of the components it wants to include.
Predictive fetch is a technology where the client decides to fetch more data from the server as currently needed to improve response time when the client needs the data later.
As we are using HTML payload and a server-side approach, predictive fetch cannot be used in our case (or is at least very difficult to use).