Tuesday, June 20, 2023

OSGIConfigs

 OSGI COnfigs

//interface

package com.mysite.core.models;

public interface OSGIconfig {
public String getServiceName();
public int getServiceCount();
public boolean isLiveData();
public String getRunModes();
}



//IMPL
package com.mysite.core.models.impl;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.osgi.service.metatype.annotations.Option;

import com.mysite.core.models.OSGIconfig;

@Component(service=OSGIconfig.class, immediate = true)
@Designate(ocd=OSGIConfigImpl.ServiceConfig.class)
public class OSGIConfigImpl implements OSGIconfig {

@ObjectClassDefinition(name="SurgeSoftware OSGI Configuration")
public @interface ServiceConfig{
@AttributeDefinition(
name="Service Name",
description="Enter the Service Name",
type=AttributeType.STRING)
public String getServiceName() default "Surge Service";
@AttributeDefinition(
name="Service Count",
description="Count the service",
type=AttributeType.INTEGER)
public int getServiceCount() default 5;

@AttributeDefinition(
name="Live Data",
description="Check this to get live data",
type=AttributeType.BOOLEAN)
public boolean isLiveData() default true;
@AttributeDefinition(
name="Run Modes",
description="Select the Run Modes",
type=AttributeType.STRING,
options= {
@Option(label="Author",value="author"),
@Option(label="Publish",value="publish"),
@Option(label="Both",value="both")
})
public String getRunModes() default "both" ;
}
private String serviceName;
private int serviceCount;
private boolean isLive;
private String runModes;
@Activate
protected void activate(ServiceConfig config)
{
serviceName=config.getServiceName();
serviceCount=config.getServiceCount();
isLive=config.isLiveData();
runModes=config.getRunModes();
}
@Override
public String getServiceName() {
return serviceName;
}

@Override
public int getServiceCount() {
return serviceCount;
}

@Override
public boolean isLiveData() {
return isLive;
}

@Override
public String getRunModes() {
return runModes;
}

}


//Sightly

<h3> OSGI Configs component </h3>

<sly data-sly-use.osgiconfigs="com.mysite.core.models.OSGIconfig"/>

<div> Service Name: ${osgiconfigs.serviceName}</div>

<div> Service Count: ${osgiconfigs.serviceCount}</div>

<div> Is Live data: ${osgiconfigs.isLiveData}</div>

<div> Run Modes: ${osgiconfigs.runModes}</div>



Tuesday, May 10, 2022

 How To Handle Query Param String and Selectors in Component 

This thing can be used in any component but in my project this requirement was for Title component, where an Author can select and the default behaviour of the component or can select the dynamic type(Query Param/Selector) value.

The dialog looks something like below:





When author selects the dynamic option from the dropdown it will show the hidden tab "Dynamic Settings" and under that we have 2 options in the drop down :
  • Query Param 
  • URL Selector 
To show/hide this tab here is the js:

/*globals Granite,Coral*/
(function ($, document) {
    'use strict';
    //used in the dialogs
    $(document).on('dialog-ready', function () {
      init()
    });

    //refresh the page on dynamic queryParam selection
    $(document).on('dialog-success', function () {
      var modeselector = document.querySelectorAll('.tabs__show-hide');
      var typeselector = document.querySelectorAll('.core-title-dynamic-type');
      if (modeselector.length !== 0 && typeselector.length !== 0) {
        if (modeselector[0].value === 'dynamic'  && typeselector[0].value === 'queryParam') {
          window.location.reload();
        }
      }
    });

    function showHideTabListItems(initial) {
      var coralTab = $("coral-tab[data-foundation-tracking-event*='dynamic settings']");
      if (initial === 'dynamic') {
        coralTab.show();
      } else {
        coralTab.hide();
      }
    }

    function setUpShowHide(selector) {
      Coral.commons.ready(selector, function () {
        selector.on('change', function (e) {
          showHideTabListItems(e.target.value);
        });

        var initial = selector.value;
        showHideTabListItems(initial);
      })
    }

    function init() {
      Coral.commons.ready(document, function () {
        var selectors = document.querySelectorAll('.tabs__show-hide');
        var coralTab = $("coral-tab[data-foundation-tracking-event*='dynamic settings']");
        if (selectors.length !== 0) {
          if (selectors[0].value === 'default' && coralTab !== undefined) {
            coralTab.hide();
          } else if (selectors[0].value === 'dynamic' && coralTab !== undefined) {
            coralTab.show();
          }
          selectors.forEach(setUpShowHide)
        }
      })
    }
  }

)(Granite.$, document);


