This is the second in my series of exploring EGL web service generation and runtime. (You can read the first installment
Exploring Web service generation and runtime - an overview.) This installment covers the generation and runtime for REST services and REST service invocations.
First the service. Back when we first started looking at implementing an EGL REST service, we had many design sessions and internally we spent a lot of time discussing different implementations. Based on those conversations and the fact that EGL service part is modeled after RPC, we started looking at JSON RPC. We discovered a couple of areas where JSON RPC didn't correlate with EGL: 1) EGL has multiple return parameters and JSON RPC has only a single return, and 2) EGL service functions throw a ServiceInvocationException which can contain more information than the JSON RPC simple error object. That's why you'll notice the EGL REST RPC service resembles a JSON RPC service, but is not JSON RPC.
EGL REST RPC services are only supported by Java generation. The EGL REST RPC service is exposed as an HTTP servlet. The servlet acts as the wrapper class to handle the data conversion and calling the generated EGL service. An EGL REST RPC service is only accessible using an HTTP POST where the HTTP body is a JSON-encoded RPC invocation and the HTTP response body contains the JSON encoded service response. The
RBD information center contains more information describing the exact JSON format of the
request and response.

The servlet needs to know what URI's correspond to what generated service. To provide this configuration information we generate a single XML file for each project. The XML file contains information for the servlet to map a valid URI to the EGL service to invoke. Generation or deployment does the following:
- Generates a -uri.xml file that contains a map of URI's to service classes. Each REST service in the egldd becomes an entry in this file.
- Registers the EGL RestServiceServlet servlet on the war, this configures the war to use the EGL RestServiceServlet for the base URI /restservices/ and for the servlet to load the -uri.xml configuration on startup to determine URI mappings.
At runtime:
- The application server routes the HTTP request to the EGL RestServiceServlet.
- The EGL RestServiceServlet determines there is a URI with /restservices/service id issued.
- The EGL RestServiceServlet parses the URI to extract the service id key to look up the service to instantiate.
- The EGL RestServiceServlet gets the JSON encoded request from the HTTP request body.
- The EGL RestServiceServlet instantiates the EGL generated service.
- The EGL RestServiceServlet converts the JSON to EGL runtime data.
- The EGL RestServiceServlet calls the service function on the EGL generated service passing the EGL runtime data.
- The EGL generated service executes the coded logic and returns.
- The EGL RestServiceServlet converts the EGL runtime data to a JSON response (this could be a thrown exception or data).
- The EGL RestServiceServlet creates an HTTP response.
- The EGL RestServiceServlet puts the JSON response in the HTTP response body.
- The EGL RestServiceServlet returns the HTTP response to the application server.
It's worth mentioning the EGL RestServiceServlet is used as both the servlet for a service and as the proxy for Rich UI client applications. The reason is because it's really performing the same functions; it receives a JSON request, decodes it and performs an action.
REST services including the EGL REST RPC service can be invoked from a JavaScript or Java generation environment. Both generation environments use a mixture of generated and runtime code to accomplished the service invocation runtime.

This block diagram shows at a high level the main components of a Java generation service invocation:
Generation/deployment:
In the Java generation environment the only service invocation specific file is the -bnd.xml file. The service invocation code will be generated into the file where you wrote the invocation. The -bnd.xml file will contain all of the service bindings selected for generation in the egldd file. Each binding has a name which is used at runtime to look up the binding information. The purpose of the binding is to decouple the EGL invocation from the physical implementation. We also provide @RESTBinding which can be used to bind the service reference variable so the binding occurs at generation time instead of runtime.
At runtime:
- The generated invocation instantiates the EGL Java runtime REST proxy.
There are 2 ways for the runtime to determine a REST invocation: - @RESTBinding will be in the EGL code in this case the generated code will contain all of the proxy configuration information.
- From reading a REST binding from the xxx-bnd.xml. In this case the proxy configuration information is contained in the -bnd.xml file.
- The generated code constructs the URL used by information from the proxy configuration information and the data passed from generated code.
- The generated code calls the EGL Java runtime REST proxy using the invoke method passing the EGL runtime parameters and the URL.
- The EGL Java runtime REST proxy converts the EGL runtime parameter data based on the specified encoding on the interface.
- The EGL Java runtime REST proxy creates an HTTP request setting the request httpMethod to the method specified in the interface.
- The EGL Java runtime REST proxy puts the encoded data on the body of the HTTP request.
- The EGL Java runtime REST proxy sends the data to the service.
- The service returns an HTTP response.
- The EGL Java runtime REST proxy retrieves HTTP response.
- The EGL Java runtime REST proxy decodes the response body back to EGL runtime objects based on the encoding specified in the interface.
- The EGL Java runtime REST proxy returns the EGL runtime data to the calling code.
NOTE: For both Java and JavaScript generation an EGL REST RPC invocation is a special case of a REST invocation where the request and response encoding are EGL REST RPC messages that consist of the data encoded as JSON and the httpMethod is set to POST.

