Extend Common Component with a Do-Before-Render Extension

Introduction

Goal

Plug additional code into CommonComponent so that all components extending CommonComponent execute this code before they are rendered.

Background

All standard components provided by Essentials are descendants of the abstract class org.onehippo.cms7.essentials.components.CommonComponent. This CommonComponent class provides an extension point where additional code can be plugged into its doBeforeRender method. Consequently all standard components (and any custom component extending CommonComponent) will execute this additional code before it is rendered.

The extension point is provided as the interface org.onehippo.cms7.essentials.components.ext.DoBeforeRenderExtension. By default a no-op implementation (org.onehippo.cms7.essentials.components.ext.NoopDoBeforeRenderExtension) is configured. 

Example

Use Case

The use case demonstrated by the example on this page is based on a Bloomreach Experience Manager project created from the Maven Archetype with the Blog feature added.

The Blog feature includes a "blog categories" key-value list. Such a key-value list is managed as a document in the CMS and can be accessed from within the delivery tier through a ValueListManager configured as Spring bean. The setup application provides a UI to create such configuration. The generated configuration can be found in your project's site module at:

site/components/src/main/resources/META-INF/hst-assembly/overrides/valueListManager.xml

  <bean id="org.onehippo.forge.selection.hst.manager.ValueListManager" class="org.onehippo.forge.selection.hst.manager.DefaultValueListManager"> 
    <constructor-arg> 
      <map> 
        <!--<entry key="name" value="/absolute/repository/path"/>-->  
        <entry key="categories" value="/content/documents/myproject/blog/blog-categories"/>
      </map> 
    </constructor-arg> 
  </bean>

You want the categories key-value list to be readily available as request attribute to any rendering template. One way to achieve this is through a DoBeforeRenderExtension: a custom piece of code that is executed by every component before it is rendered.

What about performance? 

Since a DoBeforeRenderExtension is executed by every component extending CommonComponent there is a potential for performance degradation. In this use case the key-value list is actually already being cached in memory. In other use cases it may be beneficial to cache retrieved data locally in the HstRequestContext object.

Implement DoBeforeRenderExtension Interface

Create a new class org.example.extensions.CategoriesDoBeforeRenderExtension which implements DoBeforeRenderExtension.

Implement the execute method so that it retrieves the ValueListManager bean, gets the categories value list and stores it in a request attribute categories.

site/components/src/main/java/org/example/extensions/CategoriesDoBeforeRenderExtension.java

package org.example.extensions;

import org.hippoecm.hst.content.beans.standard.HippoBean;
import org.hippoecm.hst.core.component.HstRequest;
import org.hippoecm.hst.core.component.HstResponse;
import org.hippoecm.hst.site.HstServices;
import org.onehippo.cms7.essentials.components.CommonComponent;
import org.onehippo.cms7.essentials.components.ext.DoBeforeRenderExtension;
import org.onehippo.forge.selection.hst.contentbean.ValueList;
import org.onehippo.forge.selection.hst.manager.ValueListManager;
import org.onehippo.forge.selection.hst.util.SelectionUtil;

public class CategoriesDoBeforeRenderExtension implements DoBeforeRenderExtension {

    @Override
    public void execute(final CommonComponent component, final HstRequest request, final HstResponse response) {
        ValueListManager valueListManager = HstServices.getComponentManager().getComponent(ValueListManager.class.getName());
        HippoBean siteContentBaseBean = request.getRequestContext().getSiteContentBaseBean();
        ValueList categoriesValueList = valueListManager.getValueList(siteContentBaseBean, "categories");
        if (categoriesValueList != null) {
            request.setAttribute("categories", SelectionUtil.valueListAsMap(categoriesValueList));
        }
    }

}

Configure DoBeforeRenderExtension Spring Bean

In the Spring configuration replace the default configured NoopDoBeforeRenderExtension by org.example.extensions.CategoriesDoBeforeRenderExtension .

site/components/src/main/resources/META-INF/hst-assembly/overrides/hippo-essentials-spring.xml

  <bean id="org.onehippo.cms7.essentials.components.ext.DoBeforeRenderExtension"
        class="org.example.extensions.CategoriesDoBeforeRenderExtension"/>

Use the Key-Value List in a Template

Now any component that uses a component class extending CommonComponent has a request attribute categories (containing the key-value list as java.util.Map) available to its rendering template.

For example to render a blog post's categories on the blog overview page you could add the following to the blog-list-.ftl template:

repository-data/webfiles/src/main/resources/site/freemarker/hstdefault/blog/blog-list.ftl

<ul>
  <#list item.categories as category>
    <li>${categories[category]}</li>
  </#list>
</ul>
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?