REST local binding

Local binding improves the performance of the REST framework by providing an optimized REST flow.

It prevents loop-back HTTP REST requests when the WebSphere Commerce WAR is on the same application server, and directly passes the response data map to the REST tag. That is, it forces the behavior of the HTTP REST request to operate on a single thread, and prevent the need to create multiple threads to resolve subsequent requests. Local binding prevents local calls from the WebSphere Commerce service to the REST service layer and prevents extra resources from being required from the WebSphere Commerce service (web container).

Local binding operates on the RESTtag. It supports requests under the RESTTag (wcf:rest) implementation.

The following optimized flow is the result of local binding on the REST framework:
Optimized flow for local binding on the REST framework
Where:
  • REST local binding creates an internal servlet request that wraps the original request, and an internal servlet response. The internal request overrides the URL with the initially started REST URL. The parameters, headers, and attributes are passed from the original request. Extra attributes to the request include the flag to indicate whether the current request is in local binding, the response data map, and the request body map. In addition, constants for local binding are also defined for store preview.
  • The internal response overrides the header and the response output stream to prevent any additional overhead. A separate local binding output stream is created for the response to prevent any overwrites with the output stream from the original request.
  • For requests that contain a body (POST and PUT requests), the body is added as an attribute to the request, in the form of a map, and passed to the handlers. When the request body is empty, the request body attribute in the request is also empty. When the request input map is added to the attribute of the internal request and fetching it when needed, the serialization and deserialization of the request body is avoided, with the raw data used when needed. All logic for fetching the request body map is performed within the com.ibm.commerce.foundation.rest.resourcehandler.AbstractResourceHandler.getMapFromRequest(HttpServletRequest request, String responseFormat) method. The method then returns a JSONObject of the data map from the internal request's attribute, when the IN_LOCAL_BINDING flag is set in the internal request's attribute. This data map is a hash map that is composed of the response data from the REST request made.
  • A request dispatcher is used to directly start a REST call without an HTTP request. The dispatcher is created using the REST context for the request, and the targeted URL is the path of the initial REST URL. After a dispatcher is retrieved, an include is performed on it using the internal request and internal response wrapper objects. After it is created and the servlet container is activated, the servlet that is mapped to the REST URL is entered in the dispatcher's creation. JSON is the forced response format for local binding and the response data map is set as an attribute of the internal request, then returned to the REST tag. By passing the data map directly, any serialization or deserialization of the data can be skipped, instead using the raw data map when needed.

Internal request optimizations

An internal request and response are created with a combination of values that are provided by the initial configuration file and overrides of the original values. The response format is set to be JSON (both the request query parameter and the header sets the responseFormat as JSON). Response logic is done in the JSON entity provider. The dispatcher is run to the formulated REST URL using the REST context first created at server start.

The following list summarizes some of the steps that might be skipped during the internal request that is run in local binding that usually occurs under remote binding. These steps are either determined to be unnecessary in local binding's being run, or cause extra overhead during run time and are omitted for performance optimization in local binding:
  • Skipping user session validation to reuse the existing validation token by using the request attribute that indicates local binding.
  • Skipping userId parsing to fetch the userId from the existing user session.
  • The authentication cookie, persistent session cookie, and user session are all retrieved from the session context.
  • Request input map is fetched directly from the internal request's attribute, and deserialization of the request body is avoided.
  • Any invocation of the XMLEntityProvider is skipped, as local binding solely operates within the JSONEntityProvider.
  • The Rest Tag is able to accept the response map as an attribute of the internal request. After control is returned to the RestTag, and any parsing of the output stream is skipped.

For store preview, code paths similar to the code provided in RestPreviewServlet are reproduced in the dispatcher's run time, with alterations for local binding. Store preview is determined by the in_Preview flag set in the request's attribute. The preview dispatcher is created using the REST servlet context from the ServerConfiguration, and the targeted URL is the path of the initial REST URL. After a dispatcher is retrieved, an include is performed on it using the created internal request and internal response wrapper objects.

The resulting data map is passed to the JSON Entity provider, converted to a JSON Object, and added as an attribute to the internal request. Any writing or handling of the response output stream uses the local binding response output stream to avoid unnecessary writes, since all data is passed through the request attributes. The REST Tag retrieves the map from the request attributes.