<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>Woonsan Ko</title>
      <link>http://blogs.onehippo.org/woonsan/</link>
      <description></description>
      <language>en</language>
      <copyright>Copyright 2009</copyright>
      <lastBuildDate>Fri, 05 Jun 2009 17:28:37 +0100</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

            <item>
         <title>Spring Web MVC framework support in HST-2</title>
         <description><![CDATA[<h1>Spring Web MVC framework support in HST-2</h1>
<br>
HST-2 has provided a basic support to enable developers to utilize
Spring Framework IoC container for HST components. [1]<br>
Now, HST-2 provides even more. It supports Spring Web MVC Framework
based applications under HST-2 environment! Using Spring Web MVC
Framework in HST-2 based application development, developers can make
use of very useful features that Spring Web MVC Framework is providing,
such as clear separation of roles (controller, validator, command
object, form object, model object, handler mapping, view resolver,
etc.), high configurability, customizability and flexibility.<br>
<br>
<em>Acknowledgement: I wrote and tested this Spring Web MVC Framework bridging solution with Spring Framework 2.5.6. However, I think this bridging solution would work with Spring Framework 1.1.5 or later version because the bridging solution depends on the followings only:
<ul>
<li>The bridging solution's extended DispatcherServlet needs to override <CODE><STRONG>protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)</STRONG>, which was added since Spring Framework 1.1.5.</CODE></li>
<li>The bridging solution is using simple URL dispatching to spring managed URLs, which has been already in the core part of Spring Web MVC Framework since its origination.</li>
</ul>
<br>
<br>
<h3>1. A Simple Form Controller Example: Contact-SpringMVC</h3>
You can build and run a Spring Web MVC Framework integration example.
This example is available since HST-2.03.07.<br>
<ul>
<li>Build all:<br>
<pre>$ mvn clean install -DskipTests</pre>
</li>
<li>Run a testsuite's cms application:<br>
<pre>$ cd testsuite/cms</pre>
<pre>$ mvn jetty:run-war</pre>
</li>
<li>Run a testsuite's site application:<br>
<pre>$ cd testsuite/site</pre>
<pre>$ mvn jetty:run</pre>
</li>
<li>Visit <a href="http://localhost:8085/site/preview/news">http://localhost:8085/site/preview/news</a></li>
</ul>
<br>
Now, click the "Contact-SpringMVC" link on the left menu. You can see a
page like the following:<br>
<br>
<div style="text-align: center;"><img
style="width: 317px; height: 172px;" alt="ContactSpringMVC-1"
title="ContactSpringMVC-1" src="http://blogs.hippo.nl/woonsan/contact-spring-1.png"><br>
</div>
<br>
<br>
If you enter some invalid information, e.g., "wicky" as email, the page
will show some validation errors which were generated by the Spring Web
MVC Framework like the following:<br>
<br>
<h4 style="text-align: center;"><img
style="width: 320px; height: 172px;" alt="Contact SpringMVC 2"
title="Contact SpringMVC 2" src="http://blogs.hippo.nl/woonsan/contact-spring-2.png"></h4>
<br>
Now, let's fill valid information and it will show a success view which
is defined in the Spring Web MVC configurations.<br>
<br>
<div style="text-align: center;"><img
style="width: 322px; height: 174px;" alt="Contact Spring MVC 3"
title="Contact Spring MVC 3" src="http://blogs.hippo.nl/woonsan/contact-spring-3.png"><br>
</div>
<br>
Here's the simplified configuration for the above Spring Web MVC
Framework based application.<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">&lt;?xml version="1.0" ?&gt;<br>
&lt;!-- <span style="font-weight: bold;">/testsuite/site/src/main/webapp/WEB-INF/applicationContext.xml</span>
--&gt;<br>
<br>
&lt;beans&gt;<br>
&nbsp; &lt;bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="prefix" value="/WEB-INF/jsp/"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="suffix" value=".jsp"/&gt;<br>
&nbsp; &lt;/bean&gt;<br>
<br>
&nbsp; &lt;bean<br>
&nbsp;&nbsp;&nbsp;
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="mappings"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span
style="font-weight: bold;">/spring/contactspringmvc.do =
contactFormController</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br>
&nbsp; &lt;/bean&gt;<br>
&nbsp; <br>
&nbsp; &lt;!-- Spring Web MVC Integration Example --&gt;<br>
&nbsp; &lt;bean id="<span style="font-weight: bold;">contactFormController</span>"
class="org.hippoecm.hst.springmvc.<span style="font-weight: bold;">ContactFormController</span>"&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="mailSender" ref="mailSender" /&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="templateMessage"
ref="templateMessage" /&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">formView</span>"
value="spring/contactspringmvc-form"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">successView</span>"
value="spring/contactspringmvc-success"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">commandName</span>"
value="contactMessage"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">commandClass</span>"
value="org.hippoecm.hst.springmvc.ContactMessageBean"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">validateOnBinding</span>"
value="true"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;property name="<span style="font-weight: bold;">validators</span>"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean
class="org.hippoecm.hst.springmvc.<span style="font-weight: bold;">ContactMessageValidator</span>"
/&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br>
&nbsp; &lt;/bean&gt;<br>
&lt;beans&gt;</td>
</tr>
</tbody>
</table>
<br>
There's nothing new. Every beans in the applicationContext.xml are just
normal beans which can be found in just a normal Spring Web MVC
Framework applications.<br>
The only connection point from HST-2 container is the following
component configurations in the repository:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">&lt;!-- <span
style="font-weight: bold;">/toolkit-resources/addon/testcontents/src/main/resources/hstconfiguration/components.xml</span>
--&gt;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:node sv:name="<span
style="font-weight: bold;">contactspringmvcform</span>"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:property
sv:name="jcr:primaryType" sv:type="Name"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;sv:value&gt;hst:component&lt;/sv:value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/sv:property&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:property sv:name="<span
style="font-weight: bold;">hst:template</span>" sv:type="String"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;sv:value&gt;<span style="font-weight: bold;">contactspringmvc</span>&lt;/sv:value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/sv:property&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:property sv:name="<span
style="font-weight: bold;">hst:componentclassname</span>"
sv:type="String"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;sv:value&gt;<span style="font-weight: bold;">org.hippoecm.hst.component.support.SimpleDispatcherHstComponent</span>&lt;/sv:value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/sv:property&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:property sv:name="<span
style="font-weight: bold;">hst:parameternames</span>"
sv:type="String"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;sv:value&gt;<span style="font-weight: bold;">action-path</span>&lt;/sv:value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/sv:property&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sv:property sv:name="<span
style="font-weight: bold;">hst:parametervalues</span>"
sv:type="String"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;sv:value&gt;<span style="font-weight: bold;">spring/contactspringmvc.do</span>&lt;/sv:value&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/sv:property&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/sv:node&gt;</td>
</tr>
</tbody>
</table>
<br>
The Contact-SpringMVC example has one component, "<span
style="font-weight: bold;">contactspringmvcform</span>", which
component class should be set to "<span style="font-weight: bold;">org.hippoecm.hst.component.support.SimpleDispatcherHstComponent</span>"
to enable bridging to a pure Spring Web MVC Framework application.<br>
Please note that this bridge component can have additional parameters
as follows:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top; font-weight: bold;">Name<br>
</td>
<td style="vertical-align: top; font-weight: bold;">Description<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">dispatch-path<br>
</td>
<td style="vertical-align: top;">The default dispatch path, to
which the container dispatches on each invocation.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">action-path<br>
</td>
<td style="vertical-align: top;">The dispatch path for doAction()
invocation of the component. If this is not configured, then
'dispatch-path' would be used instead.<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">before-render-path<br>
</td>
<td style="vertical-align: top;">The dispatch path for
doBeforeRender() invocation of the component. If this is not
configured, then 'dispatch-path' would be used instead.</td>
</tr>
<tr>
<td style="vertical-align: top;">render-path<br>
</td>
<td style="vertical-align: top;">The dispatch path for rendering
phase. If this is not configured, then 'dispatch-path' would be used
instead.</td>
</tr>
<tr>
<td style="vertical-align: top;">before-resource-path<br>
</td>
<td style="vertical-align: top;">The dispatch path for
doBeforeServeResource() invocation of the component. If this is not
configured, then 'dispatch-path' would be used instead.</td>
</tr>
<tr>
<td style="vertical-align: top;">resource-path<br>
</td>
<td style="vertical-align: top;">The dispatch path for resource
serving phase. If this is not configured, then 'dispatch-path' would be
used instead.</td>
</tr>
</tbody>
</table>
<br>
The bridge component, "<span style="font-weight: bold;">org.hippoecm.hst.component.support.SimpleDispatcherHstComponent</span>",
delegates all invocations by dispatching to configured paths.<br>
<br>
Finally, you need to configure an extended Dispatcher Servlet in
web.xml to run this example:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">&nbsp; &lt;servlet&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;<span style="font-weight: bold;">HstDispatcherServlet</span>&lt;/servlet-name&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;<span style="font-weight: bold;">org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet</span>&lt;/servlet-class&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;<span
style="font-weight: bold;">contextConfigLocation</span>&lt;/param-name&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;<span
style="font-weight: bold;">/WEB-INF/applicationContext.xml</span>&lt;/param-value&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br>
&nbsp; &lt;/servlet&gt;<br>
<br>
&nbsp; &lt;servlet-mapping&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;<span style="font-weight: bold;">HstDispatcherServlet</span>&lt;/servlet-name&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;<span style="font-weight: bold;">*.do</span>&lt;/url-pattern&gt;<br>
&nbsp; &lt;/servlet-mapping&gt;</td>
</tr>
</tbody>
</table>
<br>
The only difference is that the extended Dispatcher Servlet, "<span
style="font-weight: bold;">org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet</span>"
should be used instead of the default "<span style="font-weight: bold;">org.springframework.web.servlet.DispatcherServlet</span>"
of Spring Web MVC Framework.<br>
The reason why this is necessary is explained in the next section.<br>
<br>
In summary, you can use Spring Web MVC based application for HST-2
component development. <br>
<ul>
<li>To enable this bridging from HST-2 container, you need to use the
delegator component, "<span style="font-weight: bold;">org.hippoecm.hst.component.support.SimpleDispatcherHstComponent".</span>
</li>
<li>To allow seamless bridging from HST-2 container, you need to use
the "<span style="font-weight: bold;">org.hippoecm.hst.component.support.spring.mvc.HstDispatcherServlet</span>"
in your web.xml.</li>
<li>You need to configure some parameters such as "action-path" for
the delegator comopnent, "<span style="font-weight: bold;">org.hippoecm.hst.component.support.SimpleDispatcherHstComponent</span>".</li>
<li>You can now make use of all features provided by Spring Web MVC
Framework such as validating, form controller, etc.!<br>
</li>
</ul>
<br>
<h3>2. The Internal with Architectural Explanation<br>
</h3>
<h4>2.1. Introduction to HST-2 request processing</h4>
I think it is a good time to explain briefly about the request
processing architecture here because it is fundamental to understand
the bridging solution.<br>
For simplicity, I'd like to show an interaction between the HST
container and each HST component here instead of explaining all details.<br>
The basic interactions can be depicted as follows.<br>
<br>
<br>
<a href="http://blogs.hippo.nl/woonsan/hst-interaction.png" target="_blank"><img style="width: 353px; height: 265px;" alt="HST-2 Interaction"
title="HST-2 Interaction" src="http://blogs.hippo.nl/woonsan/hst-interaction.png"></a><br>
* Click the image to enlarge.
<br><br><br>
In the above diagram, the followings are assumed:<br>
<ul>
<li>The client is requesting a page which maps to a page
configuration which is composed of a root HstComponents, "Parent"</li>
<li>The "Parent" component has two child components, "LeftChild" and
"RightChild". These two child components are siblings.</li>
<li>At the time, the client is submitting a form included in the
HstComponent, "RightChild".<br>
</li>
</ul>
<br>
The interaction sequences would be like the following in this case:<br>
<ol>
<li>Client requests to HST-2 container.</li>
<li>Because the client is submitting a form by an action URL, the
container invokes doAction() of "RightChild".</li>
<li>The container redirects to a render page.<br>
(Because the container aggregates multiple components in a page, the
action phase should be separated from the render phase of all
components. HST-2 container's aggregation implies the PRG pattern. [2])<br>
</li>
<li>Client requests to the render page.</li>
<li>The container invokes doBeforeRender() of each component. The
invocation order of doBeforeRender() is from parent to child. The
invocation order between siblings is not specified.<br>
</li>
<li>The container dispatches to the render path of each component.
The dispatch order of render page of component is from child to parent.
The invocation order between siblings is not specified.</li>
<li>A parent component's render page can include the rendered content
of a child component.</li>
<li>The container writes the aggregated content to the client.<br>
</li>
</ol>
<br>
Here are important things to note as a bridge solution developer:<br>
<ul>
<li>Because the action phase request and render phase request are
separated in HST-2 request processing, the web application framework
should not assume that the request would be shared between the two
phases.<br>
For example, when you use SimpleFormController of Spring Web MVC
Framework with a form view page and a validator, if a user enters
invalid information in the form, the dispatcher would render the form
view again with some validation error information. Internally, this
information is stored in a ModelAndView object to be rendered in the
render phase. This cannot work in HST-2 request processing because the
requests are not shared between action phase and render phase.<br>
Therefore, that kind of shared information between action phase and
render phase should be passed correctly between two separate request
processing phases by bridging solutions.</li>
<li>By the way, because HST request and response objects are just
extended objects to the default HttpServletRequest and
HttpServletResponse, the other bridging integration stuffs could be
easier than expected in other technologies such as Apache Portals
Bridge. [3]<br>
</li>
</ul>
<br>
Because HST request and response objects are just HttpServletRequest
and HttpServletResponse objects, we can think of a very simple bridging
solution. We can create a HstComponent which dispatches all invocation
to the specified dispatch path. In this case, all necessary handlings
should be done by the dispatched servlet or JSP page.<br>
This is covered in the next section.<br>
<br>
<h4>2.2. A very simple bridging solution: <code>SimpleDispatcherHstComponent</code></h4>
This component is the simplest bridging solution to native
servlet-based applications.<br>
Here's the simplified source:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">package
org.hippoecm.hst.component.support;<br>
<br>
public class SimpleDispatcherHstComponent extends GenericHstComponent {<br>
&nbsp;&nbsp;&nbsp; public static final String LIFECYCLE_PHASE_ATTRIBUTE
= SimpleDispatcherHstComponent.class.getName() + ".lifecycle.phase";<br>
&nbsp;&nbsp;&nbsp; public static final String BEFORE_RENDER_PHASE =
"BEFORE_RENDER_PHASE";<br>
&nbsp;&nbsp;&nbsp; public static final String DISPATCH_PATH_PARAM_NAME
= "dispatch-path";<br>
&nbsp;&nbsp;&nbsp; public static final String
BEFORE_RENDER_PATH_PARAM_NAME = "before-render-path";<br>
&nbsp;&nbsp;&nbsp; public static final String RENDER_PATH_PARAM_NAME =
"render-path";<br>
&nbsp;&nbsp;&nbsp; public static final String ACTION_PATH_PARAM_NAME =
"action-path";<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; @Override<br>
&nbsp;&nbsp;&nbsp; public void doAction(HstRequest request, HstResponse
response) throws HstComponentException {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
doDispatch(getDispatchPathParameter(request,
request.getLifecyclePhase()), request, response);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; @Override<br>
&nbsp;&nbsp;&nbsp; public void doBeforeRender(HstRequest request,
HstResponse response) throws HstComponentException {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
request.setAttribute(LIFECYCLE_PHASE_ATTRIBUTE, BEFORE_RENDER_PHASE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String dispatchPath =
getDispatchPathParameter(request, request.getLifecyclePhase());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dispatchPath != null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
response.setRenderPath(dispatchPath);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
doDispatch(getDispatchPathParameter(request, BEFORE_RENDER_PHASE),
request, response);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
request.removeAttribute(LIFECYCLE_PHASE_ATTRIBUTE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; protected void doDispatch(String dispatchPath,
HstRequest request, HstResponse response) throws HstComponentException {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dispatchPath != null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
getServletConfig().getServletContext().getRequestDispatcher(dispatchPath).include(request,
response);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
catch (ServletException e) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
throw new HstComponentException(e);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
catch (IOException e) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
throw new HstComponentException(e);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; protected String getDispatchPathParameter(HstRequest
request, String lifecyclePhase) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String dispatchPath = null;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if
(BEFORE_RENDER_PHASE.equals(lifecyclePhase)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dispatchPath = getParameter(BEFORE_RENDER_PATH_PARAM_NAME, request,
null);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if
(HstRequest.RENDER_PHASE.equals(lifecyclePhase)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dispatchPath = getParameter(RENDER_PATH_PARAM_NAME, request, null);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if
(HstRequest.ACTION_PHASE.equals(lifecyclePhase)) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dispatchPath = getParameter(ACTION_PATH_PARAM_NAME, request, null);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dispatchPath == null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dispatchPath = getParameter(DISPATCH_PATH_PARAM_NAME, request, null);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dispatchPath != null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if
(dispatchPath.charAt(0) != '/') {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dispatchPath = new StringBuilder(dispatchPath.length() +
1).append('/').append(dispatchPath).toString();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return dispatchPath;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; protected String getParameter(String name,
HstRequest request, String defaultValue) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String value = (String)
this.getComponentConfiguration().getParameter(name,
request.getRequestContext().getResolvedSiteMapItem());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (value != null ?
value : defaultValue);<br>
&nbsp;&nbsp;&nbsp; }<br>
}</td>
</tr>
</tbody>
</table>
<br>
<br>
In the above component, doAction() just dispatches to a dispatch path,
which is configured by 'action-path' or falled back to 'dispatch-path'
if 'action-path' is not specified in the repository configuration.<br>
And, doBeforeRender() just dispatches to a dispatch path, which is
configured by 'before-render-path' or falled back to 'dispatch-path' if
'before-render-path' is not specified in the repository configuration.
Also, it sets the render path dynamically by the configuration value
for 'render-path', which can be falled back to 'dispatch-path' if not
configured.<br>
So, when the container invokes doAction() or doBeforeRender() of this
component, it actually dispatches to the native servlet or JSP pages.
Also, the container would invoke the render path dynamically set by
this component.<br>
The remaining thing is to write the dispatched servlet or JSP page to
handle all the invocation correctly.<br>
<br>
In most web application framework, the frontend controller should be a
servlet, but I'd like to use a simple JSP page for simplicity here.<br>
The above component should have a paramter 'dispatch-url' set to
'jsp/components/contactdispatch.jsp'.<br>
Here is an example native JSP page to handle those (as a simplified
version):<br>
<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">&lt;%--
/jsp/components/contactdispatch.jsp --%&gt;<br>
&lt;%!<br>
private static String[] formFields = {"name","email","textarea"};<br>
<br>
private void doBeforeRender(HstRequest request, HstResponse response)
throws HstComponentException {<br>
&nbsp;&nbsp;&nbsp; HttpSession session = request.getSession(true);<br>
&nbsp;&nbsp;&nbsp; FormMap formMap = (FormMap)
session.getAttribute("contactdispatch:formMap");<br>
&nbsp;&nbsp;&nbsp; if (formMap == null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formMap = new FormMap();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
session.setAttribute("contactdispatch:formMap", formMap);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; request.setAttribute("form", formMap);<br>
}<br>
<br>
private void doAction(HstRequest request, HstResponse response) throws
HstComponentException {<br>
&nbsp;&nbsp;&nbsp; HttpSession session = request.getSession(true);<br>
&nbsp;&nbsp;&nbsp; FormMap formMap = new FormMap(request, formFields);<br>
&nbsp;&nbsp;&nbsp; session.setAttribute("contactdispatch:formMap",
formMap);<br>
&nbsp;&nbsp;&nbsp; // Do a really simple validation: <br>
&nbsp;&nbsp;&nbsp; if (formMap.getField("email") != null &amp;&amp;
formMap.getField("email").contains("@")) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // success<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do your business logic<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // possible do a redirect to
a thankyou page: do not use directly response.sendRedirect;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HstSiteMapItem item =
request.getRequestContext().getResolvedSiteMapItem().getHstSiteMapItem().getChild("thankyou");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (item != null) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sendRedirect(request, response, item.getId());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
log.warn("Cannot redirect because siteMapItem not found. ");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // validation failed.
Persist form map, and add possible error messages to the formMap<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formMap.addMessage("email",
"Email address must contain '@'");<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
private void sendRedirect(HstRequest request, HstResponse response,
String redirectToSiteMapItemId) {<br>
&nbsp;&nbsp;&nbsp; HstLinkCreator linkCreator =
request.getRequestContext().getHstLinkCreator();<br>
&nbsp;&nbsp;&nbsp; HstSiteMap siteMap =
request.getRequestContext().getResolvedSiteMapItem().getHstSiteMapItem().getHstSiteMap();<br>
&nbsp;&nbsp;&nbsp; HstLink link =
linkCreator.create(siteMap.getSiteMapItemById(redirectToSiteMapItemId));<br>
&nbsp;&nbsp;&nbsp; StringBuffer url = new StringBuffer();<br>
&nbsp;&nbsp;&nbsp; for (String elem : link.getPathElements()) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String enc =
response.encodeURL(elem);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url.append("/").append(enc);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; String urlString = ((HstResponse)
response).createNavigationalURL(url.toString()).toString();<br>
&nbsp;&nbsp;&nbsp; try {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
response.sendRedirect(urlString);<br>
&nbsp;&nbsp;&nbsp; } catch (IOException e) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new
HstComponentException("Could not redirect. ",e);<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
%&gt;<br>
<br>
&lt;%<br>
HstRequest hstRequest = (HstRequest) request;<br>
HstResponse hstResponse = (HstResponse) response;<br>
<br>
String hstRequestLifecyclePhase = hstRequest.getLifecyclePhase();<br>
String dispatchLifecyclePhase = (String)
hstRequest.getAttribute(SimpleDispatcherHstComponent.LIFECYCLE_PHASE_ATTRIBUTE);<br>
<br>
if (HstRequest.ACTION_PHASE.equals(hstRequestLifecyclePhase)) {<br>
&nbsp;&nbsp;&nbsp; doAction(hstRequest, hstResponse);<br>
} else if
(SimpleDispatcherHstComponent.BEFORE_RENDER_PHASE.equals(dispatchLifecyclePhase))
{<br>
&nbsp;&nbsp;&nbsp; doBeforeRender(hstRequest, hstResponse);<br>
} else if (HstRequest.RENDER_PHASE.equals(hstRequestLifecyclePhase)) {<br>
%&gt;<br>
&lt;div&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;form method="POST" name="myform"
action="&lt;hst:actionURL/&gt;"&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;input type="hidden" name="previous"
value="${form.previous}"/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;br/&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;table&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;Name&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;input type="text" name="name"
value="${form.value['name']}" /&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;font
style="color:red"&gt;${form.message['name']}&lt;/font&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;Email&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;input type="text" name="email"
value="${form.value['email']}"/&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;font
style="color:red"&gt;${form.message['email']}&lt;/font&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;Text&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;textarea
name="textarea"&gt;${form.value['textarea']}&lt;/textarea&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;font
style="color:red"&gt;${form.message['textarea']}&lt;/font&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;c:if test="${form.previous != null}"&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;input type="submit" name="prev" value="prev"/&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;/c:if&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;td&gt;&lt;input type="submit" value="send"/&gt;&lt;/td&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/table&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;/form&gt;<br>
&lt;/div&gt;<br>
&lt;% } %&gt;</td>
</tr>
</tbody>
</table>
<br>
<br>
Because the component just dispatches each invocation to a dispatch
path, the above JSP pages should handle everything correctly.<br>
The following JSP scriptlets detect the request process lifecycle
phases and invoke the proper methods, which were just copied from the
existing Contact component example.<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: top;">&lt;%<br>
if (HstRequest.ACTION_PHASE.equals(hstRequestLifecyclePhase)) { <br>
&nbsp;&nbsp;&nbsp; doAction(hstRequest, hstResponse); <br>
} else if
(SimpleDispatcherHstComponent.BEFORE_RENDER_PHASE.equals(dispatchLifecyclePhase))
{ <br>
&nbsp;&nbsp;&nbsp; doBeforeRender(hstRequest, hstResponse); <br>
} else if (HstRequest.RENDER_PHASE.equals(hstRequestLifecyclePhase)) {<br>
%&gt;<br>
//...<br>
&lt;%<br>
}<br>
%&gt;<br>
</td>
</tr>
</tbody>
</table>
<br>
So, any kind of servlet based application can control everything by
using this kind of technique.<br>
<br>
<h4>2.3. An extended DispatcherServlet: <code>HstDispatcherServlet</code></h4>
In the Spring Web MVC Framework bridging solution, the simplest
bridging component, "<code>SimpleDispatcherHstComponent</code>", is
used, and the 'action-path' parameter is just set to a spring managed
URL like '<span style="font-weight: bold;">spring/contactspringmvc.do</span>'.<br>
So, we can say that the frontend controller should handle everything.<br>
For this reason, we provide a dispatcher servlet, "<span
style="font-weight: bold;">HstDispatcherServlet</span>", which extends
the default <span style="font-weight: bold;">DispatcherServlet</span>.<br>
The responsibility of HstDispatcherServlet is very simple. It should
pass the ModelAndView object from the action request phase to render
request phase: <br>
<ul>
<li>After completing action phase, it should store the ModelAndView
object into session attributes temporarily.</li>
<li>Before doing render phase, it should restore the ModelAndView
object from the session attributes if available.</li>
</ul>
<br>
HstDispatcherServlet just overrides the method, <span
style="font-weight: bold; font-style: italic;">render(ModelAndView mv,
HttpServletRequest request, HttpServletResponse response)</span> of the
default DispatcherServlet to accomplish this.<br>
<br>
<br>
<br>
<h3>References</h3>
[1]
<a
href="http://blogs.hippo.nl/woonsan/2009/04/spring_framework_support_in_hs_1.html">http://blogs.hippo.nl/woonsan/2009/04/spring_framework_support_in_hs_1.html</a><br>
[2] <a href="http://en.wikipedia.org/wiki/Post/Redirect/Get">http://en.wikipedia.org/wiki/Post/Redirect/Get</a><br>
[3] <a href="http://portals.apache.org/bridges/">http://portals.apache.org/bridges/</a><br>
<br>
<br>

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-9457822-1");
pageTracker._trackPageview();
} catch(err) {}</script>]]></description>
         <link>http://blogs.onehippo.org/woonsan/2009/06/spring_web_mvc_framework_suppo_1.html</link>
         <guid>http://blogs.onehippo.org/woonsan/2009/06/spring_web_mvc_framework_suppo_1.html</guid>
        
        
         <pubDate>Fri, 05 Jun 2009 17:28:37 +0100</pubDate>
      </item>
            <item>
         <title>Spring framework support in HST-2</title>
         <description><![CDATA[I'd like to explain the current status to support Spring Framework-based developer community.
HST-2 (Hippo Site Toolkit - 2) now supports Spring Framework more than the earlier versions because there are a lot of developers utilizing the framework.

<strong>1. Introduction</strong>

It is very desirable to use spring web framework if the development team is familiar with Spring and they could make better productivity with that.
HST-2 now provides a bridge <CODE>HstComponent</CODE> to <CODE>HstComponent</CODE> beans which are managed by spring web application context.
So, you can define your HstComponent beans in your spring context configuration and inject your existing component to them.
You can see an example in the HST-2 source already if you download the source from the trunk for now.
In the /applications/site/, 'contact-spring' menu will show the example which uses the bridge component. The actual bean is defined in <CODE>/WEB-INF/applicationContext.xml</CODE> like the following:

<code><pre>
  &lt;!-- HST Component Beans --&gt;
  &lt;bean id="contactBean" class="org.hippoecm.hst.components.ContactSpring"&gt;
    &lt;property name="mailSender" ref="mailSender" /&gt;
    &lt;property name="templateMessage" ref="templateMessage" /&gt;
  &lt;/bean&gt;

  &lt;!-- The existing components as an example --&gt;
  &lt;bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage"&gt;
    &lt;property name="to" value="contact@mycompany.com" &gt;
    &lt;property name="subject" value="My opinion" &gt;
  &lt;/bean&gt;
  &lt;bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"&gt;
    &lt;property name="host" value="mail.mycompany.com"/&gt;
  &lt;/bean&gt;
</pre></code>

<strong>2. How it integrates with HST 2.3?</strong>

HST container manages, invokes and aggregates only components based on  <CODE>HstComponent</CODE> interface for some reasons: to support transparent page aggregation, seamless portal integration, etc.
A generic <CODE>HstComponent</CODE> was developed to play a role as a bridge to a bean managed by spring framework.
So, the generic bridge <CODE>HstComponent</CODE> will delegate all invocation to the actual HstComponent bean managed by spring framework.

<strong>3. What the benefits are? What the drawbacks are?</strong>

Spring-based developers can use full cool functionalities of spring framework like Dependency Injection, out-of-box spring components to support enterprise computing like JDBC template, transaction management and enterprise messaging, AOP techniques, Web Service support, Various view technologies, etc.
<CODE>HstComponent</CODE> can be fully integrated with these rich spring supports.

The Spring bridge <CODE>HstComponent</CODE> invokes directly the actual bean, so there's no performance degrade and functional shortage here.

Of course, it looks a little bit different from the original spring web mvc pattern. The differences you can think of are originally from the differences of goals: HST-2 is to support transparent page aggregation and seamless portal integration, etc.
Because HST-2 container aggregates multiple components in one page, the action phase should be separated from the rendering phase of all components. This means that HST container's aggregation should imply the <EM>PRG</EM> pattern internally. [1]
Therefore, in a HST component, the *controlling* logic should be separated in doAction() and in doBeforeRender(). Also, those two separate phase should have separate request life cycles.

Anyway, once you get accustomed to <CODE>HstComponent</CODE> request lifecycles, you can easily use the pattern with <CODE>HstComponent</CODE> in the spring framework best practices.
For example, spring developers can write controller logics in <CODE>HstComponent</CODE>s and use any kinds of view technologies to build view pages.

On the other hand, somebody can ask me, 'why can't spring webmvc manage the request handling directly itself? why HST container controls the request at the frontend and it dispatches to spring web mvc later?'
The answers can be like the following:
  - HST manages the page aggregation like portal. If you want to use that kind of page aggregation and you don't want to care its detail except of focusing on making each component block, you need to hand it over to HST container.
    HST container promises that it would provide transparent page aggregation, sitemap/sitemenu and seamless portal integration.
  - If you don't want that kind of page aggregation, you can still use some HST components as out-of-box components such as JCR session pooling repository, event listener (observation), search helper, etc. by definining those components in your spring configuration.

<strong>4. What's next?</strong>

I think this spring bean bridging solution is very useful for many use cases. However, some Spring Web MVC framework-proficient developers can complain that they cannot use some kind of <EM>handler mappings</EM> for each controller.
I agree that this simple bridging solution could not be enough for the developers.
I think we can go further by providing *HST component phase parameter handler mapping*. :-) 
This can be regarded as *HST Spring Web MVC*.
Sounds like <CODE>org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping</CODE> of Spring Portlet Web MVC?
Yes, because the request life cycle of HST component is very similar to portlet, almost similar design can be adopted.
However, I think there are some better features in <EM>HST Spring Web MVC</EM> than <EM>Spring Portlet Web MVC</EM>. One is the fact that Hst Component controller in <EM>HST Spring Web MVC</EM> might not be tied to portlet api directly.
Anyway, I'd like to look into this improvement soon. Please stay tuned!


[1] <a href="http://en.wikipedia.org/wiki/Post/Redirect/Get">http://en.wikipedia.org/wiki/Post/Redirect/Get</a>

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-9457822-1");
pageTracker._trackPageview();
} catch(err) {}</script>]]></description>
         <link>http://blogs.onehippo.org/woonsan/2009/04/spring_framework_support_in_hs_1.html</link>
         <guid>http://blogs.onehippo.org/woonsan/2009/04/spring_framework_support_in_hs_1.html</guid>
        
        
         <pubDate>Mon, 20 Apr 2009 11:04:55 +0100</pubDate>
      </item>
      
   </channel>
</rss>