When the invocation occurs in a JavaScript generation environment, there is both a JavaScript and a Java component of the invocation. JavaScript is bound by the "Same origin policy" and this means that JavaScript can only communicate back to the same server domain that served the JavaScript html file. So to accomplish a service invocation the generated JavaScript application needs 2 HTTP requests. The first request is between the browser (the JavaScript application) and the EGL proxy RestServiceServlet. The second request is from the EGL proxy RestServiceServlet and the service. In a similar manner, the response flows back from the service to the EGL proxy RestServiceServlet to the browser. Here is how how the EGL generated JavaScript application assembles the requests and expects the response:

An important thing to note is the service invocation request is encoded and decoded by the JavaScript code, the EGL proxy RestServiceServlet just handles the creation and population of the HTTP request and HTTP response, no EGL runtime data conversion occurs.
During deployment:
- A -bnd.js file is generated for JavaScript. The -bnd.js file serves the same purpose and the -bnd.xml file generated for Java: the configuration information for the service invocation and in this example an EGL REST proxy. The generated service invocation along with the bnd file are used to create the service invocation HTTP request. It is worth noting that the -bnd.js file is not assembled into the application html file like other generated .js files, the -bnd.js file is loaded by the html file when it is loaded. This provides a way to externalize service invocation URL's from the application logic.
- The EGL proxy RestServiceServlet is registered on the war. This configures the war to understand the ___proxy URI.
The JavaScript REST invocation is executed it follows the following path:
- The EGL generated JavaScript code calls the EGL REST proxy.
- The EGL REST proxy determines a REST invocation by either @RestBinding or reading the service binding from the -bnd.js file.
- The EGL REST proxy converts the request parameters and binding into a service HTTP request URL and encodes the parameters into the service HTTP request body. The encoding and httpMethod are obtained from the interface.
- The EGL REST proxy creates the RestServiceServlet proxy HTTP request targeting the EGL proxy RestServiceServlet URL (___proxy) on the application server.
- The EGL REST proxy encodes the service HTTP request and puts it in the EGL proxy RestServiceServlet HTTP request body.
- The EGL REST proxy sends the request to the EGL proxy RestServiceServlet on the application server.
- The JavaScript application is asynchronous so at this point the JavaScript application continues executing code at the next EGL statement after the service invocation call statement.
- The EGL proxy RestServiceServlet creates an HTTP request and populates it from the browsers HTTP request body.
- The EGL proxy RestServiceServlet sends the request to the service.
- The EGL proxy RestServiceServlet waits for the service to respond.
- The EGL proxy RestServiceServlet receives the response from the service.
- The EGL proxy RestServiceServlet creates an HTTP response to send back to the browser.
- The EGL proxy RestServiceServlet puts the response from the service into the HTTP response being sent back to the browser, and returns the response to the JavaScript running in the browser.
- The JavaScript runtime receives the response.
- The JavaScript runtime determines the response is a REST service invocation response. The information regarding how to handle the response was included in the JavaScript object that made the request.
- The JavaScript runtime converts the service invocation HTTP response to EGL runtime data by decoding it using the encoding specified on the interface.
- The JavaScript runtime calls the function specified in the call statement's 'returning to' passing the EGL runtime data.
In up-coming blogs, I'll discuss JAX-RPC SOAP for Java, Tomcat and WebSphere, and JAX-WS SOAP for Java, Tomcat and WebSphere. Let me know what service topics you'd like to hear about!
Joe Vincens