View Hooks provide a means to define extension points in JSP and FreeMarker templates. Project Extensions can make use of these extension points to add their own functionality at the respective locations in the resulting website without having to change the core templates.
In the past you either directly implemented the functions in your content beans and templates or you implemented a plugin by means of an Section 5.2, “Aspects” to achieve this. Both solutions are feasible however content beans and Aspects should only accomplish basic tasks based on the content defined by the editor and View Hooks are more loosely coupled and as such improve your project's code quality.
Required Configuration
View Hooks are not enabled by default. In order to use them in your templates you have to append the Spring
bean viewHookEventView
to the list of existing
Section 4.3.3.1, “View Repository”.
<customize:append id="customProgrammedViews" bean="programmedViews"> <map> <entry key="com.coremedia.objectserver.view.events.ViewHookEvent" value-ref="viewHookEventView"/> </map> </customize:append>
Instead of using a customizer you can also add the viewHookEventView
to the existing map
of programmedViews
.
Example Implementation
Assuming there is a content bean CMArticle
which represents an editorial article and a corresponding
template called CMArticle.detail.jsp
. The template defines an extension point with the id
articleEnd
.
<div class="detailView"> <h1><c:out value="${self.title}"/></h1> <cm:include self="${self.text}" view="detailText"/> <cm:hook id="articleEnd "self="${self}"/> </div>
A project extension now wants to add a list of user generated comments at the end of the article. Instead of
changing the CMArticle.detail.jsp
in the core modules directly, you only need to add an
implementation of the
com.coremedia.objectserver.view.events.ViewHookEventListener to the Spring application context.
An implementation of this interface could look as follows:
@Named public class CommentsViewHookEventListener implements ViewHookEventListener<CMArticle> { @Inject private CommentsService commentsService; @Override public RenderNode onViewHook(ViewHookEvent<CMArticle> event) { if("articleEnd".equals(event.getId())) { CommentsResult commentsResult = commentsService.getCommentsResult(event.getBean()); return new RenderNode(commentsResult); } return null; } @Override public int getOrder() { return DEFAULT_ORDER; } }
The resulting
com.coremedia.objectserver.view.RenderNode contains the object and the view name that will finally be
passed to the Section 4.3.3.2, “View Lookup”. The view lookup is responsible for
identifying and rendering the corresponding template or programmed view.
Returning null
tells the application to skip this listener.