Saturday, May 15, 2021

How to write the a Sling Model, OSGI Service and bean class In AEM 6.5


1.   Reading Single valued properties(Simple)

This is the most common task that every AEM developer has to encounter to write a sling model to perform some operation on component, that business logic at backend. Here I will show you how to read simple values from dialog in sling model and make operations on it as required.

Step 1 : Creating Model (interface)

 

@ConsumerType

public interface sampleModel extends ComponentExporter {

   

    /**

     * get Sample Model Bean

     *

     * @return SampleModelBean properties

     */

    SampleModelBean getSampleModelBean();

   

    /**

     * Check if the selector is available

     *

     * @return boolean is selector available in the url

     */

    boolean isSelectorAvailable();

}

 

Step 2: Creating Bean Class to read an return values

 

public class SampleModelBean {

   

    private String title;

   

    private String description;

   

   

    public SampleModelBean() {

   

    }

   

    /**

     * Constructor for initializing the instance

     */

   

    public SampleModelBean(String title, String description) {

        this.title = title;

        this.description = description;

    }

 

    /**

     * Title

     *

     * @return String title

     */

    public String getTitle() {

        return title;

    }

   

    /**

     * Description

     *

     * @return String description

     */

    public String getDescription() {

        return description;

    }

 

Step 3 : Creating an implementation class to Implement business logic as required

@Model(adaptables = {SlingHttpServletRequest.class}, adapters = {SampleModel.class,

                ComponentExporter.class, }, resourceType = Constants.SAMPLE_COMPONENT_RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)

@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)

public class SampleModelImpl extends CommonFieldsImpl implements SampleModel {

 

    @ValueMapValue(name = Constants.TITLE)

    private String title;

   

    @ValueMapValue(name = SOIConstants.DESCRIPTION)

    private String description;

 

    @SlingObject

    private ResourceResolver resourceResolver;

   

    private boolean isSelectorAvailable;

   

    private ServiceModelBean serviceModelBean;

 

    /**

     * Initialize the variables with business logic

     */

    @PostConstruct

    private void initModel() {

   

Resource resource = resourceResolver.getResource(somePath);

            if (!ResourceUtil.isNonExistingResource(resource)) {

                someMethod(resource);

            }

    }

      

    private void someMethod(Resource resource) {

       Resource masterRes = ResourceUtils.getChildResourceWithPath(resource, constants.MASTER_PATH);

        if(!ResourceUtil.isNonExistingResource(masterRes)) {

            ValueMap vMap = ResourceUtils.getChildResourceWithPath(resource, constants.MASTER_PATH).getValueMap();

            if (MapUtils.isNotEmpty(vMap)) {

              title = MapUtils.getString(vMap, constants.TITLE, StringUtils.EMPTY);

              description = MapUtils.getString(vMap, constants.DESCRIPTION, StringUtils.EMPTY);

}

this.sampleModelBean = new SampleModelBean(title, description);

   }

}

 

     /**

     * Returns the Title.

     *

     * @return title

     */

    public String getTitle() {

        return title;

    }

   

    /**

     * Returns the Description.

     *

     * @return description

     */

    public String getDescription() {

        return decription;

    }

    /**

     * Get the sampleModelBean

     *

     * @return sample model bean

     */

    @Override

    public SampleModelBean getSampleModelBean() {

        return this.sampleModelBean;

    }

   

    /**

     * Is the selector available in the url

     *

     * @return boolean is selector available

     */

    @Override

    public boolean isSelectorAvailable() {

        return this.isSelectorAvailable;

    }

   

    /**

     * Gets the exported type.

     *

     * @return the exported type

     */

    @Override

    public String getExportedType() {

        return constants.SAMPLE_COMPONENT_RESOURCE_TYPE;

    }

}

 

Constants file

 

  /** The Constant service component resource type */

    public static final String SERVICE_COMPONENT_RESOURCE_TYPE = "sampleproject/components/content/v1/sample";

 

  /** The constant title */

    public static final String TITLE = "title";

 

  /** The constant title */

    public static final String DESCRIPTION = "description";

 

 

sample.html file

