loading table of contents...

4.3.3.9. View Hooks

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.