
Client and server communication
Now that we've examined the client and server, we need to better understand the communication between the two. WaveMaker almost exclusively uses the HTTP methods GET
and POST
. In HTTP, GET
is used, as you might suspect even without ever having heard of RFC 2626 (https://tools.ietf.org/html/rfc2616), to request, or get, a specific resource. Unless installed as a native application on a mobile device, a WaveMaker web application is loaded via a GET
method. From index.html
and runtimeLoad.js
to the user defined pages and any images used on those images, the applications themselves are loaded into the browser using GET
. All service calls, database reads and writes, or otherwise any invocations of a Java service functions, on the other hand, are POST
. The URL of these POST
functions is always the service named .json
. For example, calls to a Java service named userPrefSvc
would always be to the URL /userPrefSvc.json
. Inside the POST
method's request payload will be any required parameters including the method of the service to be invoked. The response will be the response returned from that call. PUT
methods are not possible because we cannot nor do not want to know all possible WaveMaker server calls at "designtime", while the project files are open for writing in the Studio. This pattern avoids any URL length constraints, enabling lengthy datasets to be transferred while freeing up the URL to pass parameters such as page state.
Let's take a look at an example. If you want to follow along in your browser's console, this is the third request of three when we select "Fog City Books" in the CRM Simple application when running the application with the console open as we first did when exploring the sample application in Chapter 1, Getting Started with WaveMaker.
The following URL is the request URL:
http://crm_simple.localhost:8094/services/runtimeService.json
The following is request payload:
{"params":["custpurchaseDB","com.custpurchasedb.data.Lineitem",null,{"properties":["id","item"],"filters":["id.orderid=9"],"matchMode":"start","ignoreCase":false},{"maxResults":500,"firstResult":0}],"method":"read","id":251422}
The response is as follows:
{"dataSetSize":2,"result":[{"id":{"itemid":2,"orderid":9},"item":{"itemid":2,"itemname":"Kidnapped","price":12.99},"quantity":2},{"id":{"itemid":10,"orderid":9},"item":{"itemid":10,"itemname":"Gravitys Rainbow","price":11.99},"quantity":1}]}
As we expect, the request URL is to a service (in this case named runtime service), with the .json
extension. Runtime service is the built-in WaveMaker service for reading and writing with the Hibernate (http://www.hibernate.org), data models generated by importing a database. We'll learn more about the imported data models in Chapter 7, Working with Databases. Security service and WaveMaker service are the other built-in services used at runtime. The security service is used for security functions such as getUserName()
and logout()
. Note this does not include login, which is handled by Acegi. The WaveMaker service has functions such as getServerTimeOffset()
, used to adjust for time zones, and remoteRESTCall()
, used to proxy some web service calls. How the runtime service functions is easy to understand by observation.
Inside the request payload we have, as the URL suggested, a JavaScript Object Notation (JSON) structure. JSON (http://www.json.org/), is a lightweight data-interchange format regularly used in AJAX applications. Dissecting our example request from the top of the structure enclosed in the outer-most {}'s looks like the following:
{"params":[…….],"method":"read","id":251422}
We have three top level name-value pairs to our request object: params
, method
, and id
. The id
is 251422
; method is read and the params
value is an array, as indicated by the [] brackets:
["custpurchaseDB","com.custpurchasedb.data.Lineitem",null,{},{ }]
In our case, we have an array of five values. The first is the database service name, custpurchaseDB
. Next we have what appears to be the package and class name we will be reading from, not unlike from
in a SQL query. After which, we have a null and two objects. JSON is friendly to human reading, and we could continue to unwrap the two objects in this request in a similar fashion. Let's examine the rest of this request in Chapter 7, Working with Databases, when we discuss database services and check out the response. At the top level, we have dataSetSize
, the number of results, and the array of the results:
{"dataSetSize":2,"result":[]}
Inside our result array we have two objects:
[{"id":{"itemid":2,"orderid":9},"item":{"itemid":2,"itemname":"Kidnapped","price":12.99},"quantity":2},{"id":{"itemid":10,"orderid":9},"item":{"itemid":10,"itemname":"Gravitys Rainbow","price":11.99},"quantity":1}]}
Our first item has the compound key of itemid 2 with orderid 9. This is the item Kidnapped
, which is a book costing $11.99. The other object in our result array also has the orderid 9, as we expect when reading line items from the selected order. This one is also a book, the item Gravity's Rainbow
.