adobe / aem-core-wcm-components

Standardized components to build websites with AEM.
https://docs.adobe.com/content/help/en/experience-manager-core-components/using/introduction.html
Apache License 2.0
723 stars 737 forks source link

Teaser Delegation Pattern Breaks OOTB Image component #2768

Open shehjadkhan-ansys opened 1 month ago

shehjadkhan-ansys commented 1 month ago

Bug Report

Current Behavior We have extended the OOTB teaser component to add few more properties, for which I have used the recommended delegation pattern, but after I added delegation code OOTB image component starts breaking, I cannot open the dialog. First of all, how does OOTB image component gets impacted by extends teaser component this makes me nervous relying on OOTB core components. Apparently, my code is break at line number 34 at mypackage.TeaserImpl.getLink(TeaserImpl.java:34) which is where I am just initiating the delegating with resourceSuperType

Also I have raised this question on Adobe community forum https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/teaser-delegation-pattern-breaks-ootb-image-component/m-p/677190#M169304

Expected behavior/code Extending teaser component using delegation pattern have no impact on functioning of OOTB image component, also in general code related to teaser should not be called while OOTB image component is used, or dialog is tried to be accessed.

Environment AEM version and patch level: AEM as cloud service 24.4. Core Components version: 2.24.6

Possible Solution OOTB teaser component handles the null pointer exception related to getLink method and in general teaser java code does not get invoked while using OOTB image component.

Additional context / Screenshots Below is my code

`// Removed package name for sharing in public

import javax.annotation.PostConstruct;

import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Via; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.apache.sling.models.annotations.via.ResourceSuperType;

import com.adobe.cq.wcm.core.components.commons.link.Link; import com.adobe.cq.wcm.core.components.commons.link.LinkManager; import com.adobe.cq.wcm.core.components.models.Teaser;

import lombok.experimental.Delegate;

//import com.adobe.cq.wcm.core.components.models.datalayer.ComponentData; //import com.adobe.cq.wcm.core.components.models.datalayer.builder.DataLayerBuilder; //import com.adobe.cq.wcm.core.components.util.ComponentUtils;

@Model(adaptables = { SlingHttpServletRequest.class }, adapters = Teaser.class, resourceType = TeaserImpl.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)

public class TeaserImpl implements Teaser {

public final static String RESOURCE_TYPE = "myapp/components/content/teaser";

@Self
@Via(type = ResourceSuperType.class)
@Delegate(excludes = DelegationExclusion.class)
private Teaser delegate;

@SlingObject
private Resource resource;

@Self
protected LinkManager linkManager;

protected Link eyebrowLink;

@ValueMapValue(name = "fileReferenceIcon")
protected String icon;

@ValueMapValue(name = "fileReferenceVideo")
protected String video;

@PostConstruct
private void initModel() {
    this.eyebrowLink = linkManager.get(resource).withLinkUrlPropertyName("eyebrowLink").build();
}

public Link getEyebrowLink() {
    return eyebrowLink;
}

public String getIcon() {
    return icon;
}

public String getVideo() {
    return video;
}

private interface DelegationExclusion {
   // ComponentData getData();
}

/* Sample code for potential customization of data layer

public String getDummyname(){ return "customize data layer"; } @Override public ComponentData getData() { // Use ComponentUtils to verify if the DataLayer is enabled if (ComponentUtils.isDataLayerEnabled(resource)) {

        return DataLayerBuilder.extending(delegate.getData()).asComponent()
                .withTitle(this::getDummyname)
                .build();

    }
    // return null if the Data Layer is not enabled
    return null;
}

*/ }`

Error log (See the forum post for full log message)

Caused by: java.lang.NullPointerException: null

            at mypackage.TeaserImpl.getLink(TeaserImpl.java:34) [mypackage.core:1.0.0.SNAPSHOT]

            at mypackage.TeaserImpl.getLink(TeaserImpl.java:34) [mypackage.core:1.0.0.SNAPSHOT]

            at mypackage.TeaserImpl.getLink(TeaserImpl.java:34) [mypackage.core:1.0.0.SNAPSHOT]

            at com.adobe.cq.wcm.core.components.commons.editor.dialog.inherited.PageImageThumbnail.initModel(PageImageThumbnail.java:115) [com.adobe.cq.core.wcm.components.core:2.24.6]

            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

            at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

            at java.base/java.lang.reflect.Method.invoke(Method.java:566)

            at org.apache.sling.models.impl.ModelAdapterFactory.invokePostConstruct(ModelAdapterFactory.java:989) [org.apache.sling.models.impl:1.6.4]

            at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:789) [org.apache.sling.models.impl:1.6.4]

            ... 411 common frames omitted