Page tree
Skip to end of metadata
Go to start of metadata

Magnolia has a feature called auto generation that allows for generating components into areas to pre-populate the page.


Auto generation is supported by Blossom as of 3.0.2 using the @AutoGenerator annotation. See the documentation on auto generation for more details. This page is now obsolete but kept here for the convenience of users on previous versions.



At the moment this feature is however not directly available in Blossom. This page describes a solution for making use of the feature until Blossom provides it out of the box.

This is an example of how it is used. The area implements an interface AutoGeneratingArea and implements the generate() method. There it has the opportunity to add components to the area. In this case it adds a node, sets the template to use and adds properties for its content.

@Area("promos")
@Controller
@AvailableComponentClasses({TextComponent.class})
public static class PromosArea implements AutoGeneratingArea {

    @TabFactory("Content")
    public void contentTab(TabBuilder tab) {
        tab.addEdit("heading", "Heading", "");
    }

    @RequestMapping("/mainTemplate/promos")
    public String render() {
        return "areas/promosArea.ftl";
    }

    @Override
    public void generate(Node areaNode) throws RepositoryException {
        if (!areaNode.hasNode("component")) {
            Node text = areaNode.addNode("text", NodeTypes.Component.NAME);
            text.setProperty(NodeTypes.Renderable.TEMPLATE, "acmeModule:components/text");
            text.setProperty("heading", "Auto generated");
            text.setProperty("text", "<p>This text was autogenerated!</p>");
            areaNode.getSession().save();
        }
    }
}

To enable it add this to your blossom-servlet.xml.

<bean class="info.magnolia.module.blossom.template.TemplateExporter">
  <property name="templateDefinitionBuilder">
    <bean class="info.magnolia.module.blossom.autogeneration.AutoGenerationTemplateDefinitionBuilder" />
  </property>
</bean>

Copy these two classes to your project. The first is the interface you implement in your areas and the second performs the callback to your area controller when it is rendered. 

package info.magnolia.module.blossom.autogeneration;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

public interface AutoGeneratingArea {

    void generate(Node areaNode) throws RepositoryException;
}


package info.magnolia.module.blossom.autogeneration;

import info.magnolia.module.blossom.dispatcher.BlossomDispatcher;
import info.magnolia.module.blossom.template.BlossomAreaDefinition;
import info.magnolia.module.blossom.template.DetectedHandlersMetaData;
import info.magnolia.module.blossom.template.HandlerMetaData;
import info.magnolia.module.blossom.template.TemplateDefinitionBuilder;
import info.magnolia.rendering.engine.RenderException;
import info.magnolia.rendering.generator.Generator;
import info.magnolia.rendering.template.AutoGenerationConfiguration;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AutoGenerationTemplateDefinitionBuilder extends TemplateDefinitionBuilder {

    @Override
    protected BlossomAreaDefinition buildAreaDefinition(BlossomDispatcher dispatcher, DetectedHandlersMetaData detectedHandlers, HandlerMetaData area) {
        BlossomAreaDefinition definition = super.buildAreaDefinition(dispatcher, detectedHandlers, area);
        if (AutoGeneratingArea.class.isAssignableFrom(area.getHandler().getClass())) {
            definition.setAutoGeneration(new BlossomAutoGenerationConfiguration((AutoGeneratingArea) area.getHandler()));
        }
        return definition;
    }

    public static class BlossomAutoGenerationConfiguration implements AutoGenerationConfiguration {

        private final AutoGeneratingArea handler;

        public BlossomAutoGenerationConfiguration(AutoGeneratingArea handler) {
            this.handler = handler;
        }

        public AutoGeneratingArea getHandler() {
            return handler;
        }

        @Override
        public Map<String, Object> getContent() {
            return null;
        }

        @Override
        public Class<Generator<AutoGenerationConfiguration>> getGeneratorClass() {
            return (Class) BlossomGenerator.class;
        }
    }

    public static class BlossomGenerator implements Generator<BlossomAutoGenerationConfiguration> {

        private final static Logger log = LoggerFactory.getLogger(BlossomGenerator.class);

        private Node areaNode;

        public BlossomGenerator(Node areaNode) {
            this.areaNode = areaNode;
        }
 
        @Override
        public void generate(BlossomAutoGenerationConfiguration configuration) throws RenderException {
            try {
                configuration.getHandler().generate(areaNode);
            } catch (RepositoryException e) {
                log.error("Failed to autogenerate components for [{}]", configuration.getHandler().getClass().getName(), e);
            }
        }
    }
}