Spring MVC Bridge
Introduction
Goal
Integrate Hippo's delivery tier (HST) with Spring Web MVC.
Use Case
You may have an existing Spring Web MVC application that you want to integrate into your Hippo project. Hippo's delivery tier (a.k.a. HST) enables such integrations through the HST Spring MVC Bridge.
Spring Web MVC Bridge in HST
HST Spring MVC Bridge provides a simple integration with an existing Spring MVC application by using request dispatching.
To see a demo, build and run the demo in Hippo Test Suite project. This project is available in our source code repository: Hippo Test Suite.
Next, click on the Contact-SpringMVC link on the left menu of the example website ( http://localhost:8080/site/contact-springmvc). You will see a page containing a simple form and when you submit invalid information, e.g., wicky as email, the page will show validation errors which are generated by the Spring Web MVC Framework. If you then submit valid information, it will show a success view which is defined in the Spring Web MVC configuration.
In summary:
-
You need to use org.hippoecm.hst.component.support.SimpleDispatcherHstComponent for a HST component class with dispatching URI parameters.
-
You need to configure your own Spring MVC Framework based application which should be dispatched by the HST component.
-
You need to configure and use org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet instead of the default org.springframework.web.servlet.DispatcherServlet that is provided by the Spring MVC Framework.
-
You can make use of all features provided by Spring Web MVC Framework such as validating, form controller, etc.!
HstDispatcherServlet Configuration
In your web application, your have probably configured Spring MVC Framework DispatcherServlet. In order to use the HST Spring MVC Bridge solution you must replace the default org.springframework.web.servlet.DispatcherServlet with org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet.
<!-- SNIP --> <!-- NOTE: Use HstDispatcherServlet instead of the default DispatcherServlet! --> <servlet> <servlet-name>HstDispatcherServlet</servlet-name> <servlet-class>org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> </servlet> <!-- SNIP --> <servlet-mapping> <servlet-name>HstDispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- SNIP -->
The HST Container redirects the request to a new GET URL after processiong an action phase following the PRG pattern.
Therefore, HstDispatcherServlet should extend the default DispatcherServlet to do the following:
- After completing the action phase, it stores the ModelAndView object into HttpSession attributes temporarily.
- Before doing render phase, it restores the ModelAndView object from the HttpSession attributes if available.
The HstDispatcherServlet overrides the method render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) to accomplish those.
SimpleDispatcherHstComponent Configuration
You can configure a Spring MVC Bridge component as follows (example configuration taken from Contact-SpringMVC example in Hippo Test Suite):
Component: /hst:hst/hst:configurations/democommon/hst:components/bodycontactspringmvcformpage/content
<sv:node sv:name="content"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hst:component</sv:value> </sv:property> <sv:property sv:name="hst:componentclassname" sv:type="String"> <sv:value>org.hippoecm.hst.component.support.SimpleDispatcherHstComponent</sv:value> </sv:property> <sv:property sv:multiple="true" sv:name="hst:parameternames" sv:type="String"> <sv:value>action-path</sv:value> </sv:property> <sv:property sv:multiple="true" sv:name="hst:parametervalues" sv:type="String"> <sv:value>/spring/contactspringmvc.do</sv:value> </sv:property> <sv:property sv:name="hst:template" sv:type="String"> <sv:value>contactspringmvc</sv:value> </sv:property> </sv:node>
Template: /hst:hst/hst:configurations/democommon/hst:templates/contactspringmvc
<sv:node sv:name="contactspringmvc" xmlns:sv="http://www.jcp.org/jcr/sv/1.0"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hst:template</sv:value> </sv:property> <sv:property sv:name="hst:renderpath" sv:type="String"> <sv:value>/spring/contactspringmvc.do</sv:value> </sv:property> </sv:node>
In the example above the bridge component will use the contactspringmvc template in the RENDER phase to render.
But, in the ACTION phase (i.e., submitting a form via an HST Action URL), the bridge component dispatches the request to the /spring/contactspringmvc.do path (as configured by the action-path parameter) to process the action submission.
After processing the ACTION phase, the HstDispatcherServlet will store the ModelAndView object returned from the Spring controller and the HST Container will redirect to the original page, using the contactspringmvc template to do the rendering.
Please note that this bridge component ( SimpleDispatcherHstComponent) can have additional parameters as follows:
Name | Description |
dispatch-path | The default dispatch path, to which the container dispatches on each invocation. |
action-path | The dispatch path for doAction() invocation of the component. If this is not configured, then 'dispatch-path' would be used instead. |
before-render-path | The dispatch path for doBeforeRender() invocation of the component. If this is not configured, then 'dispatch-path' would be used instead. |
render-path | The dispatch path for rendering phase. If this is not configured, then 'dispatch-path' would be used instead. |
before-resource-path | The dispatch path for doBeforeServeResource() invocation of the component. If this is not configured, then 'dispatch-path' would be used instead. |
resource-path | The dispatch path for resource serving phase. If this is not configured, then 'dispatch-path' would be used instead. |
The Internals
The internal interaction between the bridge component ( SimpleDispatcherHstComponent) and the Spring MVC application can be explained with the following diagram (you can compare it with the diagram for the default DispatcherServlet).
If there's an ACTION phase request coming to the component, then it should pass from the step 1 to the step 6. For RENDER phase request, the remaining steps will be processed:
- HST Container process a FORM POST request and invokes the page containing the bridge component in ACTION phase.
- SimpleDispatcherHstComponent dispatches the request to Spring MVC application by the configured URI (e.g, "action-path" HST component parameter), which should map to a Controller in the Spring MVC application context.
- HstDispatcherServlet invokes a Controller configured in the Spring MVC application context.
- If the Controller in the ACTION phase returns a ModelAndView, then HstDispatcherServlet stores it into HttpSession for the specific HST Component window (the component window reference name is used for the session attribute key).
- SimpleDispatcherHstComponent finishes the ACTION phase processing.
- HST Container redirects to a RENDER URL after processing FORM POST request.
- HST Container process a GET RENDER request and invokes the page containing the bridge component in RENDER phase.
- SimpleDispatcherHstComponent dispatches the request to Spring MVC application by the configured URI (e.g, in either HST template configuration, "render-path" or "dispatch-path" HST component parameter), which should map to a Controller in the Spring MVC application context.
- HstDispatcherServlet checks if there exists a ModelAndView stored in HttpSession for the specific HST Component window (by using the key based on the component window reference name). If exists, it retrieves the ModelAndView attribute and removes it from HttpSession. And, it invokes a Controller configured in the Spring MVC application context to process the RENDER phase request.
- The Controller may return a new ModelAndView, and then HstDispatcherServlet renders the View Template with the model.