The Component Dialog code is here:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured"
    jcr:title="Title"
    sling:resourceType="cq/gui/components/authoring/dialog"
    extraClientlibs="[core.wcm.components.title.v2.editor]"
    trackingFeature="core-components:title:v3">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <tabs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs"
                maximized="{Boolean}true">
                <items jcr:primaryType="nt:unstructured">
                    <properties
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Properties"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        margin="{Boolean}true">
                        <items jcr:primaryType="nt:unstructured">
                            <columns
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                                margin="{Boolean}true">
                                <items jcr:primaryType="nt:unstructured">
                                    <column
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/container">
                                        <items jcr:primaryType="nt:unstructured">
                                            <mode
                                                granite:class="tabs__show-hide"
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                                fieldLabel="Mode"
                                                name="./mode">
                                                <items jcr:primaryType="nt:unstructured">
                                                    <default
                                                        jcr:primaryType="nt:unstructured"
                                                        text="Default"
                                                        value="default"/>
                                                    <dynamic
                                                        granite:hide="${cqDesign.disableDynamic}"
                                                        jcr:primaryType="nt:unstructured"
                                                        text="Dynamic"
                                                        value="dynamic"/>
                                                </items>
                                            </mode>
                                            <title
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldDescription="Leave empty to use the page title."
                                                fieldLabel="Title"
                                                name="./jcr:title"/>                                            
                                            <link
                                                granite:hide="${cqDesign.linkDisabled}"
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/include"
                                                path="/mnt/overlay/core/wcm/components/commons/editor/dialog/link/v1/link/edit/link"/>
                                            <id
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldDescription="HTML ID attribute to apply to the component."
                                                fieldLabel="ID"
                                                name="./id"/>
                                        </items>
                                    </column>
                                </items>
                            </columns>
                        </items>
                    </properties>
                    <dynamic-settings
                        granite:hide="${cqDesign.disableDynamic}"
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Dynamic Settings"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        margin="{Boolean}true"
                        size="L">
                        <items jcr:primaryType="nt:unstructured">
                            <columns
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                                margin="{Boolean}true">
                                <items jcr:primaryType="nt:unstructured">
                                    <column
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/container">
                                        <items jcr:primaryType="nt:unstructured">
                                            <dynamic-type
                                                granite:class="core-title-dynamic-type"
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/select"
                                                fieldLabel="Type"
                                                name="./dynamicType">
                                                <items jcr:primaryType="nt:unstructured">
                                                    <query-param
                                                        jcr:primaryType="nt:unstructured"
                                                        text="Query Param"
                                                        value="queryParam"/>
                                                    <url-selector
                                                        jcr:primaryType="nt:unstructured"
                                                        text="URL Selector"
                                                        value="urlSelector"/>
                                                </items>
                                            </dynamic-type>
                                            <preceding-text
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldDescription="Text before the dynamic text "
                                                fieldLabel="Preceding text"
                                                name="./precedingText"/>
                                            <trailing-text
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldDescription="Text after the dynamic text"
                                                fieldLabel="Trailing text"
                                                name="./trailingText"/>
                                        </items>
                                    </column>
                                </items>
                            </columns>
                        </items>
                        <granite:data
                            jcr:primaryType="nt:unstructured"
                            dep-value="dynamic"/>
                    </dynamic-settings>
                    <styletab
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/include"
                        path="/mnt/overlay/cq/gui/components/authoring/dialog/style/tab_edit/styletab"/>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>










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>