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:

  1. Does not store the injection references to the adaptable.
  2. Since it does not store injection references to the adapted object, the result of the adapted object has a smaller memory byte size.
  3. 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
    }
}
Note
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

Hello, I am an enthusiastic Adobe Community Advisor and a seasoned Lead AEM Developer. I am currently serving as an AEM Technical Lead at MNPDigital.ca, bringing over a decade of extensive web engineering experience and more than eight years of practical AEM experience to the table. My goal is to give back to the AEM Full Stack Development community by sharing my wealth of knowledge with others. You can connect with me on LinkedIn.

Leave a Reply

Your email address will not be published. Required fields are marked *


Back To Top