Component Filtering with HstComponentWindowFilter

Introduction

Goal

Apply a filter to the page component hierarchy for certain requests.

Use Case

Assume you have the use case that based on some criteria, for example whether the visitor is authenticated or not, you want to show or hide certain components (blocks) from a page. Assume this very www.onehippo.org as example, and that you do not want to show the Hippo Developer Training component for authenticated visitors. Assume the page configuration used extends from base and looks like :

/hst:abstractpages:
  jcr:primaryType: hst:pages
  /base:
    jcr:primaryType: hst:component
    /main;
      jcr:primaryType: hst:component
      /content:
        jcr:primaryType: hst:component
        /container:
          jcr:primaryType: hst:containercomponent
          /hippo-developer-training:
            jcr:primaryType: hst:containeritemcomponent 

You can write code in every component its class (controller) that does some checks, like whether a visitor is authenticated, and for example if so, have the renderer output nothing. The downside is that the components still have their controller (java class) and view (jsp/freemarker template) invoked.

There is a way more elegant and flexible solution to achieve the above, which effectively just removes any component completely from the tree of components for a single request. 

HstComponentWindowFilter Interface

HstComponentWindowFilter is an interface in the HST API that can be used to achieve the above requirement. It looks as follows:

public interface HstComponentWindowFilter {

    /**
     * @param requestContext
     * @param compConfig     the {@link HstComponentConfiguration} from which <code>window</code> is created
     * @param window         The {@link HstComponentWindow} to decorate
     * @return A {@link HstComponentWindow} instance which can be an enhanced or decorated version of the
     *         <code>window</code>. If the <code>window</code> should be entirely disabled/skipped, <code>null</code>
     *         should be returned
     * @throws HstComponentException
     */
    HstComponentWindow doFilter(HstRequestContext requestContext,
                                HstComponentConfiguration compConfig,
                                HstComponentWindow window) throws HstComponentException;

}

Note from javadoc above the subtle difference between returning from doFilter:

  1. null 
  2. The HstComponentWindow window after invoking window.setVisible(false) 

Example Implementation

Below is an example implementation of HstComponentWindowFilter that checks whether there is a component parameter hide-for-authenticated-users = true, and if there is one, and the visitor is authenticated, the component gets completely skipped: 

public class AuthenticatedBasedComponentFilter implements HstComponentWindowFilter {
    @Override
    public HstComponentWindow doFilter(final HstRequestContext requestContext,
                                       final HstComponentConfiguration compConfig,
                                       final HstComponentWindow window) throws HstComponentException {

        Boolean hideForAuthenticatedUsers = (Boolean)ConvertUtils.convert(
                compConfig.getParameters().get("hide-for-authenticated-users"), Boolean.class);
        if (!hideForAuthenticatedUsers) {
            return window;
        }
        Subject subject = requestContext.getSubject();
        if (subject == null) {
            return window;
        }
        return null;
    }
}

Inject the Filter in the Request Processing

After you have implemented your HstComponentWindowFilter you need to add some Spring configuration in your META-INF/hst-assembly/overrides to make sure the filtering is applied:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="org.hippoecm.hst.core.container.HstComponentWindowFilter.list"/>
    <property name="targetMethod" value="add"/>
    <property name="arguments">
      <bean class="org.example.AuthenticatedBasedComponentFilter"/>
    </property>
  </bean>

</beans>

This is all, now you have your custom component filtering enabled.

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?