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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 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 } } |
Using the constructor injection strategy can also reduce memory consumption of your application. Click here to learn about Sling Model Injection vs Constructor Injection Memory Consumption