Difference between CMS component Renderer vs Controller
Asked Answered
A

1

6

we're using Hybris v5.7 and I've added an addOn to the project. I would like to render some CMS component and I've found that there are two approaches to populate model object for rendering components: create a child class of DefaultAddOnCMSComponentRenderer or AbstractCMSAddOnComponentController and register it as a bean. Which approach is better? Maybe one of these approaches is outdated?

@Controller
@RequestMapping("/view/MarketingNotificationFormComponentController")
public class MarketingNotificationFormComponentController extends AbstractCMSAddOnComponentController<MarketingNotificationFormComponentModel> {
    @Override
    protected void fillModel(HttpServletRequest request, Model model, MarketingNotificationFormComponentModel component) {
        //populate model here
    }
}

or

public class MarketingNotificationFormComponentRenderer extends DefaultAddOnCMSComponentRenderer<MarketingNotificationFormComponentModel> {
    @Override
    protected Map<String, Object> getVariablesToExpose(PageContext pageContext, MarketingNotificationFormComponentModel component) {
        Map<String, Object> variables = new HashMap<String, Object>();
        // populate model here
        return variables;
    }
}
Angieangil answered 24/5, 2019 at 12:34 Comment(0)
P
3

Which approach is better? Maybe one of these approaches is outdated?

Actually, ComponentController and ComponentRenderer both serve different purposes.

ComponentController is where you can play around incoming requests, manipulate data or some business logic before feeding it to view to render the final output. Here you need to write view in JSP file. Refer CMSPageUrlResolvingController, SimpleResponsiveBannerComponentController, DynamicBannerComponentController etc.

ComponentRenderer is for View. Which means you are going to write view content on the page context directly inside the renderer. Here you do not require to have JSP to render the view. Refer CMSParagraphComponentRenderer, CMSLinkComponentRenderer, ImageMapComponentRenderer etc

If you just want to populate your component attributes to Model, then you don't require to define the custom controller or renderer, OOTB GenericCMSAddOnComponentController will take care of it.

Please note, If there is a respective custom componentRenderer already defined, then componentContoller won't be invoked, having said that custom componentRenderer and custom componentContoller can't work together.


How custom component controller or renderer gets invoked internally?

DefaultCMSComponentRendererRegistry.java

@Override
public void renderComponent(final PageContext pageContext, final C component)
{
    final String typeCode = getTypeService().getComposedTypeForClass(component.getClass()).getCode();
    final Map<String, CMSComponentRenderer> renderersMap = getRenderers();
    try
    {
        // To check for any custom renderer present
        if (renderersMap != null && renderersMap.containsKey(typeCode))
        {
            renderersMap.get(typeCode).renderComponent(pageContext, component);
        }
        else
        {
            // If no custom renderer, call GenericViewCMSComponentRenderer
            getDefaultCmsComponentRenderer().renderComponent(pageContext, component);
        }
    }
    catch (final Exception e)
    {
        handleException(e, component);
    }
}

GenericViewCMSComponentRenderer.java
To invokes the custom component controller or default controller

    @Override
    public void renderComponent(final PageContext pageContext, final AbstractCMSComponentModel component)
            throws ServletException, IOException
    {

     // ...
     // ...

            final String typeCode = component.getTypeCode();
            String controllerName = typeCode + "Controller";
            if (!getBeanFactory().containsBean(controllerName))
            {
                if (LOG.isDebugEnabled())
                {
                    LOG.debug("No controller defined for ContentElement [" + typeCode + "]. Using default Controller");
                }
                controllerName = DEFAULT_CONTROLLER;
            }

            final String includePath = "/view/" + controllerName;

            if (LOG.isDebugEnabled())
            {
                LOG.debug("Rendering CMS Component type [" + typeCode + "] uid [" + component.getUid() + "], include path ["
                        + includePath + "]");
            }
            renderView(pageContext, component, includePath);

     // ...
     // ...

}
Pray answered 24/5, 2019 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.