<div data-sly-use.sample="com.adobe.aem.sample.core.models.SampleModel"

   data-sly-use.templates="core/wcm/components/commons/v1/templates.html"

   data-sly-test.hasContent="${sample.sampleModelBean.title}">

<h1 class="cmp-title__text">${sample.sampleModelBean.title}</h1>

   <p>${sample.sampleModelBean.description @context = 'html'}</p>

</div>

<sly data-sly-call="${templates.placeholder @ isEmpty =!hasContent}"></sly>

 

 

2.   Reading multivalued properties from dialog(Complex)

 

This is the most common task that every AEM developer has to encounter to write a sling model to perform some operation on component, that business logic at backend. But this is complex as here I am reading the values from multifield.

Step 1: Creating Model (interface)

@ConsumerType

public interface SampleModel {

/**

     * Get the id

     *

     * @return id

     */

    String getId();

   

    /**

     * Get the class

     *

     * @return class

     */

    String getClassValue();

 

    /**

     * Get the sample data

     *

     * @return sample data

     */

    List<SampleListParentItem> getSampledata();

   

    /**

     * Get the sample social link data

     *

     * @return sample sociallinkdata

     */

    List<SampleSocialLinkItemBean> getSociallinkdata();

}

 

Step 2: Creating SampleListParentItem Class

 

public class SampleListParentItem {

   

    private List<SampleListItem> sampleItems;

   

    //Constructor to initialize value

 

    public SampleListParentItem (List<SampleListItem> sampleItems) {

        this.sampleItems = sampleItems;

    }

  

//getter

    public List<SampleListItem> getSampleItems() {

        return sampleItems;

    }

   

//setter

    public void setSampleItems(List<SampleListItem> sampleItems) {

        this.sampleItems = sampleItems;

    }   

}

 

Step 3: Creating class SampleListItem

 

@ConsumerType

public class SampleListItem {

   

    private String linkText;

    private String linkPath;

    private boolean isOpenInNewTab;

   

    public SampleListItem() {

       

    }

   

    public SampleListItem(String linkText, String linkPath, Boolean openInNewtab) {

        this.linkText = linkText;

        this.linkPath = linkPath;

        this.isOpenInNewTab = openInNewtab;

    }

   

    public String getLinkText() {

        return linkText;

    }

   

    public void setLinkText(String linkText) {

        this.linkText = linkText;

    }

   

    public String getLinkPath() {

        return linkPath;

    }

   

    public void setLinkPath(String linkPath) {

        this.linkPath = linkPath;

    }

   

    public boolean isOpenInNewTab() {

        return isOpenInNewTab;

    }

   

    public void setOpenInNewTab(boolean isOpenInNewTab) {

        this.isOpenInNewTab = isOpenInNewTab;

    }

   

 

Step 4: Creating Class SampleSocialLinkItemBean

 

public class SampleSocialLinkItemBean {

    private String linkText;

    private String linkPath;

    private String linkLabel;

   

    public SampleSocialLinkItemBean() {

       

    }

   

    public SampleSocialLinkItemBean(String linkText, String linkPath, String linkLabel) {

        this.linkText = linkText;

        this.linkPath = linkPath;

        this.linkLabel = linkLabel;

    }

   

    public String getLinkText() {

        return linkText;

    }

   

    public void setLinkText(String linkText) {

        this.linkText = linkText;

    }

   

    public String getLinkPath() {

        return linkPath;

    }

   

    public void setLinkPath(String linkPath) {

        this.linkPath = linkPath;

    }

   

    public String getLinkLabel() {

        return linkLabel;

    }

   

    public void setLinkLabel(String linkLabel) {

        this.linkLabel = linkLabel;

    }

}

 

Like this we can read values and call those values on page using HTL

 

Sample.htl

 

<sly data-sly-use.sample="${'com.adobe.aem.sample.core.models.SampleModel'}"/>

 

id="${sample.id}" class="${sample.classValue}

<sly data-sly-list.sampleItems="${sample.sampledata}"/>

<li>

<a href="${sampleItem.linkPath}" target="${sampleItem.isOpenInNewTab?'_blank':''}">${sampleItem.linkText}

</a>

</li>

</sly>