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.