HstComponent Java Class

A HstComponent can be invoked by a HstComponent container during three different request lifecycle phases: ACTION, RESOURCE and RENDER. A HstComponent is not thread-safe because the HST container creates one instance to serve concurrent requests. This means that in general you do not want to store instance variables in a HstComponent class, and if you do so, make sure that it support concurrent access. Storing request specific objects in an instance variable of a HstComponent does in general indicate a concurrency issue.

More specific:

The HST instantiates a HstComponent only once per hst component configuration. Thus assume you have 2 hst component configuration (below hst:myproject/hst:configurations/{myproject}/hst:pages or hst:myproject/hst:configurations/{myproject}/hst:components) that both have a hst:componentclassname that is com.myproject.components.Detail, then Detail.java will be instantiated twice.

An HstComponent implementation must implement the following interface:

public interface HstComponent {
    
    /**
     * Allows the component to initialize itself
     *
     * @param servletContext the servletConfig of the HST container servlet
     * @param componentConfig the componentConfigBean configuration
     * @throws HstComponentException
     */
    void init(ServletContext servletContext, ComponentConfiguration componentConfig) throws HstComponentException;

    /**
     * This method is invoked before {@link #doBeforeRender(HstRequest, HstResponse)} method to give an HstComponent
     * a chance to <i>prepare</i> any business service invocation(s).
     * This method can be implemented to prepare business content objects by creating asynchronous jobs in parallel
     * without having to wait each component's {@link #doBeforeRender(HstRequest, HstResponse)} execution sequentially.
     *
     * @param request
     * @param response
     * @throws HstComponentException
     */
    default void prepareBeforeRender(HstRequest request, HstResponse response) throws HstComponentException {
    }

    /**
     * Allows the component to do some business logic processing before rendering
     *
     * @param request
     * @param response
     * @throws HstComponentException
     */
    void doBeforeRender(HstRequest request, HstResponse response) throws HstComponentException;
    
    /**
     * Allows the component to process actions
     *
     * @param request
     * @param response
     * @throws HstComponentException
     */
    void doAction(HstRequest request, HstResponse response) throws HstComponentException;
    
    /**
     * Allows the component to do some business logic processing before serving resource
     *
     * @param request
     * @param response
     * @throws HstComponentException
     */
    void doBeforeServeResource(HstRequest request, HstResponse response) throws HstComponentException;
    
    /**
     * Allows the component to destroy itself
     *
     * @throws HstComponentException
     */
    void destroy() throws HstComponentException;

    /**
     * Returns the ComponentConfiguration for this component or <code>null</code>
     * if not implemented by a subclass
     */
    default ComponentConfiguration getComponentConfiguration() {
        return null;
    }
    
}

The most important methods are #doBeforeRender and #doAction as these are typically the only methods a custom Component implements/overrides.

In practice, a custom Component always extends the org.hippoecm.hst.component.support.bean.BaseHstComponent which in turns extends org.hippoecm.hst.core.component.GenericHstComponent. The GenericHstComponent only implements the interface methods without adding specific behavior. If there is no hst:componentclassname property defined, the GenericHstComponent will be used. The BaseHstComponent does not add behavior for doBeforeRender, doAction or doBeforeServeResource, but does add lots of common utilities. Note that #getComponentConfiguration is already implemented in the GenericHstComponent and in general never needs to be overridden.

Did you find this page helpful?
How could this documentation serve you better?