Spring-Managed HST Components
Container Level Support for Spring Framework Managed HST Components
Since Bloomreach Experience Manager 11, HST Container can get a reference to an HST Component bean maintained by Spring Framework ApplicationContext and use the bean, instead of creating an object by itself from hst:componentclassname property value.
Suppose you have the following HST Component configuration in HST configurations in repository:
/content: jcr:primaryTYpe: hst:component hst:componentclassname: org.hippoecm.hst.demo.components.Search
Until Bloomreach Experience Manager 10.x, HST Container creates an object by the class name (org.hippoecm.hst.demo.components.Search in this example).
Since Bloomreach Experience Manager 11, HST Container looks up its ComponentManager (internally backed by Spring Framework ApplicationContext) first to find a bean named by the class name (org.hippoecm.hst.demo.components.Search in this example). If a bean by the name is found, then HST Container uses the bean instead of creating a new object. If not found, it creates an HST Component object by itself like it does in Bloomreach Experience Manager 10.x or earlier versions.
By letting Spring Framework maintain your HST Component beans, you may take advantage of many good features of Spring Framework such as AOP techniques on your HST Components.
How-to with A Simple Example in Hippo Test Suite
If you want to see a demo, build and run the demo in the Hippo Test Suite project. The example is available in our source repository: Hippo Test Suite.
Next, click on the Search link on the left menu of the example website (http://localhost:8080/site/search). You will see a page containing search forms.
HST Component Class with Spring Framework Annotations
For the search page, the following HST Component was implemented in the Hippo Test Suite project:
components/src/main/java/org/hippoecm/hst/demo/components/Search.java
package org.hippoecm.hst.demo.components; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; /** * This HstComponent must be annotated with {@link Service}. * <P> * Note: HstComponent bean must always be {@link ConfigurableBeanFactory.SCOPE_PROTOTYPE} like this example. * Otherwise, thread-safety issue can occur due to a singleton bean instance of HstComponent. * In this example, the bean name (set by {@link Service} annotation) is set to the FQCN of this component class * because the component classname (as configured by @hst:componentclassname property) can be scanned for component * parameters in many other locations (e.g, Channel Manager), unless you explicitly set the @hst:parametersinfoclassname * property which has been supported since v12.1. * </P> */ // If you skip the value in @Component annotation, the logical bean name will be a camel-cased simple class name: "search", // which should be set to the @hst:componentclassname property instead of the FQCN. @Component(DemoConstants.COMPONENT_BASE_PACKAGE + ".Search") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Search extends AbstractSearchComponent { // -->8-->8-- }
The Search class now has several Spring Framework annotations. Those annotations are needed when you want to take advantage of Spring Framework Automatic Component Scanning feature:
- @Component annotation is required.
- In the earlier versions than Bloomreach Experience Manager 12.1, the value of @Component annotation should be set to the FQCN of the component class (which is the same as @hst:componentclassname property value) for the following reasons:
- If the value is skipped, you must set @hst:componentclassname property to the auto-generated logical Spring bean name, a camel-cased simple class name. e.g, "searchComponent" instead of "org.example.components.SearchComponent".
- The component parameters information cannot be automatically scanned (while using Channel Manager for instance) because @hst:componentclassname property value doesn't have a FQCN value.
- Since Bloomreach Experience Manager 12.1, you may skip the value of @Component annotation in the following conditions:
- You must set @hst:componentclassname property to the auto-generated logical Spring bean name, a camel-cased simple class name. e.g, "searchComponent" instead of "org.example.components.SearchComponent".
- You should set @hst:parametersinfoclassname property (since v12.1) to specify the FQCN of the component parameters info interface (which is equivalent to the type attribute of org.hippoecm.hst.core.parameters.ParametersInfo annotation in the component class. So, the component parameters info can be scanned by the new @hst:parametersinfoclassname property value if needed (while using Channel Manager for instance).
- @Scope annotation is required and it must be set to ConfigurableBeanFactory.SCOPE_PROTOTYPE. Otherwise, you could meet severe thread-safety issues or parameter collision issues.
Enabling Spring Framework Automatic Component Scanning
Now, we need to enable Spring Framework Automatic Component Scanning in initializing HST Container Component Manager. You can simply add the following in an XML file under site/src/main/resources/META-INF/hst-assembly/overrides/ folder. In the Hippo Test Suite project, it is included in components/src/main/resources/hst-assembly/overrides/components.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- (HST)Components Annotation Scanning --> <context:component-scan base-package="org.hippoecm.hst.demo.components" /> <-- SNIP --> </beans>
When HST Container and its ComponentManager are initialized, Spring Framework will scan all the available components under the package org.hippoecm.hst.demo.components and register all the scanned beans. In this specific example, it will register a bean named org.hippoecm.hst.demo.components.Search, and later when HST Container needs to invoke the Search HST Component (as configured in the component configuration in the repository), it simply gets a reference to the existing bean instead of creating a new object by the class name by itself.
Summary
Since Bloomreach Experience Manager 11, HST Container can get a reference to a bean maintained by Spring Framework, instead of creating an object by itself. In the perspective of HST Component configurations in the repository, there is no change from the traditional way of configuring component class name with hst:componentclassname property value. However, HST Container looks up a bean by the hst:componentclassname property value first from the ComponentManager (backed by Spring Framework ApplicationContext). If found, it simply uses the bean. Otherwise, it creates a new object like it does in CMS 10 or earlier versions.
When you want to take advantage of Spring Framework Automatic Component Scanning feature, you should use @Component and @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) annotations and enable the automatic scanning by adding <context:component-scan base-package="..." /> in an overriding bean assembly XML file.
By letting Spring Framework maintain your HST Component beans, you may take advantage of many good features of Spring Framework such as AOP techniques on your HST Components. See the examples in the Hippo Test Suite project for more detail.