Spring Managed HST Components
Container Level Support for Spring Framework Managed HST Components
Since Hippo CMS 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:
<sv:node sv:name="content"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hst:component</sv:value> </sv:property> <sv:property sv:name="hst:componentclassname" sv:type="String"> <sv:value>org.hippoecm.hst.demo.components.Search</sv:value> </sv:property> <!-- SNIP --> </sv:node>
Until Hippo CMS 10.x, HST Container creates an object by the class name (org.hippoecm.hst.demo.components.Search in this example).
Since Hippo CMS 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 Hippo CMS 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 is annotated with {@link Component}. * <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. * Also, the bean name (set by {@link Service} annotation) must be the FQCN of this component class * because the component class is scanned for component parameters in many other locations in HST Container. * </P> */ @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:
- @Scope annotation is required and it must be set to ConfigurableBeanFactory.SCOPE_PROTOTYPE.
- @Component annotation is required and it must be set to the FQCN of the class. You must not set to something else different than the FQCN of the HST component class because the raw class is also scanned by other HST Container components (e.g., for ParametersInfo proxy dynamic generation at runtime). In this specific example, DemoConstants.COMPONENT_BASE_PACKAGE + ".Search" is the same as org.hippoecm.hst.demo.components.Search.
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 as shown above), it simply gets a reference to the existing bean instead of creating a new object by the class name by itself.
Summary
Since Hippo CMS 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 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) and @Component(<FQCN>) 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.