HST Request Processing
1. Introduction
Pipelines are based on the inversion of control pattern. The request processing pipelines are assembled through Spring Framework configurations. HST Container is largely driven by a request/response processing data flow, much like the servlet or HTTP request/response paradigm. Requests are made by client agents such as webbrowsers and the HST Container processes the request on the thread provided by the application server. Request processing is achieved in a workflow like pipeline, where valves are plugged into the request pipeline. The workflow of the valves is configurable just like any other components in the Spring Framework configurations. Pipelines reference (via Spring Framework dependency injection) one or more valves. Valves are also bean components which can be also assembled in the Spring Framework configurations.
2. Pipeline Driven Processing
Requests to the HST Container always come in via HstFilter which parses the URL and resolves a proper mount. The request URL can be mapped to a pipeline by configuring hst:namedpipeline property for a mount. By default, the default site pipeline aggregates HST Component pages.
.
3. Pipeline Architecture
In an HST based application, requests are processed through a series of Valves assembled together as a pipeline.
As described below, when a request comes, HstRequestContext is created to process the request through a pipeline.
.
4. Pipeline Mapping Configuration
The pipeline mapping configuration is provided in classpath:/org/hippoecm/hst/site/container/SpringComponentManager-pipelines.xml.
<bean id="org.hippoecm.hst.core.container.Pipelines" class="org.hippoecm.hst.core.container.HstSitePipelines"> <property name="defaultPipelineName" value="DefaultSitePipeline"/> <property name="pipelines"> <map> <entry key="DefaultSitePipeline"> <bean class="org.hippoecm.hst.core.container.HstSitePipeline"> <property name="initializationValves"> <list> <ref bean="initializationValve"/> <ref bean="cmsSecurityValve"/> </list> </property> <property name="processingValves"> <list> <ref bean="securityValve" /> <ref bean="subjectBasedSessionValve" /> <ref bean="jcrSessionStatefulConcurrencyValve"/> <ref bean="contextResolvingValve" /> <ref bean="localizationValve" /> <ref bean="actionValve" /> <ref bean="resourceServingValve" /> <ref bean="pageInfoRenderingValve" /> <ref bean="esiPageInfoScanningValve" /> <ref bean="pageCachingValve"/> <ref bean="componentRenderingValve" /> <ref bean="aggregationValve" /> </list> </property> <property name="cleanupValves"> <list> <ref bean="cleanupValve"/> <ref bean="diagnosticReportingValve"/> </list> </property> </bean> </entry> </property> </bean>
As you can see above, the request processing component of HST Container actually invokes three series of valves: initializationValves, processingValves and cleanupValves. The initializationValves contains valves which are responsible for initialization, the processingValves contains valves which are doing core request processing, and the cleanupValves contains valves which are responsible for cleaning up the temporary request processing data.
5. Request Handling with Components
In the previous sections, the internal pipeline processing inside HST Container has been discussed. In this section, a typical interaction between HST Container and each HST components will be discussed here to explain how the request processing is done with HST Components.
A typical page request can be depicted as follows:
In the above diagram, the following is assumed:
-
The client is requesting a page which maps to a page configuration which is composed of a root HST Component, "Parent".
-
The "Parent" component will be resolved to contain two child components at runtime: "LeftChild" and "RightChild". These two child components are siblings in this example.
-
At the time, suppose the client is submitting a form included in the "RightChild" HST Component to an HST Action URL.
The interaction sequences would be like the following in this example:
-
Client requests to HST Container via the HST Action URL.
-
Because the client is submitting a form by an Action URL, the Container invokes doAction() of "RightChild".
-
The Container redirects to a render page after invoking #doAction(). (Because the Container aggregates multiple components in a page, the Action phase should be separated from the Render phase of all components. HST Container aggregation implies PRG (POST/REDIRECT/GET) pattern.
-
Client requests to the render page.
-
The Container invokes #doBeforeRender() of each component. The invocation order of #doBeforeRender() is from parent to child.
-
The Container dispatches to the render path of the template of each component. The dispatch order is from child to parent.
-
A parent component's render page can include the rendered content of a child component. (For example, the template of the parent component can use <hst:include /> tag to include the rendered content of its child component.)
-
The Container writes the aggregated content to the client.
If the page did not submit a form via an Action URL, and it just request a page via GET method, then the sequence will start from 4 above.
6. HstRequest / HstResponse
During all the interactions between HST Container and HST Components, org.hippoecm.hst.core.component.HstRequest and org.hippoecm.hst.core.component.HstResponse objects are given to each component.
Basically, HstRequest and HstResponse are simply extending javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse. So, you can normally use the existing methods of those with HstRequest and HstResponse.
In addition, HstRequest object provide namespaced access to information such as the parameters and attributes for the component from the request, the HstRequestContext and lifecycle phase. The access is namespaced such that every HstComponent can read and write parameters and attributes from the HstRequest without needing to take into account other Components writing for example to the same attribute name.
With HstResponse, the HST Component can produce HST URLs, contribute head elements and set various HTTP headers. Also, with the template associated with the component, it may delegate the generation of content to a servlet, JSP or any other templates.