December 28, 2020
Estimated Post Reading Time ~

AEM Sling Model Constructor Injection

Sling Models field injection, @inject, are used to support injection of AEM Library-specific context objects. However, there is an alternative way to inject AEM objects into Sling Models, and its called Constructor Injection.

The benefits of Sling Model Constructor Injection:
  • Does not store the injection references to the adaptable.
  • Since it does not store injection references to the adapted object, the result of the adapted object has a smaller memory byte size.
  • Reducing AEM application consumption
1. Sling Model using Field Injection Example:

The example below illustrates a Sling Model field injection of 35 different AEM objects to be available for the adapted object. This example displays how specific Sling Model annotations are being used, references are stored to the adapted object.

MyModel.class:
package com.sourcedcode.core.models;

import com.adobe.cq.sightly.SightlyWCMMode;
import com.adobe.cq.sightly.WCMScriptHelper;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.components.Component;
import com.day.cq.wcm.api.components.ComponentContext;
import com.day.cq.wcm.api.components.EditContext;
import com.day.cq.wcm.api.designer.Design;
import com.day.cq.wcm.api.designer.Designer;
import com.day.cq.wcm.api.designer.Style;
import org.apache.log4j.Logger;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.*;
import org.apache.sling.settings.SlingSettingsService;
import org.apache.sling.xss.XSSAPI;

import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.List;

@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MyModel {

@ScriptVariable
private Component component;

@ScriptVariable
private ComponentContext componentContext;

@ScriptVariable
private Design currentDesign;

@ScriptVariable
private Node currentNode;

@ScriptVariable
private com.day.cq.wcm.api.Page currentPage;

@ScriptVariable
private HttpSession currentSession;

@ScriptVariable
private Style currentStyle;

@ScriptVariable
private Style currentStyleCustomScriptVarName;

@ScriptVariable
private Designer designer;

@ScriptVariable
private EditContext editContext;

@ScriptVariable
private Logger log;

@ScriptVariable
private PrintWriter out;

@ScriptVariable
private PageManager pageManager;

@ScriptVariable
private ValueMap pageProperties;

@ScriptVariable
private BufferedReader reader;

@ScriptVariable
private SlingHttpServletRequest request;

@ScriptVariable
private ResourceResolver resolver;

@ScriptVariable
private Resource resource;

@ScriptVariable
private Design resourceDesign;

@ScriptVariable
private Page resourcePage;

@ScriptVariable
private SlingHttpServletResponse response;

@ScriptVariable
private SlingScriptHelper sling;

@ScriptVariable
private WCMScriptHelper slyWcmHelper;

@ScriptVariable
private SightlyWCMMode wcmmode;

@ScriptVariable
private XSSAPI xssAPI;

@ValueMapValue
private String linkPath;

@ValueMapValue
private String homePagePath;

@ChildResource
private List<Resource> navLinks;

@RequestAttribute
private String socialParam;

@OSGiService
private SlingSettingsService slingSettingsService;

@Self
private Node node;

@SlingObject
private SlingHttpServletRequest slingHttpServletRequest;

@SlingObject
private SlingHttpServletResponse slingHttpServletResponse;

@SlingObject
private Resource currentResource;

@SlingObject
private ResourceResolver resourceResolver;

@PostConstruct
protected void initModel() {
// logic goes here
}
}

2. Sling Model Constructor Injection Example:
Let’s convert the field injection example to use constructor injection from the above example.

This example below shows a Sling Model which injects 35 different AEM objects with Constructor Injection to be available for the adapted object. Once the Sling Model has been adapted, the adapted object does not store injection references. The result of the adapted object has a smaller memory byte size.

The name of a constructor argument parameter cannot be detected via the Java Reflection API, so the @Named annotation is mandatory for injectors that require a name for resolving the injection.

MyModelConstructor.class:
package com.sourcedcode.core.models;

import com.adobe.cq.sightly.SightlyWCMMode;
import com.adobe.cq.sightly.WCMScriptHelper;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.components.Component;
import com.day.cq.wcm.api.components.ComponentContext;
import com.day.cq.wcm.api.components.EditContext;
import com.day.cq.wcm.api.designer.Design;
import com.day.cq.wcm.api.designer.Designer;
import com.day.cq.wcm.api.designer.Style;
import org.apache.log4j.Logger;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.*;
import org.apache.sling.settings.SlingSettingsService;
import org.apache.sling.xss.XSSAPI;

import javax.inject.Inject;
import javax.inject.Named;
import javax.jcr.Node;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.List;

@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MyModelConstructor implements Serializable {

@Inject
public MyModelConstructor(
@ScriptVariable @Named("component") final Component component,
@ScriptVariable @Named("componentContext") final ComponentContext componentContext,
@ScriptVariable @Named("currentDesign") final Design currentDesign,
@ScriptVariable @Named("currentNode") final Node currentNode,
@ScriptVariable @Named("currentPage") final com.day.cq.wcm.api.Page currentPage,
@ScriptVariable @Named("currentSession") final HttpSession currentSession,
@ScriptVariable @Named("currentStyle") final Style currentStyle,
@ScriptVariable @Named("currentStyle") final Style currentStyleCustomScriptVarName,
@ScriptVariable @Named("designer") final Designer designer,
@ScriptVariable @Named("editContext") final EditContext editContext,
@ScriptVariable @Named("log") final Logger log,
@ScriptVariable @Named("out") final PrintWriter out,
@ScriptVariable @Named("pageManager") final PageManager pageManager,
@ScriptVariable @Named("pageProperties") final ValueMap pageProperties,
@ScriptVariable @Named("reader") final BufferedReader reader,
@ScriptVariable @Named("request") final SlingHttpServletRequest request,
@ScriptVariable @Named("resolver") final ResourceResolver resolver,
@ScriptVariable @Named("resource") final Resource resource,
@ScriptVariable @Named("resourceDesign") final Design resourceDesign,
@ScriptVariable @Named("resourcePage") final Page resourcePage,
@ScriptVariable @Named("response") final SlingHttpServletResponse response,
@ScriptVariable @Named("sling") final SlingScriptHelper sling,
@ScriptVariable @Named("slyWcmHelper") final WCMScriptHelper slyWcmHelper,
@ScriptVariable @Named("wcmmode") final SightlyWCMMode wcmmode,
@ScriptVariable @Named("xssAPI") final XSSAPI xssAPI,
@ValueMapValue @Named("locationsMenusDefaultLinkPath") final String customLocationsMenusDefaultLinkPath,
@ValueMapValue @Named("homePagePath") final String homePagePath,
@ChildResource @Named("navLinks") final List<Resource> navLinks,
@RequestAttribute @Named("socialParam") final String socialParam,
@OSGiService @Named("slingSettingsService") final SlingSettingsService slingSettingsService,
@Self @Named("node") final Node node,
@SlingObject @Named("slingHttpServletRequest") final SlingHttpServletRequest slingHttpServletRequest,
@SlingObject @Named("slingHttpServletResponse") SlingHttpServletResponse slingHttpServletResponse,
@SlingObject @Named("currentResource") final Resource currentResource,
@SlingObject @Named("resourceResolver") final ResourceResolver resourceResolver
) {
// logic goes here
}
}


Note:
Using the constructor injection strategy can also reduce memory consumption of your application.


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.